ukui-system-monitor/0000755000175000017500000000000013764351525013475 5ustar fengfengukui-system-monitor/man/0000755000175000017500000000000013703014441014232 5ustar fengfengukui-system-monitor/man/ukui-system-monitor.10000644000175000017500000000137413703014441020305 0ustar fengfeng.\" Man page for ukui-system-monitor .TH UKUISYSTEMMONITOR 1 "17 December 2019" "UKUI Desktop Environment" .\" Please adjust this date when revising the manpage. .\" .SH "NAME" ukui-system-monitor \- The tool for the UKUI Desktop Environment .SH "SYNOPSIS" .B ukui-system-monitor .SH "DESCRIPTION" The \fBukui-system-monitor\fR program is a part of the ukui-system-monitor, it provides users with graphical interface tools. .PP This manual page documents the \fBukui-system-monitor\fR command. .P .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: https://github.com/ukui/ukui-system-monitor/issues .SH "AUTHORS" .SS This Man Page has been written for the UKUI Desktop Environment by: tangguang (2020) .SH "SEE ALSO" ukui-system-monitor/ukui-system-monitor.desktop0000644000175000017500000000067213746753570021067 0ustar fengfeng[Desktop Entry] Name=Kylin System Monitor Name[zh_CN]=系统监视器 Name[tr_TR]=Kylin Sistem İzleyici GenericName=Kylin System Monitor GenericName[zh_CN]=系统监视器 Comment=Kylin System Monitor Comment[zh_CN]=系统监视器 Comment[tr_TR]=Kylin Sistem İzleyici Keywords=guide; Exec=/usr/bin/ukui-system-monitor Icon=ukui-system-monitor Terminal=false Type=Application NoDisplay=false Categories=System;Utility; StartupNotify=false ukui-system-monitor/shell/0000755000175000017500000000000013764070001014567 5ustar fengfengukui-system-monitor/shell/macro.h0000644000175000017500000000341013764070001016037 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QWER_H #define QWER_H /** *DBus */ #define KYLIN_USER_GUIDE_PATH "/" #define KYLIN_USER_GUIDE_SERVICE "com.kylinUserGuide.hotel" #define KYLIN_USER_GUIDE_INTERFACE "com.guide.hotel" /** * QT主题 */ #define THEME_QT_SCHEMA "org.ukui.style" #define MODE_QT_KEY "style-name" #define FONT_SIZE "system-font-size" #define THEME_QT_TRANS "org.ukui.control-center.personalise" /* QT图标主题 */ #define ICON_QT_KEY "icon-theme-name" /* * about the size of every single control */ #define NORMALHEIGHT 30 #define SPECIALWIDTH 200 #define NORMALWIDTH 100 #define MAINWINDOWHEIGHT 590 #define MAINWINDOWWIDTH 760 #define SEARCHBUTTON 16 #define DEFAULT_FONT_SIZE 11 #define SERVICE_NAME_SIZE 64 #define UKUI_SYSTEM_MONITOR_PATH "/" #define UKUI_SYSTEM_MONITOR_SERVICE "com.ukuisystemmonitor.hotel" #define UKUI_SYSTEM_MONITOR_INTERFACE "com.systemmonitor.hotel" #define PADDING 1.5 #define POINTSPACE 10 enum SIGTYPE { REDTYPE = 0, PURPLETYPE, GREENTYPE, BLUETYPE, YELLOWTYPE }; #endif ukui-system-monitor/COPYING0000644000175000017500000010451513746753504014541 0ustar fengfeng GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ukui-system-monitor/ukui-system-monitor.pro0000644000175000017500000000007513703014441020167 0ustar fengfengTEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ src \ ukui-system-monitor/component/0000755000175000017500000000000013746753504015502 5ustar fengfengukui-system-monitor/component/utils.h0000644000175000017500000000424213746753504017015 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UTILS_H #define UTILS_H #include #define ITEMHEIGHT 30 #define ITEMHSPACE 10 #define ITEMVSPACE 5 #define PAGESPACE 20 #define ITEMWIDTH 650 #define SHADOW_LEFT_TOP_PADDING 2 #define SHADOW_RIGHT_BOTTOM_PADDING 4 #define MAIN_WINDOW_WIDTH 900 #define MAIN_WINDOW_HEIGHT 600 #define TITLE_BAR_HEIGHT 39 #define ITEM_LEFT_RIGHT_PADDING 5 //const int windowShadowPadding = 10; //#define VERSION "2.4.1" const QString UKUI_COMPANY_SETTING = "ukui/ukui-system-monitor"; const QString UKUI_SETTING_FILE_NAME_SETTING = "ukui-system-monitor"; enum CleanerModuleID { CacheApt = 0, CacheSoftware, CacheThumbnail, CacheFirefox, CacheChromium, CookieFirefox, CookieChromium, TraceX11, InvalidID, }; enum CleanerCategoryID { CacheCategory = 0, CookieCategory, TraceCategory, InvalidCategory, }; typedef enum{ YOUKER_EN, YOUKER_ZH_CN, YOUKER_ES, } LANGUAGE; typedef enum{ CACHE, PACAKAGE, COOKIES, BROWSER, TRACE, BIGFILE, } CLEANERTAB; struct AutoData { QString appPath; QString appName; QString appComment; QString iconName; QString appStatus; }; typedef enum{ BUTTON_ENTER, BUTTON_LEAVE, BUTTON_PRESSED, BUTTON_DISABLE, BUTTON_FIRST, BUTTON_SCALED, }BUTTONSTATUS; typedef enum{ HOMEPAGE, CLEANPAGE, INFOPAGE, SETTINGPAGE, BOXPAGE, }PAGESTATUS; #endif // UTILS_H ukui-system-monitor/component/mytitlebar.h0000644000175000017500000000277213746753504020037 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYTITLEBAR_H #define MYTITLEBAR_H #include class QHBoxLayout; class MyTristateButton; class MyTitleBar : public QFrame { Q_OBJECT public: MyTitleBar(const QString &title = "", bool needMin = false, QWidget *parent = 0); ~MyTitleBar(); void setLeftContent(QWidget *content); void setMiddleContent(QWidget *content); void initLeftContent(); void initMiddleContent(); void initRightContent(); void initWidgets(); signals: void minSignal(); void closeSignal(); private: QString m_title; bool m_needMin; QHBoxLayout *m_layout = nullptr; QHBoxLayout *m_lLayout = nullptr; QHBoxLayout *m_mLayout = nullptr; QHBoxLayout *m_rLayout = nullptr; }; #endif // MYTITLEBAR_H ukui-system-monitor/component/mytitlebar.cpp0000644000175000017500000001046313746753504020366 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mytitlebar.h" #include "utils.h" #include "../widgets/mytristatebutton.h" #include #include #include #include MyTitleBar::MyTitleBar(const QString &title, bool needMin, QWidget *parent) :QFrame(parent) , m_title(title) , m_needMin(needMin) { this->setWindowFlags(Qt::FramelessWindowHint);//this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint | Qt::WindowCloseButtonHint); // this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);//Attention: Qt::WindowCloseButtonHint make showMinimized() valid // this->setMouseTracking(true); this->setFixedHeight(TITLE_BAR_HEIGHT); this->setAutoFillBackground(true); // this->setAttribute(Qt::WA_TranslucentBackground); QPalette palette; palette.setColor(QPalette::Background, QColor("#0d87ca")); this->setPalette(palette); initWidgets(); } MyTitleBar::~MyTitleBar() { QLayoutItem *child; while ((child = m_lLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_mLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_rLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } delete m_layout; } void MyTitleBar::setLeftContent(QWidget *content) { QLayoutItem *child; while ((child = m_lLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } m_lLayout->addWidget(content); } void MyTitleBar::setMiddleContent(QWidget *content) { QLayoutItem *child; while ((child = m_mLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } m_mLayout->addWidget(content); } void MyTitleBar::initLeftContent() { QWidget *w = new QWidget; m_lLayout = new QHBoxLayout(w); m_lLayout->setContentsMargins(6, 0, 0, 0); m_lLayout->setSpacing(0); QLabel *titleLabel = new QLabel; titleLabel->setStyleSheet("QLabel{background-color:transparent;color:#ffffff; font-size:12px;}"); titleLabel->setText(m_title); m_lLayout->addWidget(titleLabel); m_layout->addWidget(w, 1, Qt::AlignLeft); } void MyTitleBar::initMiddleContent() { QWidget *w = new QWidget; w->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_mLayout = new QHBoxLayout(w); m_mLayout->setContentsMargins(0, 0, 0, 0); m_mLayout->setSpacing(0); m_layout->addWidget(w); } void MyTitleBar::initRightContent() { QWidget *w = new QWidget; m_rLayout = new QHBoxLayout(w); m_rLayout->setContentsMargins(0, 0, 0, 0); m_rLayout->setSpacing(0); m_layout->addWidget(w, 1, Qt::AlignRight); if (m_needMin) { MyTristateButton *minBtn = new MyTristateButton; minBtn->setObjectName("MinButton"); connect(minBtn, SIGNAL(clicked()), this, SIGNAL(minSignal())); m_rLayout->addWidget(minBtn); } MyTristateButton *closeBtn = new MyTristateButton; closeBtn->setObjectName("CloseButton"); connect(closeBtn, SIGNAL(clicked()), this, SIGNAL(closeSignal())); m_rLayout->addWidget(closeBtn); } void MyTitleBar::initWidgets() { m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); initLeftContent(); initMiddleContent(); initRightContent(); } ukui-system-monitor/src/0000755000175000017500000000000013764351367014270 5ustar fengfengukui-system-monitor/src/filesystemlistitem.h0000644000175000017500000000347313746753504020406 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FILESYSTEMLISTITEM_H #define FILESYSTEMLISTITEM_H #include #include #include #include #include "filesystemdata.h" #include "shell/customstyle.h" #include "../shell/macro.h" class FileSystemListItem : public QObject { Q_OBJECT public: FileSystemListItem(FileSystemData *info); ~FileSystemListItem(); bool isSameItem(FileSystemListItem *item); void drawCellBackground(QRect rect, QPainter *painter, int level); void drawBackground(QRect rect, QPainter *painter, int index, bool isSelect, QString currentTheme); void drawForeground(QRect rect, QPainter *painter, int column, int index, bool isSelect, bool isSeparator); QString getDeviceName() const; QString getDirectory() const; void initThemeMode(); void initFontSize(); private: FileSystemData *m_data; int iconSize; int padding; int textPadding; int fontSize; QGSettings * qtSettings; QGSettings *fontSettings; QString currentThemeMode; }; #endif // FILESYSTEMLISTITEM_H ukui-system-monitor/src/systemmonitor.json0000644000175000017500000000000313703014441020066 0ustar fengfeng{} ukui-system-monitor/src/systemmonitor.cpp0000644000175000017500000004450613764070001017720 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "systemmonitor.h" #include "../shell/macro.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); void SystemMonitor::sltMessageReceived(const QString &msg) { Qt::WindowFlags flags = windowFlags(); flags |= Qt::WindowStaysOnTopHint; setWindowFlags(flags); show(); flags &= ~Qt::WindowStaysOnTopHint; setWindowFlags(flags); showNormal(); } SystemMonitor::SystemMonitor(QWidget *parent) : QFrame(parent) , mousePressed(false) , opacitySettings(nullptr) , qtSettings(nullptr) { // this->setStyleSheet("QFrame{border: 1px solid #121212;border-radius:1px;background-color:#1f1f1f;}"); // this->setAttribute(Qt::WA_DeleteOnClose); // this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint | Qt::WindowCloseButtonHint);//去掉边框 this->setObjectName("SystemMonitor"); this->setWindowFlags(Qt::FramelessWindowHint); //set for no windowhint this->setAttribute(Qt::WA_TranslucentBackground);//背景透明 this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { opacitySettings = new QGSettings(idtrans); } getOsRelease(); this->setAutoFillBackground(true); // this->setMouseTracking(true); // installEventFilter(this); this->setWindowTitle(tr("Kylin System Monitor")); this->setWindowIcon(QIcon::fromTheme("ukui-system-monitor")); //control show img in panel //this->setFixedSize(900, 600); this->resize(MAINWINDOWWIDTH,MAINWINDOWHEIGHT); setMinimumSize(640, 480); //set the minimum size of the mainwindow proSettings = new QSettings(UKUI_COMPANY_SETTING, UKUI_SETTING_FILE_NAME_SETTING); proSettings->setIniCodec("UTF-8"); this->initTitleWidget(); this->initPanelStack(); this->initConnections(); initThemeMode(); connect(m_titleWidget,SIGNAL(changeProcessItemDialog(int)),process_dialog,SLOT(onActiveWhoseProcess(int))); //配置文件中为whoseprocess赋值 getTransparentData(); this->moveCenter(); qDebug()<<"--+--"<get(MODE_QT_KEY).toString(); } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); } void SystemMonitor::getTransparentData() { if (!opacitySettings) { m_transparency = 0.9; return; } connect(opacitySettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "transparency") { QStringList keys = opacitySettings->keys(); if (keys.contains("transparency")) { m_transparency = opacitySettings->get("transparency").toString().toDouble(); } } repaint(); }); QStringList keys = opacitySettings->keys(); if(keys.contains("transparency")) { m_transparency = opacitySettings->get("transparency").toString().toDouble(); } } SystemMonitor::~SystemMonitor() { if (m_sysMonitorStack) { foreach (QObject *child, m_sysMonitorStack->children()) { QWidget *widget = static_cast(child); widget->deleteLater(); } delete m_sysMonitorStack; } if (m_titleWidget) { delete m_titleWidget; m_titleWidget = nullptr; } if (process_dialog) { //delete process_dialog; process_dialog = nullptr; } if (resources_dialog) { //resources_dialog->deleteLater() ; resources_dialog = nullptr; qDebug() <<"resources_dialog"<<"------------------"; } if (filesystem_dialog) { //delete filesystem_dialog; filesystem_dialog = nullptr; } if (proSettings != NULL) { delete proSettings; proSettings = NULL; } if (opacitySettings != NULL){ delete opacitySettings; opacitySettings = NULL; } } void SystemMonitor::paintEvent(QPaintEvent *event) { QPainter p(this); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) p.setOpacity(0.95); #else p.setOpacity(m_transparency); #endif Q_UNUSED(event); p.setRenderHint(QPainter::Antialiasing); QPainterPath rectPath; rectPath.addRoundedRect(this->rect().adjusted(1, 1, -1, -1), 6, 6); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.setPen(Qt::transparent); pixmapPainter.setBrush(Qt::black); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 QImage img = pixmap.toImage(); qt_blurImage(img, 5, false, false); // 挖掉中心 pixmap = QPixmap::fromImage(img); QPainter pixmapPainter2(&pixmap); pixmapPainter2.setRenderHint(QPainter::Antialiasing); pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear); pixmapPainter2.setPen(Qt::transparent); pixmapPainter2.setBrush(Qt::transparent); pixmapPainter2.drawPath(rectPath); // 绘制阴影 p.drawPixmap(this->rect(), pixmap, pixmap.rect()); // 绘制一个背景 p.save(); p.fillPath(rectPath,palette().color(QPalette::Base)); p.restore(); QStyleOption opt; opt.init(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); KWindowEffects::enableBlurBehind(this->winId(),true,QRegion(rectPath.toFillPolygon().toPolygon())); } void SystemMonitor::resizeEvent(QResizeEvent *e) { if (m_titleWidget) { m_titleWidget->resize(width() - 2, MONITOR_TITLE_WIDGET_HEIGHT); } if (m_sysMonitorStack) { m_sysMonitorStack->resize(width() - 2, this->height() - MONITOR_TITLE_WIDGET_HEIGHT - 2); m_sysMonitorStack->move(1, MONITOR_TITLE_WIDGET_HEIGHT + 1); } qDebug()<<"m_titleWid.x"<geometry(); } void SystemMonitor::recordProcessVisibleColumn(int, bool, QList columnVisible) { QList m_visibleColumns; m_visibleColumns << "name"; if (columnVisible[1]) { m_visibleColumns << "user"; } // if (columnVisible[2]) { // m_visibleColumns << "status"; // } if (columnVisible[2]) { m_visibleColumns << "disk"; } if (columnVisible[3]) { m_visibleColumns << "cpu"; } if (columnVisible[4]) { m_visibleColumns << "pid"; } if (columnVisible[5]) { m_visibleColumns << "flownetpersec"; } if (columnVisible[6]) { m_visibleColumns << "memory"; } if (columnVisible[7]) { m_visibleColumns << "priority"; } QString displayedColumns = ""; for (int i = 0; i < m_visibleColumns.length(); i++) { if (i != m_visibleColumns.length() - 1) { displayedColumns += QString("%1,").arg(m_visibleColumns[i]); } else { displayedColumns += m_visibleColumns[i]; } } proSettings->beginGroup("PROCESS"); proSettings->setValue("DisplayedColumns", displayedColumns); proSettings->endGroup(); proSettings->sync(); } void SystemMonitor::recordSortStatus(int index, bool isSort) { QList columnNames = { "name", "user", "disk", "cpu", "pid", "flownetpersec", "memory", "priority"}; proSettings->beginGroup("PROCESS"); proSettings->setValue("CurrentSortColumn", columnNames[index]); proSettings->setValue("IsSort", isSort); proSettings->endGroup(); proSettings->sync(); } void SystemMonitor::recordFileSysVisibleColumn(int, bool, QList columnVisible) { QList m_visibleColumns; m_visibleColumns << "device"; if (columnVisible[1]) { m_visibleColumns << "directory"; } if (columnVisible[2]) { m_visibleColumns << "type"; } if (columnVisible[3]) { m_visibleColumns << "total"; } if (columnVisible[4]) { m_visibleColumns << "free"; } if (columnVisible[5]) { m_visibleColumns << "available"; } if (columnVisible[6]) { m_visibleColumns << "used"; } QString displayedColumns = ""; for (int i = 0; i < m_visibleColumns.length(); i++) { if (i != m_visibleColumns.length() - 1) { displayedColumns += QString("%1,").arg(m_visibleColumns[i]); } else { displayedColumns += m_visibleColumns[i]; } } proSettings->beginGroup("FileSystem"); proSettings->setValue("DisplayedColumns", displayedColumns); proSettings->endGroup(); proSettings->sync(); } void SystemMonitor::initPanelStack() { m_sysMonitorStack = new QStackedWidget(this); m_sysMonitorStack->resize(width() - 2, this->height() - TITLE_WIDGET_HEIGHT); // m_sysMonitorStack->move(1, TITLE_WIDGET_HEIGHT); m_sysMonitorStack->installEventFilter(this); process_dialog = new ProcessDialog(getReadyDisplayProcessColumns(), getCurrentSortColumnIndex(), isSortOrNot(), proSettings); process_dialog->getProcessView()->installEventFilter(this); connect(process_dialog, &ProcessDialog::changeColumnVisible, this, &SystemMonitor::recordProcessVisibleColumn); connect(process_dialog, &ProcessDialog::changeSortStatus, this, &SystemMonitor::recordSortStatus); resources_dialog = new NewResouresDialog; filesystem_dialog = new FileSystemDialog(getReadyDisplayFileSysColumns(), proSettings); filesystem_dialog->getFileSysView()->installEventFilter(this); connect(filesystem_dialog, SIGNAL(changeColumnVisible(int,bool,QList)), this, SLOT(recordFileSysVisibleColumn(int,bool,QList))); m_sysMonitorStack->addWidget(process_dialog); m_sysMonitorStack->addWidget(resources_dialog); m_sysMonitorStack->addWidget(filesystem_dialog); m_sysMonitorStack->setCurrentWidget(process_dialog); } void SystemMonitor::initTitleWidget() { m_titleWidget = new MonitorTitleWidget(proSettings, this); m_titleWidget->resize(width() - 2, MONITOR_TITLE_WIDGET_HEIGHT); m_titleWidget->move(1, 1); connect(m_titleWidget,SIGNAL(maximizeWindow()),this,SLOT(onMaximizeWindow())); connect(m_titleWidget,SIGNAL(minimizeWindow()),this,SLOT(onMinimizeWindow())); } void SystemMonitor::onMaximizeWindow() { if (this->isMaximized()) { this->showNormal(); } else { this->showMaximized(); } } void SystemMonitor::onMinimizeWindow() { this->showMinimized(); } void SystemMonitor::initConnections() { connect(m_titleWidget, SIGNAL(changePage(int)), this, SLOT(onChangePage(int))); connect(m_titleWidget, SIGNAL(canelSearchEditFocus()), process_dialog, SLOT(focusProcessView())); connect(m_titleWidget, SIGNAL(searchSignal(QString)), process_dialog, SLOT(onSearch(QString)), Qt::QueuedConnection); } void SystemMonitor::onChangePage(int index) { if (m_sysMonitorStack) { m_sysMonitorStack->setCurrentIndex(index); } } int SystemMonitor::getCurrentSortColumnIndex() { proSettings->beginGroup("PROCESS"); QString currentSortColumn = proSettings->value("CurrentSortColumn").toString(); proSettings->endGroup(); QList columnNames = {"name", "user", "disk", "cpu", "pid", "flownetpersec", "memory", "priority"}; return columnNames.indexOf(currentSortColumn); } bool SystemMonitor::isSortOrNot() { proSettings->beginGroup("PROCESS"); bool value = proSettings->value("IsSort", true).toBool(); proSettings->endGroup(); return value; } QList SystemMonitor::getReadyDisplayProcessColumns() { proSettings->beginGroup("PROCESS"); QString displayedColumns = proSettings->value("DisplayedColumns", "name,user,disk,cpu,pid,flownetpersec,memory,priority").toString(); proSettings->endGroup(); if (displayedColumns.isEmpty()) { proSettings->beginGroup("PROCESS"); displayedColumns = "name,user,disk,cpu,pid,flownetpersec,memory,priority"; proSettings->setValue("DisplayedColumns", displayedColumns); proSettings->endGroup(); proSettings->sync(); } QList m_shows; m_shows << displayedColumns.contains("name"); m_shows << displayedColumns.contains("user"); m_shows << displayedColumns.contains("disk"); m_shows << displayedColumns.contains("cpu"); m_shows << displayedColumns.contains("pid"); m_shows << displayedColumns.contains("flownetpersec"); m_shows << displayedColumns.contains("memory"); m_shows << displayedColumns.contains("priority"); return m_shows; } QList SystemMonitor::getReadyDisplayFileSysColumns() { proSettings->beginGroup("FileSystem"); QString displayedColumns = proSettings->value("DisplayedColumns", "device,directory,type,total,free,available,used").toString(); proSettings->endGroup(); if (displayedColumns.isEmpty()) { proSettings->beginGroup("FileSystem"); displayedColumns = "device,directory,type,total,free,available,used"; proSettings->setValue("DisplayedColumns", displayedColumns); proSettings->endGroup(); proSettings->sync(); } QList m_shows; m_shows << displayedColumns.contains("device"); m_shows << displayedColumns.contains("directory"); m_shows << displayedColumns.contains("type"); m_shows << displayedColumns.contains("total"); m_shows << displayedColumns.contains("free"); m_shows << displayedColumns.contains("available"); m_shows << displayedColumns.contains("used"); return m_shows; } void SystemMonitor::moveCenter() { QPoint pos = QCursor::pos(); QRect primaryGeometry; for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { primaryGeometry = screen->geometry(); } } if (primaryGeometry.isEmpty()) { primaryGeometry = qApp->primaryScreen()->geometry(); } this->move(primaryGeometry.x() + (primaryGeometry.width() - this->width())/2, primaryGeometry.y() + (primaryGeometry.height() - this->height())/2); } void SystemMonitor::getOsRelease() { QFile file("/etc/lsb-release"); if (!file.open(QIODevice::ReadOnly)) qDebug() << "Read file Failed."; while (!file.atEnd()) { QByteArray line = file.readLine(); QString str(line); if (str.contains("DISTRIB_ID")){ version=str.remove("DISTRIB_ID="); version=str.remove("\n"); } } } void SystemMonitor::closeEvent(QCloseEvent *event) { event->accept(); } /*void SystemMonitor::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //绘制背景色 // QPainterPath path; // path.addRect(QRectF(rect())); // painter.setOpacity(1); // painter.fillPath(path, QColor("#FFFFFF")); painter.setPen(QPen(QColor("#0d87ca"), 0));//边框颜色 #3f96e4 painter.setBrush(QColor("#e9eef0"));//背景色 painter.setRenderHint(QPainter::Antialiasing, true); painter.setOpacity(1); QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边 painter.drawRoundedRect(r, 4, 4); QFrame::paintEvent(event); }*/ void SystemMonitor::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->dragPosition = event->globalPos() - frameGeometry().topLeft(); this->mousePressed = true; } QFrame::mousePressEvent(event); } void SystemMonitor::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->mousePressed = false; } QFrame::mouseReleaseEvent(event); } void SystemMonitor::mouseMoveEvent(QMouseEvent *event) { if (this->mousePressed) { move(event->globalPos() - this->dragPosition); } QFrame::mouseMoveEvent(event); } void SystemMonitor::keyPressEvent(QKeyEvent *event) { if(version != "Ubuntu") { if(event->key() == Qt::Key_F1) { if(!daemonIsNotRunning()) { showGuide(qAppName()); } } } } int SystemMonitor::daemonIsNotRunning() { QString service_name = "com.kylinUserGuide.hotel_" + QString::number(getuid()); QDBusConnection conn = QDBusConnection::sessionBus(); if (!conn.isConnected()) return 0; QDBusReply reply = conn.interface()->call("GetNameOwner", service_name); qDebug()<<"reply name"<call(QStringLiteral("showGuide"),"kylin-system-monitor"); } ukui-system-monitor/src/propertiesdialog.cpp0000644000175000017500000003550713764070001020341 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "propertiesdialog.h" #include "processworker.h" #include "../widgets/mytristatebutton.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include const int spacing = 8; PropertiesDialog::PropertiesDialog(QWidget *parent, pid_t processId) : QDialog(parent) , mousePressed(false) { this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint/* | Qt::WindowCloseButtonHint*/| Qt::WindowStaysOnTopHint); // this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);//Attention: Qt::WindowCloseButtonHint make showMinimized() valid this->setAttribute(Qt::WA_TranslucentBackground); this->setAttribute(Qt::WA_Resized, false); // this->setMaximumSize(480, 600); // this->setMinimumWidth(320); this->setFixedWidth(380); pid = processId; m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 5); m_topLayout = new QHBoxLayout; m_topLeftLayout = new QHBoxLayout; m_topLeftLayout->setContentsMargins(20, 20, 0, 0); m_topLeftLayout->setSpacing(10); m_topRightLayout = new QHBoxLayout; m_topRightLayout->setMargin(0); m_topRightLayout->setSpacing(5); m_topLayout->addLayout(m_topLeftLayout); m_topLayout->addStretch(); m_topLayout->addLayout(m_topRightLayout); /*userLayout = new QHBoxLayout(); userLayout->setContentsMargins(0, 0, 0, 0); nameLayout = new QHBoxLayout(); nameLayout->setContentsMargins(0, 0, 0, 0); cmdlineLayout = new QHBoxLayout(); cmdlineLayout->setContentsMargins(0, 0, 0, 0); cpuDurationLayout = new QHBoxLayout(); cpuDurationLayout->setContentsMargins(0, 0, 0, 0); startTimeLayout = new QHBoxLayout(); startTimeLayout->setContentsMargins(0, 0, 0, 0);*/ m_logoLabel = new QLabel(); // m_logoLabel->setStyleSheet("QLabel{background:#CC00FF;border:none;}"); m_logoLabel->setFixedSize(44, 58); m_logoLabel->setContentsMargins(0, 0, 0, 0); m_logoLabel->setPixmap(QPixmap(":/res/sub_logo.png")); closeButton = new QPushButton(this); closeButton->setProperty("isWindowButton", 0x2); closeButton->setProperty("useIconHighlightEffect", 0x8); closeButton->setObjectName("CloseButton"); closeButton->setIcon(QIcon::fromTheme("window-close-symbolic")); closeButton->setFlat(true); // connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); connect(closeButton, &QPushButton::clicked, this, [=]() { this->deleteLater(); this->close(); }); closeButton->setProperty("isWindowButton", 0x2); closeButton->setProperty("useIconHighlightEffect", 0x8); // connect(closeButton, &MyTristateButton::clicked, this, [=] { // this->close(); // }); m_iconLabel = new QLabel(); // m_iconLabel->setStyleSheet("QLabel{background:transparent;border:none;}"); m_iconLabel->setFixedSize(48, 48); m_iconLabel->setContentsMargins(0, 0, 0, 0); m_titleLabel = new QLabel(); // m_titleLabel->setStyleSheet("QLabel{background-color:transparent;font-size:18px;color:#000000;}"); m_titleLabel->setFixedWidth(230); m_titleLabel->setWordWrap(true); m_topLeftLayout->addWidget(m_iconLabel, 0, Qt::AlignLeft | Qt::AlignVCenter); m_topLeftLayout->addWidget(m_titleLabel, 0, Qt::AlignLeft | Qt::AlignVCenter); m_topRightLayout->addWidget(m_logoLabel, 0, Qt::AlignTop | Qt::AlignRight); m_topRightLayout->addWidget(closeButton, 0, Qt::AlignTop | Qt::AlignRight); m_topRightLayout->setContentsMargins(0,8,8,0); QLabel *topSplit = new QLabel(); // topSplit->setStyleSheet("QLabel{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #f1f1f1, stop:1 #e0e0e0);}"); // topSplit->setStyleSheet("QLabel{background: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0 #f1f1f1, stop:1 #e0e0e0);}"); topSplit->setFixedSize(320, 1); QLabel *bottomSplit = new QLabel(); // bottomSplit->setStyleSheet("QLabel{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #f1f1f1, stop:1 #e0e0e0);}"); // bottomSplit->setStyleSheet("QLabel{background: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0 #f1f1f1, stop:1 #e0e0e0);}"); bottomSplit->setFixedSize(320, 1); m_infoFrame = new QFrame; m_infoFrame->setMaximumWidth(320); m_infoFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_bottomLayout = new QHBoxLayout; m_bottomLayout->setContentsMargins(0,0,20,0); m_bottomLayout->setSpacing(0); m_okBtn = new QPushButton; m_okBtn->setFixedSize(91, 25); m_okBtn->setObjectName("blackButton"); m_okBtn->setFocusPolicy(Qt::NoFocus); m_okBtn->setText(tr("OK")); connect(m_okBtn, &QPushButton::clicked, this, [=] { this->close(); }); m_bottomLayout->addWidget(m_okBtn, 0, Qt::AlignBottom | Qt::AlignRight); m_layout->addLayout(m_topLayout); m_layout->addSpacing(10); m_layout->addWidget(topSplit, 0, Qt::AlignCenter); m_layout->addSpacing(10); m_layout->addWidget(m_infoFrame, 0, Qt::AlignCenter); m_layout->addSpacing(5); m_layout->addWidget(bottomSplit, 0, Qt::AlignCenter); m_layout->addSpacing(5); m_layout->addLayout(m_bottomLayout); m_layout->addSpacing(10); m_layout->addStretch(); QGridLayout *infoGrid = new QGridLayout(m_infoFrame); infoGrid->setMargin(0); infoGrid->setHorizontalSpacing(spacing); infoGrid->setVerticalSpacing(spacing); infoGrid->setColumnStretch(0, 10); infoGrid->setColumnStretch(1, 100); QStringList titleList; titleList << QObject::tr("User name:") << QObject::tr("Process name:") << QObject::tr("Command line:") << QObject::tr("CPU Time:") << QObject::tr("Started Time:"); // titleList << QObject::tr("User name:") << QObject::tr("Process name:") << QObject::tr("flownet per second:") << QObject::tr("CPU Time:") << QObject::tr("Started Time:"); for (int i = 0; i < titleList.length(); ++i) { QLabel *titleLabel = new QLabel(titleList.value(i)); // titleLabel->setStyleSheet("QLabel{background-color:transparent;font-size:12px;color:#999999;}"); titleLabel->setMinimumHeight(20); QLabel *infoLabel = new QLabel(); // infoLabel->setStyleSheet("QLabel{background-color:transparent;font-size:12px;color:#000000;}"); infoLabel->setWordWrap(true); infoLabel->setMinimumHeight(28); infoLabel->setMinimumWidth(220); infoLabel->setMaximumWidth(240); infoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); infoLabel->adjustSize(); m_labelList << infoLabel; infoGrid->addWidget(titleLabel); infoGrid->addWidget(infoLabel); // QLineEdit *line = new QLineEdit(); // infoGrid->addWidget(line); } this->moveToCenter(); this->initProcproperties(); timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(refreshProcproperties())); timer->start(3000); } PropertiesDialog::~PropertiesDialog() { if (timer != NULL) { disconnect(timer,SIGNAL(timeout()),this,SLOT(refreshProcproperties())); if(timer->isActive()) { timer->stop(); } delete timer; timer = NULL; } delete closeButton; delete m_iconLabel; delete m_titleLabel; delete m_okBtn; QLayoutItem *child; while ((child = m_topLeftLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_topRightLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_topLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_bottomLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } m_labelList.clear(); delete m_infoFrame; /*delete userTitleLabel; delete userLabel; delete nameTitleLabel; delete m_appNameLabel; delete cmdlineTitleLabel; delete cpuDurationLabel; delete cpuDurationTitleLabel; delete startTimeLabel; delete startTimeTitleLabel; delete cmdlineLabel; delete userLayout; delete nameLayout; delete cmdlineLayout; delete cpuDurationLayout; delete startTimeLayout;*/ delete m_layout; } void PropertiesDialog::updateLabelFrameHeight() { int labelTotalHeight = 0; foreach (QLabel *label, m_labelList) { label->adjustSize(); labelTotalHeight += label->size().height() + spacing; } m_infoFrame->setFixedHeight(labelTotalHeight); m_infoFrame->adjustSize(); this->adjustSize(); } void PropertiesDialog::initProcproperties() { ProcessWorker *info; info = ProcessWorker::find(pid); if (info) { QString username = QString::fromStdString(info->user); // long nice = info->nice; QString name = QString::fromStdString(info->name); // QString status = formatProcessState(info->status); // uint cpu = info->pcpu; // long memory = info->mem; std::string desktopFile; desktopFile = getDesktopFileAccordProcName(name, ""); QPixmap icon_pixmap; int iconSize = 48 * qApp->devicePixelRatio(); QIcon defaultExecutableIcon = QIcon::fromTheme("application-x-executable");//gnome-mine-application-x-executable if (defaultExecutableIcon.isNull()) { defaultExecutableIcon = QIcon("/usr/share/icons/ukui-icon-theme-default/48x48/mimetypes/application-x-executable.png"); if (defaultExecutableIcon.isNull()) defaultExecutableIcon = QIcon(":/res/autostart-default.png"); } QPixmap defaultPixmap = defaultExecutableIcon.pixmap(iconSize, iconSize); // QPixmap defaultPixmap = QIcon::fromTheme("application-x-executable").pixmap(iconSize, iconSize); if (desktopFile.size() == 0) { icon_pixmap = defaultPixmap; icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); } else { icon_pixmap = getAppIconFromDesktopFile(desktopFile, 48); if (icon_pixmap.isNull()) { icon_pixmap = defaultPixmap; icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); } //QPixmap pixmap = QPixmap::fromImage(img).scaled(iconSize, iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } QString displayName = getDisplayNameAccordProcName(name, desktopFile); m_iconLabel->setPixmap(icon_pixmap); m_titleLabel->setText(displayName); /*userLabel->setText(username); m_appNameLabel->setText(QString(info->name)); cmdlineLabel->setText(QString(info->arguments)); startTimeLabel->setText(QFileInfo(QString("/proc/%1").arg(pid)).created().toString("yyyy-MM-dd hh:mm:ss")); cpuDurationLabel->setText(formatDurationForDisplay(100 * info->cpu_time / info->frequency));*/ QStringList valueList; valueList << username << QString(info->name) << QString(info->arguments) << QFileInfo(QString("/proc/%1").arg(pid)).created().toString("yyyy-MM-dd hh:mm:ss") << formatDurationForDisplay(100 * info->cpu_time / info->frequency); for (int i = 0; i < this->m_labelList.length(); ++i) { this->m_labelList.value(i)->setText(valueList.value(i)); } } this->updateLabelFrameHeight(); } void PropertiesDialog::refreshProcproperties() { ProcessWorker *info; info = ProcessWorker::find(pid); if (info) { for (int i = 0; i < this->m_labelList.length(); ++i) { if (i == 3) this->m_labelList.value(i)->setText(QFileInfo(QString("/proc/%1").arg(pid)).created().toString("yyyy-MM-dd hh:mm:ss")); if (i == 4) this->m_labelList.value(i)->setText(formatDurationForDisplay(100 * info->cpu_time / info->frequency)); } //startTimeLabel->setText(QFileInfo(QString("/proc/%1").arg(pid)).created().toString("yyyy-MM-dd hh:mm:ss")); //cpuDurationLabel->setText(formatDurationForDisplay(100 * info->cpu_time / info->frequency)); } } pid_t PropertiesDialog::getPid() { return pid; } QRect PropertiesDialog::getParentGeometry() const { if (this->parentWidget()) { return this->parentWidget()->window()->geometry(); } else { QPoint pos = QCursor::pos(); for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { return screen->geometry(); } } } return qApp->primaryScreen()->geometry(); } void PropertiesDialog::moveToCenter() { QRect qr = geometry(); qr.moveCenter(this->getParentGeometry().center()); move(qr.topLeft()); } void PropertiesDialog::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->dragPosition = event->globalPos() - frameGeometry().topLeft(); this->mousePressed = true; } QDialog::mousePressEvent(event); } void PropertiesDialog::mouseReleaseEvent(QMouseEvent *event) { this->mousePressed = false; QDialog::mouseReleaseEvent(event); } void PropertiesDialog::mouseMoveEvent(QMouseEvent *event) { if (this->mousePressed) { move(event->globalPos() - this->dragPosition); } QDialog::mouseMoveEvent(event); } void PropertiesDialog::paintEvent(QPaintEvent *event) { QPainter painter(this); //绘制圆角矩形 painter.setPen(QPen(QColor("#808080"), 0) );//边框颜色 #3f96e4 // painter.setPen(Qt::NoPen); painter.setBrush(this->palette().base());//背景色 painter.setRenderHint(QPainter::Antialiasing, true); painter.setOpacity(1); QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边 painter.drawRoundedRect(r, 6, 6); //绘制背景色 // QPainterPath path; // path.addRect(QRectF(rect())); // painter.setOpacity(1); // painter.fillPath(path, QColor("#ffffff")); QDialog::paintEvent(event); } ukui-system-monitor/src/processworker.h0000644000175000017500000000423713746753570017361 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCESSWORKER_H #define PROCESSWORKER_H #include #include #include #include #include using std::string; class ProcessWorker { ProcessWorker& operator=(const ProcessWorker&); ProcessWorker(const ProcessWorker&); typedef std::map UserMap; static UserMap users; public: ProcessWorker(pid_t pid, gint cpus, guint64 cpu_time ,QString flownet_persec); ~ProcessWorker(); typedef std::map List; typedef List::iterator Iterator; static ProcessWorker* find(pid_t pid); static List all; static Iterator begin() { return ProcessWorker::all.begin(); } static Iterator end() { return ProcessWorker::all.end(); } void setProcData(); void set_user(guint uid); std::string lookup_user(guint uid); std::string user; gulong mem; gulong start_time; guint64 cpu_time; QString flownet_persec; QString diskio_persec; int mNumFlownet; int mNumDiskIo; guint status; guint pcpu; gint nice; gchar *tooltip; gchar *name; gchar *arguments; const pid_t pid; guint uid; static std::map cpu_times; gchar *unit; gchar *session; gchar *seat; // gchar *security_context; // gchar *cgroup_name; gint num_cpus; guint64 cpu_total_time; unsigned frequency; }; #endif // PROCESSWORKER_H ukui-system-monitor/src/propertiesdialog.h0000644000175000017500000000531513746753570020023 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROPERTIESSDIALOG_H #define PROPERTIESSDIALOG_H #include #include #include #include #include #include #include class QMouseEvent; class MyTristateButton; //TODO: add timer to refresh class PropertiesDialog : public QDialog { Q_OBJECT public: PropertiesDialog(QWidget *parent = 0, pid_t pid=-1); ~PropertiesDialog(); pid_t getPid(); QRect getParentGeometry() const; void moveToCenter(); void updateLabelFrameHeight(); void initProcproperties(); public slots: void refreshProcproperties(); protected: void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; // void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; private: QPushButton *closeButton = nullptr; QLabel *m_logoLabel = nullptr; /*QHBoxLayout *cmdlineLayout; QHBoxLayout *userLayout; QHBoxLayout *nameLayout; QHBoxLayout *cpuDurationLayout; QHBoxLayout *startTimeLayout; QLabel *cmdlineLabel; QLabel *cmdlineTitleLabel; QLabel *userLabel; QLabel *userTitleLabel; QLabel *m_appNameLabel; QLabel *nameTitleLabel; QLabel *cpuDurationLabel; QLabel *cpuDurationTitleLabel; QLabel *startTimeLabel; QLabel *startTimeTitleLabel;*/ QVBoxLayout *m_layout = nullptr; QHBoxLayout *m_topLayout = nullptr; QHBoxLayout *m_topLeftLayout = nullptr; QHBoxLayout *m_topRightLayout = nullptr; QHBoxLayout *m_bottomLayout = nullptr; QLabel *m_iconLabel = nullptr; QLabel *m_titleLabel = nullptr; QPushButton *m_okBtn = nullptr; pid_t pid; QPoint dragPosition; bool mousePressed; QTimer *timer = nullptr; QFrame *m_infoFrame = nullptr; QList m_labelList; }; #endif // PROPERTIESSDIALOG_H ukui-system-monitor/src/processdata.h0000644000175000017500000000275413746753570016763 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCESSDATA_H #define PROCESSDATA_H #include #include #include #include class ProcData { public: pid_t pid; uint cpu; long m_memory; long m_nice; QString m_flownet; QString m_diskio; int m_numFlowNet; int m_numDiskIo; QPixmap iconPixmap; QString processName; QString displayName; // QString commandLine; QString path; QString user; QString m_status; QString m_session; QString cpu_duration_time; }; typedef QSharedPointer ProcDataPtr; typedef QList ProcDataPtrList; Q_DECLARE_METATYPE(ProcData) Q_DECLARE_METATYPE(ProcDataPtr) Q_DECLARE_METATYPE(ProcDataPtrList) #endif // PROCESSDATA_H ukui-system-monitor/src/systemmonitor.h0000644000175000017500000000607613764070001017365 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SYSTEMMONITOR_H #define SYSTEMMONITOR_H #include "monitortitlewidget.h" #include "processdialog.h" #include "newresource/newresourcesdialog.h" //#include "newresourcesdialog.h" #include "filesystemdialog.h" #include "shell/customstyle.h" #include "../shell/macro.h" #include #include #include #include #include #include #include //#include class SystemMonitor : public QFrame { Q_OBJECT public: SystemMonitor(QWidget *parent = 0); ~SystemMonitor(); void initTitleWidget(); void initPanelStack(); void initConnections(); QList getReadyDisplayProcessColumns(); bool isSortOrNot(); int getCurrentSortColumnIndex(); QList getReadyDisplayFileSysColumns(); void moveCenter(); void initThemeMode(); void getTransparentData(); public slots: void recordProcessVisibleColumn(int, bool, QList columnVisible); void recordSortStatus(int index, bool isSort); void recordFileSysVisibleColumn(int, bool, QList columnVisible); void onChangePage(int index); void onMaximizeWindow(); void onMinimizeWindow(); void sltMessageReceived(const QString &msg); protected: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *); void closeEvent(QCloseEvent *event); void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void keyPressEvent(QKeyEvent *event); private: int daemonIsNotRunning(); void showGuide(QString appName); void getOsRelease(); private: // WId mWindow; QStackedWidget *m_sysMonitorStack = nullptr; MonitorTitleWidget *m_titleWidget = nullptr; // ToolBar *m_toolBar = nullptr; ProcessDialog *process_dialog = nullptr; NewResouresDialog *resources_dialog = nullptr; FileSystemDialog *filesystem_dialog = nullptr; QSettings *proSettings; QPoint dragPosition; bool mousePressed; QGSettings * qtSettings; QString currentThemeMode; QGSettings *fontSettings; float fontSize; QGSettings *opacitySettings; double m_transparency; QString version; }; #endif // SYSTEMMONITOR_H ukui-system-monitor/src/img/0000755000175000017500000000000013746753504015043 5ustar fengfengukui-system-monitor/src/img/all_proc.png0000644000175000017500000000247013703014441017326 0ustar fengfengPNG  IHDRhtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp NJNIDATxb?01@@1bLD0h # ɓ`0pqq={0lذl4AD33,# H~Õl2?04$T;jܰxbXF`{9778L#z(Q xB>ǿ v!$![dc`ef@R {iI9cйALYw޺ !wj$Vq]kQJztkha)`'Q)5as,ӽwIENDB`ukui-system-monitor/src/img/fullscreen.png0000644000175000017500000000051313703014441017671 0ustar fengfengPNG  IHDR<<:r pHYs%%IR$IDATh @Eg &VFnVl`$2>vhMSn cau,ձ:Vl~3=)rp)O^)at,i=;08L#N?jى-{ f}X;au,ձ:VXXpn*V5k -+ev5-h΂:f72& fOiu,ձ:VXX Ӗ07I_IENDB`ukui-system-monitor/src/img/up_arrow.png0000644000175000017500000000264613703014441017376 0ustar fengfengPNG  IHDR pHYs  iTXtXML:com.adobe.xmp 6IDAT] 0 gojd{o*TUo#]9:1ƊdIENDB`ukui-system-monitor/src/img/processmanager.png0000644000175000017500000000401413703014441020540 0ustar fengfengPNG  IHDR00`ntEXtSoftwareAdobe ImageReadyqe<qiTXtXML:com.adobe.xmp ;C)dOC}H/uiHD6"(l'Z0±P<ɡE /dzي % FhD* \Ә2J4eɈ ci͢F^]Ͽ,e~w7U|MzKJ_8Mw\#ӊH+ugj9-4$1D__A?M+~fI6)8fr-1FҴ{_@ `q/a5ȢU{b) Ԭ,;"jzDWq#g!5xzbxc;^0vȫdMޛB[ܠ#juBYLki|a&R+gyn73u$twhSY,ɦ0O`h9?R0B sQ>\t ;qT>.śN̓M=9o5f$/`k<|zOi).z9a Kg҅#&٫ڪMF&xfu˶o-μ@Fc}sD:࠸!nߺ1|+ [C0奆c&!þMG@OBy,/P2Zzj<א  ^f7t3(_sB# ,wA? 2'TQ_? b\tmUOt9*$Jǚ#1tL Sj۰w1_儬?$}9 :#,j ЭL''ػwAWfKvwȤeI&{*e.P&ŦXX}cw6.ʼn+ҷ} 4Ff^|J0*(tWO7x%IENDB`ukui-system-monitor/src/img/drive-harddisk-system.png0000644000175000017500000000060013703014441021746 0ustar fengfengPNG  IHDRa pHYs  ~2IDAT8c?%Y# ?~`7 ;;FOO&֭[p}&`]=Vy G1ٳ$hcǎ @T`z`J]l.' ukui-system-monitor/src/img/button-close-hover-click-add-background-one.svg0000644000175000017500000000116613703014441026013 0ustar fengfeng ukui-system-monitor/src/img/minimize.png0000644000175000017500000000031213703014441017345 0ustar fengfengPNG  IHDR<<:r pHYs%%IR$|IDAThA + n$ }mw\XUkLg0tLg0tLg0tӝ}U$~.`: 3`: 3`: 3`$| sEIENDB`ukui-system-monitor/src/img/user_proc.png0000644000175000017500000000266713703014441017544 0ustar fengfengPNG  IHDRhtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp IDATxb?01@@1D8 "DDD8qD0`̙En}O/_<.e; ((..0666Zx1XF gœ:@RbЁ@:p.Ёe  - ߾}ðn5ý{+;rƍ K[kIDATxb;[ar nuƑ-mq 7iF94 8p"jՎ,?cva. ܏OH/6t* Jg4aPE5fwTUuz5Ktw1$-^|K~f`}{%fϾq{Xl9=ċv6ߎ|y-~5Ԫ\GCB@2+9xz@r[Kjlc jIENDB`ukui-system-monitor/src/img/active_proc.png0000644000175000017500000000254513703014441020034 0ustar fengfengPNG  IHDRhtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp 8{IDATxb?&3gX-?,FO>1:uk֭190-6?:ذa# aggΎ" LuGr*ܙF:! C՗/_qΧO"L' ///Od]d2E b#_8p "JӳgQQ$ X'@2`3K0FVV[!ȑ#M&pƆbRNN(;|fDCV˂,~޻w VVVV X ^W2IIENDB`ukui-system-monitor/src/img/button-close-hover-click-two.svg0000644000175000017500000000104713703014441023176 0ustar fengfeng ukui-system-monitor/src/img/close.png0000644000175000017500000000067413703014441016644 0ustar fengfengPNG  IHDR<<:r pHYs%%IR$nIDAThi@7Gw7B|O! 4{R +X-<B?H,d!%nQZ/ [`q8zl="ҋVD18F_:K<o/$&^} $KW'ס~ʝ>&cKå|}F8';\R[AU5X6,j-H@C\? 1w:E1?cjQ'M*9ڜF. */ #include "customstyle.h" #include #include #include #include #include #include #include #include InternalStyle::InternalStyle(const QString &styleName, QObject *parent) : QProxyStyle(styleName) { } InternalStyle::~InternalStyle() { } void InternalStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { //qDebug()<fillRect(option->rect, option->palette.button().color()); return; // painter->save(); // painter->setRenderHint(QPainter::Antialiasing, true); // painter->setPen(QPen(option->palette.foreground(), 1.0)); // painter->drawRect(option->rect.adjusted(+1, +1, -1, -1)); // painter->restore(); QStyleOptionFrame frame = *qstyleoption_cast(option); QFrame::Shape shape = frame.frameShape; switch (shape) { case QFrame::Box: { //border top radius painter->fillRect(frame.rect, Qt::red); return; } case QFrame::HLine: { //border bottom radius painter->fillRect(frame.rect, Qt::green); return; } case QFrame::VLine: { //both top and bottom painter->fillRect(frame.rect, Qt::blue); return; } default: // qDebug()<<"this is deafault"<parent() && widget->inherits("QComboBoxPrivateContainer")) break; return; } default: break; } return QProxyStyle::drawPrimitive(element, option, painter, widget); } void InternalStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { // qDebug()<drawPrimitive(PE_Frame, option, painter, widget); QStyleOptionFrame frame = *qstyleoption_cast(option); QFrame::Shape shape = frame.frameShape; switch (shape) { case QFrame::Box: { // Draw four rounded corners painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setBrush(option->palette.color(QPalette::Button)); painter->setPen(Qt::transparent); painter->setOpacity(0.45); painter->drawRoundedRect(widget->rect(), 6, 6); painter->restore(); return; } case QFrame::HLine: { // Draw rounded corners at the bottom left and bottom right painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); QPainterPath path; path.addRoundedRect(frame.rect, 6,6); path.setFillRule(Qt::WindingFill); path.addRect(frame.rect.width() - 6, 0, 6, 6); path.addRect(0, 0, 6, 6); painter->setPen(Qt::transparent); painter->setBrush(option->palette.color(QPalette::Button)); painter->setClipPath(path); painter->drawRect(frame.rect); painter->restore(); return; } case QFrame::VLine: { // Draw rounded corners in the upper left and upper right corners painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); QPainterPath path; path.addRoundedRect(frame.rect, 6,6); path.setFillRule(Qt::WindingFill); path.addRect(0, frame.rect.height() - 6, 6, 6); path.addRect(frame.rect.width() - 6, frame.rect.height() - 6, 6, 6); painter->setPen(Qt::transparent); painter->setBrush(option->palette.color(QPalette::Button)); painter->setClipPath(path); painter->drawRect(frame.rect); painter->restore(); return; } case QFrame::Panel: { // Do not draw corner painter->fillRect(frame.rect, option->palette.color(QPalette::Button)); return; } default: // qDebug()<<"this is deafault"<parent() && ((widget->parent()->inherits("QComboBoxPrivateContainer") || (qobject_cast(widget->topLevelWidget()) && qobject_cast(widget))))) { break; } QStyleOptionViewItem item = *qstyleoption_cast(option); item.palette.setColor(QPalette::Highlight, item.palette.base().color()); return QProxyStyle::drawControl(element, &item, painter, widget); } default: break; } return QProxyStyle::drawControl(element, option, painter, widget); } void InternalStyle::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { switch (control) { case CC_ComboBox: { const QStyleOptionComboBox *tmp = qstyleoption_cast(option); QStyleOptionComboBox combobox = *tmp; combobox.palette.setColor(QPalette::Button, combobox.palette.base().color()); return QProxyStyle::drawComplexControl(control, &combobox, painter, widget); break; } default: break; } return QProxyStyle::drawComplexControl(control, option, painter, widget); } void InternalStyle::polish(QPalette &pal) { QProxyStyle::polish(pal); pal.setColor(QPalette::Window, pal.base().color()); pal.setColor(QPalette::Inactive, QPalette::Base, pal.base().color()); // pal.setColor(QPalette::Button, pal.alternateBase().color()); } void InternalStyle::polish(QWidget *widget) { QProxyStyle::polish(widget); if (qobject_cast(widget)) { auto pal = qApp->palette(); pal.setColor(QPalette::Base, pal.alternateBase().color()); widget->setPalette(pal); } } void InternalStyle::unpolish(QWidget *widget) { QProxyStyle::unpolish(widget); } ukui-system-monitor/src/shell/customstyle.h0000644000175000017500000000442313746753504020145 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CUSTOMSTYLE_H #define CUSTOMSTYLE_H #include /*! * \brief The InternalStyle class * \note * InternalStyle is a special style naming rule of qt5-ukui-platformtheme. * It tells the platform do not take care of the style management of application * when an application set the style as default style. * * Do not modify this class name, otherwise the style will changed to default system * style when system style changed. * * InternalStyle是qt5-ukui-platformtheme的特殊命名规则, * 它用于告知平台插件不接管系统主题的管理(前提是将其设置为qApp的默认主题)。 * * 不要修改这个类名,否则切换系统主题时,应用定制的应用主题会被系统主题覆盖。 */ class InternalStyle : public QProxyStyle { Q_OBJECT public: explicit InternalStyle(const QString &styleName, QObject *parent = nullptr); ~InternalStyle(); void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const; void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const; void polish(QPalette &pal); void polish(QWidget *widget); void unpolish(QWidget *widget); signals: }; #endif // CUSTOMSTYLE_H ukui-system-monitor/src/filesystemdialog.cpp0000644000175000017500000001160413746753504020341 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemdialog.h" #include #include #include #include #include #include "filesystemdata.h" #include "filesystemworker.h" #include "filesystemwatcher.h" FileSystemDialog::FileSystemDialog(QList toBeDisplayedColumns, QSettings *settings, QWidget *parent) :QWidget(parent) ,proSettings(settings) // ,m_monitorFile("/home/lixiang/testwatcher/1.c") // ,m_monitorFile("/etc/mtab") { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setAcceptDrops(true); setAttribute(Qt::WA_NoMousePropagation); // setAttribute(Qt::WA_TranslucentBackground); this->setObjectName("FileSystemDialog"); m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); m_fileSysListWidget = new FileSystemListWidget(toBeDisplayedColumns); connect(m_fileSysListWidget, &FileSystemListWidget::rightMouseClickedItem, this, &FileSystemDialog::popupMenu, Qt::QueuedConnection); connect(m_fileSysListWidget, SIGNAL(changeColumnVisible(int,bool,QList)), this, SIGNAL(changeColumnVisible(int,bool,QList))); m_layout->addWidget(m_fileSysListWidget); m_fileSystemWorker = new FileSystemWorker; m_fileSystemWorker->moveToThread(qApp->thread()); // this->initFileSystemMonitor(); m_menu = new QMenu(); m_refreshAction = new QAction(tr("Refresh"), this); connect(m_refreshAction, &QAction::triggered, this, &FileSystemDialog::refreshFileSysList); m_menu->addAction(m_refreshAction); this->refreshFileSysList(); m_fileSystemWatcher = FileSystemWatcher::instance(); //it will emit a signal to tell us if the device is added or removed connect(m_fileSystemWatcher, &FileSystemWatcher::deviceAdded, this, [=] (const QString &dev) { this->refreshFileSysList(); }); connect(m_fileSystemWatcher, &FileSystemWatcher::deviceRemoved, this, [=] (const QString &dev) { this->refreshFileSysList(); }); //refresh file system info every 10 minutes m_timer = new QTimer(this); connect(m_timer,SIGNAL(timeout()),this,SLOT(refreshFileSysList())); m_timer->start(10000); } FileSystemDialog::~FileSystemDialog() { // m_fileSystemMonitor->removePath(m_monitorFile); // delete m_fileSystemMonitor; if (m_timer != NULL) { disconnect(m_timer,SIGNAL(timeout()),this,SLOT(refreshProcproperties())); if(m_timer->isActive()) { m_timer->stop(); } delete m_timer; m_timer = NULL; } m_fileSystemWorker->deleteLater(); delete m_fileSysListWidget; delete m_refreshAction; delete m_menu; delete m_layout; } void FileSystemDialog::refreshFileSysList() { m_fileSystemWorker->onFileSystemListChanged(); QList items; for (FileSystemData *info : m_fileSystemWorker->diskInfoList()) { FileSystemListItem *item = new FileSystemListItem(info); items << item; } m_fileSysListWidget->refreshFileSystemItems(items); } void FileSystemDialog::popupMenu(QPoint pos) { m_menu->exec(pos); } FileSystemListWidget* FileSystemDialog::getFileSysView() { return m_fileSysListWidget; } void FileSystemDialog::initFileSystemMonitor() { /*int fd = inotify_init(); int wd = inotify_add_watch (fd, path, mask); // int ret = inotify_rm_watch (fd, wd);*/ /*m_fileSystemMonitor = new QFileSystemWatcher(this); // m_fileSystemMonitor->addPath(m_monitorFile); QFileInfo info(m_monitorFile); m_fileSystemMonitor->addPath(info.absoluteFilePath()); connect(m_fileSystemMonitor, SIGNAL(directoryChanged(QString)), this, SLOT(onDirectoryChanged(QString))); connect(m_fileSystemMonitor, &QFileSystemWatcher::fileChanged, [=] (const QString &path) { qDebug()<< "file path===================="<type() == QEvent::LayoutRequest) // setFixedHeight(m_centralLayout->sizeHint().height()); // return QWidget::event(event); //} ukui-system-monitor/src/filesystemlistwidget.cpp0000644000175000017500000005770513763560717021276 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemlistwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include FileSystemListWidget::FileSystemListWidget(QList toBeDisplayedColumns, QWidget *parent) : QWidget(parent) ,m_titlePadding(10) ,m_titleHeight(40) ,m_rowHeight(29) ,m_offSet(0) ,m_origOffset(0) ,m_scrollbarWidth(10) ,m_titleHoverColumn(-1) ,m_titlePressColumn(-1) ,m_mouseAtScrollArea(false) ,m_mouseDragScrollbar(false) ,fontSettings(nullptr) ,qtSettings(nullptr) { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } initFontSize(); this->m_lastItem = NULL; this->m_listItems = new QList(); this->m_selectedItems = new QList(); this->columnTitles << tr("Device") << tr("Directory") << tr("Type") << tr("Total") << tr("Free") << tr("Available") << tr("Used"); QList widths; widths << 150 << -1 << 80 << 80 << 80 << 80 << 120;//-1时让该行填充所有剩余空间 QFont font; font.setPixelSize(12);//需要和填充所有剩余空间的那个的文字字体大小一致 font.setPointSize(9) QFontMetrics fm(font); this->m_columnWidths.clear(); for (int i = 0; i < widths.length(); i++) { if (widths[i] == -1) { this->m_columnWidths << widths[i]; } else {//-1时让改行填充所有剩余空间 int maxWidth = fm.width(this->columnTitles[i]) + this->m_titlePadding + /*m_upArrowPixmap.width() / m_upArrowPixmap.devicePixelRatio() +*/ 2 * 2; this->m_columnWidths << std::max(widths[i], maxWidth); } } this->m_columnVisibles.clear(); for (int i = 0; i < toBeDisplayedColumns.count(); i++) { this->m_columnVisibles.append(toBeDisplayedColumns[i]); } this->setFocus(); } FileSystemListWidget::~FileSystemListWidget() { if (this->m_hideScrollbarTimer != NULL) { disconnect(this->m_hideScrollbarTimer,SIGNAL(timeout()),this,SLOT(hideScrollbar())); if(this->m_hideScrollbarTimer->isActive()) { this->m_hideScrollbarTimer->stop(); } delete this->m_hideScrollbarTimer; this->m_hideScrollbarTimer = nullptr; } delete this->m_lastItem; delete this->m_listItems; delete this->m_selectedItems; if(fontSettings) { delete fontSettings; } if(qtSettings) { delete qtSettings; } } void FileSystemListWidget::clearItems() { qDeleteAll(this->m_listItems->begin(), this->m_listItems->end()); this->m_listItems->clear(); } void FileSystemListWidget::initThemeMode() { if (!qtSettings) { // qWarning() << "Failed to load the gsettings: " << THEME_QT_SCHEMA; return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); repaint(); } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); } void FileSystemListWidget::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } void FileSystemListWidget::addSelectedItems(QList items, bool recordLastItem) { this->m_selectedItems->append(items); if (recordLastItem && this->m_selectedItems->count() > 0) { this->m_lastItem = this->m_selectedItems->last(); } } void FileSystemListWidget::clearSelectedItems(bool clearLast) { this->m_selectedItems->clear(); if (clearLast) { this->m_lastItem = NULL; } } void FileSystemListWidget::refreshFileSystemItems(QList items) { QList *allItems = new QList(); FileSystemListItem *newLastItem = NULL; for (FileSystemListItem *item:items) { for (FileSystemListItem *selectionItem:*this->m_selectedItems) { if (item->isSameItem(selectionItem)) { allItems->append(item); break; } } } if (this->m_lastItem != NULL) { for (FileSystemListItem *item:items) { if (item->isSameItem(this->m_lastItem)) { newLastItem = item; break; } } } clearItems(); this->m_listItems->append(items); clearSelectedItems(); addSelectedItems(*allItems, false); this->m_lastItem = newLastItem; this->m_offSet = setOffset(this->m_offSet); repaint(); } void FileSystemListWidget::leaveEvent(QEvent * event) { hideScrollbar(); QWidget::leaveEvent(event); } void FileSystemListWidget::hideScrollbar() { this->m_mouseAtScrollArea = false; this->m_origOffset = this->m_offSet; repaint(); } void FileSystemListWidget::mouseMoveEvent(QMouseEvent *mouseEvent) { if (this->m_mouseDragScrollbar) { this->m_offSet = setOffset((mouseEvent->y() - getScrollbarHeight() / 2 - this->m_titleHeight) / (getTheScrollAreaHeight() * 1.0) * this->getItemsTotalHeight()); repaint(); } else if (mouseAtScrollArea(mouseEvent->x()) != this->m_mouseAtScrollArea) { this->m_mouseAtScrollArea = mouseAtScrollArea(mouseEvent->x()); repaint(); } } void FileSystemListWidget::mouseDoubleClickEvent(QMouseEvent *event) { bool isTitleArea = mouseAtTitleArea(event->y()); bool isScrollArea = mouseAtScrollArea(event->x()); if (!isTitleArea && !isScrollArea) { int pressedItemIndex = (this->m_offSet + event->y() - this->m_titleHeight) / this->m_rowHeight; if (pressedItemIndex >= this->m_listItems->count()) { clearSelectedItems(); repaint(); } else { if (event->button() == Qt::LeftButton) { FileSystemListItem *pressItem = (*this->m_listItems)[pressedItemIndex]; bool pressInSelectionArea = false; for (FileSystemListItem *item : *this->m_selectedItems) { if (item == pressItem) { pressInSelectionArea = true; break; } } if (pressInSelectionArea) { //open the mount dir FileSystemListItem *item = static_cast(pressItem); QString targetPath = QString("file://%1").arg(item->getDirectory()); QDesktopServices::openUrl(QUrl(targetPath));//xdg-open } } } } QWidget::mouseDoubleClickEvent(event); } void FileSystemListWidget::mousePressEvent(QMouseEvent *mouseEvent) { setFocus(); bool isTitleArea = mouseAtTitleArea(mouseEvent->y()); bool isScrollArea = mouseAtScrollArea(mouseEvent->x()); if (isTitleArea) {//点击列表的标题栏区域 if (mouseEvent->button() == Qt::RightButton) { if (m_columnVisibles.count() == this->columnTitles.count()) { QMenu *menu = new QMenu(); menu->setObjectName("MonitorMenu"); for (int i = 0; i < m_columnVisibles.count(); i++) { if (i != 0) {//让第一行总是显示,不可以设置显示或者不显示,其他行可以设置 QAction *action = new QAction(menu); action->setText(this->columnTitles[i]); action->setCheckable(true); action->setChecked(m_columnVisibles[i]); connect(action, &QAction::triggered, this, [this, action, i] { m_columnVisibles[i] = !m_columnVisibles[i]; emit this->changeColumnVisible(i, m_columnVisibles[i], m_columnVisibles); repaint(); }); menu->addAction(action); } } menu->exec(this->mapToGlobal(mouseEvent->pos())); delete menu; } } } else if (isScrollArea) {//点击滚动条区域 int barHeight = getScrollbarHeight(); int barY = getScrollbarY(); if (mouseEvent->y() > barY && mouseEvent->y() < barY + barHeight) { this->m_mouseDragScrollbar = true; } else { this->m_offSet = setOffset((mouseEvent->y() - barHeight / 2 - this->m_titleHeight) / (getTheScrollAreaHeight() * 1.0) * this->getItemsTotalHeight()); repaint(); } } else { int pressedItemIndex = (this->m_offSet + mouseEvent->y() - this->m_titleHeight) / this->m_rowHeight; if (pressedItemIndex >= this->m_listItems->count()) { clearSelectedItems(); repaint(); } else { if (mouseEvent->button() == Qt::LeftButton) { if (pressedItemIndex < this->m_listItems->count()) { if (mouseEvent->modifiers() == Qt::ControlModifier) { FileSystemListItem *item = (*this->m_listItems)[pressedItemIndex]; if (this->m_selectedItems->contains(item)) { this->m_selectedItems->removeOne(item); } else { QList items = QList(); items << item; addSelectedItems(items); } } else { clearSelectedItems(); QList items = QList(); items << (*this->m_listItems)[pressedItemIndex]; addSelectedItems(items); } repaint(); } } else if (mouseEvent->button() == Qt::RightButton) { FileSystemListItem *pressItem = (*this->m_listItems)[pressedItemIndex]; bool pressInSelectionArea = false; for (FileSystemListItem *item : *this->m_selectedItems) { if (item == pressItem) { pressInSelectionArea = true; break; } } if (pressInSelectionArea) { emit this->rightMouseClickedItem(this->mapToGlobal(mouseEvent->pos())); } } } } } void FileSystemListWidget::mouseReleaseEvent(QMouseEvent *) { if (this->m_mouseDragScrollbar) { this->m_mouseDragScrollbar = false; repaint(); } else { if (this->m_titlePressColumn != -1) { this->m_titlePressColumn = -1; repaint(); } } } void FileSystemListWidget::wheelEvent(QWheelEvent *event) { if (event->orientation() == Qt::Vertical) { this->m_origOffset = this->m_offSet; qreal scrollStep = event->angleDelta().y() / 100.0; this->m_offSet = setOffset(this->m_offSet - scrollStep * this->m_rowHeight); repaint(); } event->accept(); } void FileSystemListWidget::paintEvent(QPaintEvent *) { // QPainter painter(this); // painter.setRenderHint(QPainter::Antialiasing, true); // QList titleItemsWidths = getTitleItemsWidths(); // painter.setOpacity(0.05); // int penWidth = 1; // QPainterPath framePath; // framePath.addRoundedRect(QRect(rect().x() + penWidth, rect().y() + penWidth, rect().width() - penWidth * 2, rect().height() - penWidth * 2), 5, 5);//背景弧度 // painter.setClipPath(framePath); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QList titleItemsWidths = getTitleItemsWidths(); int penWidth = 0; // QPainterPath framePath; // framePath.addRoundedRect(QRect(rect().x() + penWidth, rect().y() + penWidth, rect().width() - penWidth * 2, rect().height() - penWidth * 2), 0, 0);//背景弧度 // painter.setClipPath(framePath); // draw border QPainterPath path; path.addRoundedRect(rect().adjusted(2, 2, -2, -2), 0, 0); painter.setClipRect(QRect(), Qt::NoClip); // QPen pen2(QColor(Qt::red)); // pen2.setWidth(1); // painter.setPen(pen2); // painter.drawPath(path); painter.setPen(Qt::NoPen); //painter.fillRect(this->rect(),QColor(0,0,FF,0x20)); painter.setOpacity(0.05); //framePath.setFillRule(Qt::ImhNone); //标题的背景 if (this->m_titleHeight > 0) { // QPainterPath titlePath; // titlePath.addRect(QRectF(rect().x(), rect().y(), rect().width(), this->m_titleHeight)); // painter.setOpacity(0.02); // //painter.fillPath(titlePath, QColor("#ffffff")); // painter.fillPath(titlePath,QColor("palette(windowText)")); QPainterPath titlePath; titlePath.addRect(QRectF(rect().x(), rect().y(), rect().width(), this->m_titleHeight)); //painter.setOpacity(1); painter.fillPath(titlePath, QColor("palette(windowText)")); // painter.fillPath(titlePath,QColor("#ffffff")); //painter.fillPath(titlePath, QColor("#CC00FF")); } int title_Y = 0; int title_Height = 0; if (this->m_titleHeight > 0) { int counter = 0; int posX = 0; for (int itemWidth:titleItemsWidths) { if (itemWidth > 0) { //标题文字 //title painter.setOpacity(0.57); QFont font = painter.font(); font.setPixelSize(fontSize); painter.setFont(font); painter.setPen(QPen(palette().color(QPalette::WindowText))); //#999999 // painter.setPen(QPen(QColor("#cc00ff"))); if (this->columnTitles[counter] == tr("Device") || this->columnTitles[counter] == tr("Directory") || this->columnTitles[counter] == tr("Used")) painter.drawText(QRect(posX + this->m_titlePadding, 0, itemWidth, this->m_titleHeight), Qt::AlignCenter, this->columnTitles[counter]); else painter.drawText(QRect(posX, 0, itemWidth - this->m_titlePadding, this->m_titleHeight), Qt::AlignCenter, this->columnTitles[counter]); //水平下划线 // painter.setOpacity(0.8); // QPainterPath h_separatorPath; // h_separatorPath.addRect(QRectF(posX, rect().y() + this->m_titleHeight - 1, itemWidth, 1)); // painter.fillPath(h_separatorPath, QColor("#e0e0e0")); if (counter < titleItemsWidths.size()) { //垂直分割线,文件系统的标题栏的垂直下划线 QPainterPath v_separatorPath; v_separatorPath.addRect(QRectF(rect().x() + posX - 1, rect().y() + 10, 1, this->m_titleHeight - 15)); // painter.fillPath(v_separatorPath, QColor(QPalette::WindowText)); //"#e0e0e0" painter.setOpacity(0.20); painter.fillPath(v_separatorPath,palette().color(QPalette::WindowText)); } posX += itemWidth; } counter++; } title_Y += this->m_titleHeight; title_Height += this->m_titleHeight; } //去掉列表标题栏后的列表显示区域的背景 painter.setOpacity(0.05); QPainterPath backgroundPath; backgroundPath.addRect(QRectF(rect().x(), rect().y() + this->m_titleHeight, rect().width(), rect().height() - this->m_titleHeight)); //painter.fillPath(backgroundPath, QColor("palette(windowText)")); //挂载的磁盘文件系统信息 QPainterPath scrollAreaPath; scrollAreaPath.addRect(QRectF(rect().x(), rect().y() + this->m_titleHeight, rect().width(), getTheScrollAreaHeight())); int rowCounter = 0; for (FileSystemListItem *item:*this->m_listItems) { if (rowCounter > ((this->m_offSet - this->m_rowHeight) / this->m_rowHeight)) { QPainterPath itemPath; itemPath.addRect(QRect(0, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, rect().width(), this->m_rowHeight)); // painter.setClipPath((framePath.intersected(scrollAreaPath)).intersected(itemPath)); bool isSelect = this->m_selectedItems->contains(item); painter.save(); item->drawBackground(QRect(0, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, rect().width(), this->m_rowHeight), &painter, rowCounter, isSelect, currentThemeMode); painter.restore(); int columnCounter = 0; int columnTitleX = 0; for (int titleItemWidth : titleItemsWidths) { if (titleItemWidth > 0) { painter.save(); if (columnCounter < titleItemsWidths.size() - 1) item->drawForeground(QRect(columnTitleX, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, titleItemWidth, this->m_rowHeight), &painter, columnCounter, rowCounter, isSelect, true); else item->drawForeground(QRect(columnTitleX, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, titleItemWidth, this->m_rowHeight), &painter, columnCounter, rowCounter, isSelect, false); painter.restore(); columnTitleX += titleItemWidth; } columnCounter++; } title_Height += this->m_rowHeight; if (title_Height > rect().height()) { break; } } rowCounter++; } // painter.setClipPath(framePath); //没有挂载的磁盘文件系统信息时绘制提示文字 if (this->m_listItems->size() == 0) { painter.setOpacity(1); painter.setPen(QPen(QColor("#666666"))); QFont font = painter.font() ; font.setPointSize(22); painter.setFont(font); painter.drawText(QRect(rect().x(), rect().y() + this->m_titleHeight, rect().width(), rect().height() - this->m_titleHeight), Qt::AlignCenter, tr("No File System Info")); } //背景 // QPen framePen; // framePen.setColor(QColor("#F5F5F5")); // painter.setPen(framePen); painter.setOpacity(0.2); // painter.drawPath(framePath); //垂直滚动条 if (this->m_mouseAtScrollArea) { paintScrollbar(&painter); } else if (this->m_origOffset != this->m_offSet) { paintScrollbar(&painter); readyToHideScrollbar(); } } void FileSystemListWidget::paintScrollbar(QPainter *painter) { if (this->getItemsTotalHeight() > getTheScrollAreaHeight()) { qreal opacitry = 0; if (this->m_mouseDragScrollbar) { opacitry = 0.8; } else { if (this->m_mouseAtScrollArea) opacitry = 0.7; else opacitry = 0.5; } int barWidth = (this->m_mouseAtScrollArea || this->m_mouseDragScrollbar) ? this->m_scrollbarWidth : 6; int barY = getScrollbarY(); int barHeight = getScrollbarHeight(); painter->setOpacity(opacitry); QPainterPath path; path.addRoundedRect( QRectF(rect().x() + rect().width() - barWidth - 4, barY + 2, barWidth, barHeight - 2 * 2), 2, 2);//2 is radius painter->fillPath(path, QColor("#0B95D7")); QPen pen; pen.setColor(QColor("#0B95D7")); pen.setWidth(1); painter->setOpacity(0); painter->setPen(pen); painter->drawPath(path); } } QList FileSystemListWidget::getTitleItemsWidths() { QList titleItemsWidths; if (this->m_columnWidths.length() > 0) { if (this->m_columnWidths.contains(-1)) { for (int i = 0; i < this->m_columnWidths.count(); i++) { if (this->m_columnWidths[i] != -1) { if (m_columnVisibles[i]) { titleItemsWidths << this->m_columnWidths[i]; } else { titleItemsWidths << 0; } } else { if (m_columnVisibles[i]) { int totalWidth = 0; for (int j = 0; j < this->m_columnWidths.count(); j++) { if (this->m_columnWidths[j] != -1 && m_columnVisibles[j]) { totalWidth += this->m_columnWidths[j]; } } titleItemsWidths << rect().width() - totalWidth; } else { titleItemsWidths << 0; } } } } else { for (int i = 0; i < this->m_columnWidths.count(); i++) { if (m_columnVisibles[i]) { titleItemsWidths << this->m_columnWidths[i]; } else { titleItemsWidths << 0; } } } } else { titleItemsWidths << rect().width(); } return titleItemsWidths; } bool FileSystemListWidget::mouseAtScrollArea(int x) { return (x > rect().x() + rect().width() - this->m_scrollbarWidth) && (x < rect().x() + rect().width()); } bool FileSystemListWidget::mouseAtTitleArea(int y) { return (y > rect().y() && y < rect().y() + this->m_titleHeight); } int FileSystemListWidget::setOffset(int offset) { return std::max(0, std::min(offset, getBottomOffset())); } int FileSystemListWidget::getItemsTotalHeight() { return m_listItems->count() * m_rowHeight; } int FileSystemListWidget::getTheScrollAreaHeight() { return this->rect().height() - this->m_titleHeight; } int FileSystemListWidget::getScrollbarY() { return static_cast((this->m_offSet / (this->getItemsTotalHeight() * 1.0)) * getTheScrollAreaHeight() + this->m_titleHeight); } int FileSystemListWidget::getScrollbarHeight() { return std::max(static_cast(getTheScrollAreaHeight() / (this->getItemsTotalHeight() * 1.0) * rect().height()), 30);//30 is min height } int FileSystemListWidget::getBottomOffset() { int itemsHeight = this->getItemsTotalHeight(); if (itemsHeight > rect().height() - this->m_titleHeight) { return this->getItemsTotalHeight() - rect().height() + this->m_titleHeight; } else { return 0; } } void FileSystemListWidget::readyToHideScrollbar() { if (this->m_hideScrollbarTimer) { if (this->m_hideScrollbarTimer->isActive()) this->m_hideScrollbarTimer->stop(); } else { this->m_hideScrollbarTimer = new QTimer(); this->m_hideScrollbarTimer->setSingleShot(true); connect(this->m_hideScrollbarTimer, SIGNAL(timeout()), this, SLOT(hideScrollbar())); } this->m_hideScrollbarTimer->start(2000); } ukui-system-monitor/src/src.pro0000644000175000017500000001117213764070001015562 0ustar fengfeng#------------------------------------------------- # # ukui-system-monitor # #------------------------------------------------- QT += core x11extras gui dbus network KWindowSystem isEqual(QT_MAJOR_VERSION, 5) { QT += widgets gui svg x11extras } include(QtSingleApplication/qtsingleapplication.pri) TARGET = ukui-system-monitor TEMPLATE = app DESTDIR = .. LIBS += -L/usr/lib/ -lX11 -lpcap -lm CONFIG += link_pkgconfig \ c++11 \ debug #gio-2.0 #LIBS +=-lgio-2.0 -lglib-2.0 PKGCONFIG += libgtop-2.0 \ libsystemd \ gsettings-qt \ x11 ICON.files = img/ukui-system-monitor.png ICON.path = /usr/share/icons/hicolor/ desktop.files += ../ukui-system-monitor.desktop desktop.path = /usr/share/applications/ target.source += $$TARGET target.path = /usr/bin schemes.files += ../data/*.xml schemes.path = /usr/share/glib-2.0/schemas/ #include(src/QtSingleApplication/qtsingleapplication.pri) #include(qtsingleapplication/qtsingleapplication.pri) #INCLUDEPATH += qtsingleapplication #DEPENDPATH += qtsingleapplication INSTALLS += target \ desktop \ schemes \ ICON unix { UI_DIR = .ui MOC_DIR = .moc OBJECTS_DIR = .obj } HEADERS += \ ../shell/macro.h \ systemmonitor.h \ processmanager.h \ processdialog.h \ processlistwidget.h \ processlistitem.h \ processworker.h \ linebandwith.h \ util.h \ ../component/utils.h \ ../widgets/mydialog.h \ ../widgets/mytristatebutton.h \ ../widgets/myunderlinebutton.h \ ../widgets/myhoverbutton.h \ propertiesdialog.h \ processcategory.h \ processdata.h \ ../widgets/myactiongroup.h \ ../widgets/myactiongroupitem.h \ ../widgets/myaction.h \ monitortitlewidget.h \ filesystemdialog.h \ filesystemworker.h \ filesystemdata.h \ ../widgets/mysearchedit.h \ filesystemlistwidget.h \ filesystemlistitem.h \ filesystemwatcher.h \ renicedialog.h \ ../component/mytitlebar.h \ framelessExtended/cursorposcalculator.h \ framelessExtended/framelesshandle.h \ framelessExtended/framelesshandleprivate.h \ framelessExtended/widgethandlerealize.h \ singleProcessNet/devices.h \ singleProcessNet/scanthread.h \ singleProcessNet/packet.h \ singleProcessNet/kylinsystemnethogs.h \ singleProcessNet/process.h \ singleProcessNet/connection.h \ singleProcessNet/conninode.h \ singleProcessNet/inode2prog.h \ singleProcessNet/refreshthread.h \ singleProcessNet/decpcap.h \ smoothlinegenerator.h \ newresource/sigcheck.h \ newresource/newresourcesdialog.h \ newresource/cpuhistorychart.h \ newresource/swapandmemorychart.h \ newresource/networkchart.h # newresourcesdialog.h SOURCES += \ main.cpp \ systemmonitor.cpp \ processmanager.cpp \ processdialog.cpp \ processlistwidget.cpp \ processlistitem.cpp \ processworker.cpp \ linebandwith.cpp \ util.cpp \ ../widgets/mydialog.cpp \ ../widgets/mytristatebutton.cpp \ ../widgets/myunderlinebutton.cpp \ ../widgets/myhoverbutton.cpp \ propertiesdialog.cpp \ processcategory.cpp \ ../widgets/myactiongroup.cpp \ ../widgets/myactiongroupitem.cpp \ ../widgets/myaction.cpp \ monitortitlewidget.cpp \ filesystemdialog.cpp \ filesystemworker.cpp \ filesystemdata.cpp \ ../widgets/mysearchedit.cpp \ filesystemlistwidget.cpp \ filesystemlistitem.cpp \ filesystemwatcher.cpp \ renicedialog.cpp \ ../component/mytitlebar.cpp \ framelessExtended/cursorposcalculator.cpp \ framelessExtended/framelesshandle.cpp \ framelessExtended/widgethandlerealize.cpp \ singleProcessNet/devices.cpp \ singleProcessNet/scanthread.cpp \ singleProcessNet/packet.cpp \ singleProcessNet/process.cpp \ singleProcessNet/connection.cpp \ singleProcessNet/conninode.cpp \ singleProcessNet/inode2prog.cpp \ singleProcessNet/refreshthread.cpp \ singleProcessNet/decpcap.c \ smoothlinegenerator.cpp \ newresource/newresourcesdialog.cpp \ newresource/sigcheck.cpp \ newresource/cpuhistorychart.cpp \ newresource/swapandmemorychart.cpp \ newresource/networkchart.cpp # newresourcesdialog.cpp OTHER_FILES += \ systemmonitor.json RESOURCES += \ res.qrc TRANSLATIONS += \ translation/ukui-system-monitor_bo.ts \ translation/ukui-system-monitor_de.ts \ translation/ukui-system-monitor_es.ts \ translation/ukui-system-monitor_fr.ts \ translation/ukui-system-monitor_ru.ts \ translation/ukui-system-monitor_tr.ts \ translation/ukui-system-monitor_zh_CN.ts ukui-system-monitor/src/processlistwidget.h0000644000175000017500000001044713763560717020225 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCESSLISTWIDGET_H #define PROCESSLISTWIDGET_H #include "processlistitem.h" #include "shell/customstyle.h" #include "../shell/macro.h" #include #include #include #include #include typedef bool (* SortFunction) (const ProcessListItem *item1, const ProcessListItem *item2, bool sort); typedef bool (* SearchFunction) (const ProcessListItem *item, QString text); class ProcessListWidget : public QWidget { Q_OBJECT public: ProcessListWidget(QList toBeDisplayedColumns, QWidget *parent = 0); ~ProcessListWidget(); void readyToHideScrollbar(); void setProcessSortFunctions(QList *list, int sortColumn=-1, bool isSort=false); void setSearchFunction(SearchFunction func); void addItems(QList items); void clearItems(); void addSelectedItems(QList items, bool recordLastItem=true); void clearSelectedItems(bool clearLast=true); void refreshItems(QList items); void doSearch(QString text); void selectTheFirstItem(); void selectTheLastItem(); void selectThePrevItem(int offset); void selectTheNextItem(int offset); void shiftToHomeItem(); void shiftToEndItem(); void shiftToPrevItem(int offset); void shiftToNextItem(int offset); void shiftToSelectedItems(int start, int end); int getItemsTotalHeight(); QList getSearchedItems(QList items); void sortItemsByColumn(int column, bool isSort); int getBottomOffset(); int getScrollbarY(); int getScrollbarHeight(); int getTheScrollAreaHeight(); QList getTitleItemsWidths(); int setOffset(int offset); bool mouseAtScrollArea(int x); bool mouseAtTitleArea(int y); void initThemeMode(); void initFontSize(); signals: void rightMouseClickedItems(QPoint pos, QList items); void changeColumnVisible(int index, bool visible, QList columnVisible); void changeSortStatus(int index, bool isSort); public slots: void hideScrollbar(); protected: virtual void leaveEvent(QEvent *event); void keyPressEvent(QKeyEvent *keyEvent); void mouseMoveEvent(QMouseEvent *mouseEvent); void mousePressEvent(QMouseEvent *mouseEvent); void mouseReleaseEvent(QMouseEvent *mouseEvent); void paintEvent(QPaintEvent *); void wheelEvent(QWheelEvent *event); void paintScrollbar(QPainter *painter); // bool eventFilter(QObject *obj, QEvent *event); // void resizeEvent(QResizeEvent *event); private: QTimer *m_hideScrollbarTimer = nullptr; SearchFunction m_searchFunc; ProcessListItem *m_lastItem = nullptr; QList *m_listItems; QList *m_searchedItems; QList *m_selectedItems; QList columnTitles; QList *m_sortFuncList; QList *m_isSortList; QList m_columnWidths; QList m_columnVisibles; QList widths; QString m_searchText; bool m_isSort; bool m_mouseAtScrollArea; bool m_mouseDragScrollbar; int m_currentSortIndex; int m_origOffset; int m_offSet; int m_rowHeight; int m_scrollbarWidth; int m_titleHeight; int m_titleHoverColumn; int m_titlePadding; int m_titlePressColumn; QPixmap m_downArrowPixmap; QPixmap m_upArrowPixmap; float fontSize; QGSettings *qtSettings; QGSettings *fontSettings; QString currentThemeMode; qreal opacity; }; #endif // PROCESSLISTWIDGET_H ukui-system-monitor/src/maincontroller.cpp0000644000175000017500000000630013746753570020025 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "maincontroller.h" MainController* MainController::mSelf = 0; //static variable MainController* MainController::self() //static function //complete the singleton object { if (!mSelf) { mSelf = new MainController; } return mSelf; } MainController::MainController() { init(); monitor=new SystemMonitor(); monitor->setAttribute(Qt::WA_DeleteOnClose); monitor->show(); FramelessHandle * pHandle = new FramelessHandle(monitor); pHandle->activateOn(monitor); delete pHandle; } MainController::~MainController() { delete monitor; delete mSelf; } void MainController::init() //init select { if(IsNotRunning()) { creatDBusService(); //create connect qDebug()<<"Create DBus Service"; } else { qDebug()<<"ukui-system-monior is running"; //or finish the process exit(0); } } int MainController::IsNotRunning() { //determine the session bus that if it has been connected char service_name[SERVICE_NAME_SIZE]; memset(service_name, 0, SERVICE_NAME_SIZE); snprintf(service_name, SERVICE_NAME_SIZE, "%s_%d",UKUI_SYSTEM_MONITOR_SERVICE,getuid()); QDBusConnection conn = QDBusConnection::sessionBus(); if (!conn.isConnected()) return 0; QDBusReply reply = conn.interface()->call("GetNameOwner", service_name); return reply.value() == ""; } void MainController::creatDBusService() { // 用于建立到session bus的连接 //to be used for creating the session bus connection QDBusConnection bus = QDBusConnection::sessionBus(); // 在session bus上注册名为"com.ukui_user_guide.hotel"的service // register the service in session bus that named by "com.ukui_user_guide.hotel" char service_name[SERVICE_NAME_SIZE]; memset(service_name, 0, SERVICE_NAME_SIZE); snprintf(service_name, SERVICE_NAME_SIZE, "%s_%d", UKUI_SYSTEM_MONITOR_SERVICE, getuid()); if (!bus.registerService(service_name)) { //注意命名规则-和_ //Note the naming convention. qDebug() << bus.lastError().message(); exit(1); } // "QDBusConnection::ExportAllSlots"表示把类Hotel的所有Slot都导出为这个Object的method // "QDBusConnection::ExportAllSlots" stands for that it makes all the slot in class hotel export to the method of this object bus.registerObject("/", this ,QDBusConnection::ExportAllSlots); } ukui-system-monitor/src/processcategory.cpp0000644000175000017500000000640613746753504020215 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processcategory.h" #include "../widgets/myhoverbutton.h" ProcessCategory::ProcessCategory(int tabIndex, QWidget *parent) : QWidget(parent) ,width(16) ,height(16) ,activeIndex(tabIndex) { setFixedSize(width * 3, height); layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); activeProcessButton = new MyHoverButton(this); activeProcessButton->setPicture(":/img/active_proc.png"); activeProcessButton->setToolTip(tr("Active Processes")); userProcessButton = new MyHoverButton(this); userProcessButton->setPicture(":/img/user_proc.png"); userProcessButton->setToolTip(tr("My Processes")); allProcessButton = new MyHoverButton(this); allProcessButton->setPicture(":/img/all_proc.png"); allProcessButton->setToolTip(tr("All Processes")); if (activeIndex == 0) { activeProcessButton->setChecked(true); userProcessButton->setChecked(false); allProcessButton->setChecked(false); } else if (activeIndex == 2) { activeProcessButton->setChecked(false); userProcessButton->setChecked(false); allProcessButton->setChecked(true); } else { activeProcessButton->setChecked(false); userProcessButton->setChecked(true); allProcessButton->setChecked(false); } connect(activeProcessButton, &MyHoverButton::clicked, this, [=] { activeIndex = 0; emit this->activeWhoseProcessList(activeIndex); activeProcessButton->setChecked(true); userProcessButton->setChecked(false); allProcessButton->setChecked(false); }); connect(userProcessButton, &MyHoverButton::clicked, this, [=] { activeIndex = 1; emit this->activeWhoseProcessList(activeIndex); activeProcessButton->setChecked(false); userProcessButton->setChecked(true); allProcessButton->setChecked(false); }); connect(allProcessButton, &MyHoverButton::clicked, this, [=] { activeIndex = 2; emit this->activeWhoseProcessList(activeIndex); activeProcessButton->setChecked(false); userProcessButton->setChecked(false); allProcessButton->setChecked(true); }); layout->addWidget(activeProcessButton); layout->addWidget(userProcessButton); layout->addWidget(allProcessButton); this->setLayout(layout); } ProcessCategory::~ProcessCategory() { delete activeProcessButton; delete userProcessButton; delete allProcessButton; delete layout; } ukui-system-monitor/src/processmanager.cpp0000644000175000017500000000400713746753570020010 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processmanager.h" #include #include #include #include ProcessManager::ProcessManager(QObject *parent) : QObject(parent) { process_dialog = new SystemMonitor; //process_dialog->setStyleSheet(); } ProcessManager::~ProcessManager() { if (process_dialog) { delete process_dialog; process_dialog = nullptr; } } QString ProcessManager::getGuid() { return "UBUNTU-KYLIN-PROCESS"; } QString ProcessManager::getName() { return tr("System Monitor"); } QString ProcessManager::getDescribe() { return tr("Help user to kill process");//方便用户杀掉进程 } QString ProcessManager::getPicture() { return "processmanager.png"; } void ProcessManager::doAction() { // int windowWidth = QApplication::desktop()->width(); // int windowHeight = QApplication::desktop()->height(); // process_dialog->resetSkin(); // process_dialog->move((windowWidth - 850) / 2,(windowHeight - 476) / 2); process_dialog->show(); process_dialog->raise(); process_dialog->setFocus(); } QWidget *ProcessManager::centralWidget() { return process_dialog; } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(ProcessManager, ProcessManager) #endif ukui-system-monitor/src/monitortitlewidget.h0000644000175000017500000001000613764070001020352 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MONITORTITLEWIDGET_H #define MONITORTITLEWIDGET_H #include #include #include #include #include #include #include #include "shell/customstyle.h" #include "../shell/macro.h" class QVBoxLayout; class QHBoxLayout; class QLabel; class QPushButton; class MySearchEdit; class MyTristateButton; class MonitorTitleWidget : public QFrame { Q_OBJECT public: MonitorTitleWidget(QSettings *settings, QWidget *parent); ~MonitorTitleWidget(); void initTitlebarLeftContent(); void initTitlebarMiddleContent(); void initTitlebarRightContent(); void initToolbarLeftContent(); void initToolbarRightContent(); void initWidgets(); void setSearchEditFocus(); void initThemeMode(); void initFontSize(); void getTransparentData(); public slots: void onRefreshSearchResult(); void handleSearchTextChanged(); void onCancelSearchBtnClicked(bool b); void onMinBtnClicked(); void onMaxBtnClicked(); void onCloseBtnClicked(); void onUpdateMaxBtnStatusChanged(); void switchChangeItemProcessSignal(int a); void animationFinishedSlot(); signals: void updateMaxBtn(); void changePage(int index); void searchSignal(QString searchContent); void canelSearchEditFocus(); void changeProcessItemDialog(int index); void maximizeWindow(); void minimizeWindow(); void SearchFocusIN(); void SearchFocusOut(); protected: void mouseDoubleClickEvent(QMouseEvent *event) override; // void paintEvent(QPaintEvent *event) override; bool eventFilter(QObject *, QEvent *event) override; void resizeEvent(QResizeEvent *event); void paintEvent(QPaintEvent *event); private: QPropertyAnimation *m_animation; QEasingCurve m_hideCurve; QEasingCurve m_showCurve; QSettings *proSettings; MySearchEdit *m_searchEdit = nullptr; QLineEdit *m_searchEditNew = nullptr; QWidget *m_queryWid=nullptr; QLabel *m_queryIcon=nullptr; QLabel *m_queryText=nullptr; //QPushButton *m_cancelSearchBtn = nullptr; QString searchTextCache; QTimer *m_searchTimer = nullptr; QLabel *emptyLabel = nullptr; QVBoxLayout *m_layout = nullptr; QHBoxLayout *m_topLayout = nullptr; QHBoxLayout *m_titleMiddleLayout = nullptr; QHBoxLayout *m_titleRightLayout = nullptr; QHBoxLayout *m_bottomLayout = nullptr; QHBoxLayout *m_titleLeftLayout = nullptr; QHBoxLayout *m_toolLeftLayout = nullptr; QHBoxLayout *m_toolRightLayout = nullptr; MyTristateButton *maxBtn = nullptr; QWidget *buttonWidget = nullptr; QPushButton *m_processButton = nullptr; QPushButton *m_resourceButton = nullptr; QPushButton *m_filesystemButton = nullptr; QPushButton *maxTitleBtn = nullptr; QComboBox *m_changeBox; QLabel *titleLabel; QWidget *emptyWidget = nullptr; QWidget *emptyWidget2 = nullptr; float fontSize; QGSettings *qtSettings; QGSettings *fontSettings; QGSettings * ifsettings; QGSettings *opacitySettings; QString currentThemeMode; double m_transparency; QList *whichBox; int whichNum; int i=0; QPixmap pixmap; bool m_isSearching; QHBoxLayout* queryWidLayout; }; #endif // MONITORTITLEWIDGET_H ukui-system-monitor/src/filesystemdialog.h0000644000175000017500000000367313746753504020015 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "filesystemlistwidget.h" class FileSystemData; class FileSystemWorker; class FileSystemWatcher; class QVBoxLayout; class QHBoxLayout; class FileSystemDialog : public QWidget { Q_OBJECT public: explicit FileSystemDialog(QList toBeDisplayedColumns, QSettings *settings, QWidget* parent = 0); ~FileSystemDialog(); FileSystemListWidget *getFileSysView(); void initFileSystemMonitor(); public slots: void refreshFileSysList(); void onDirectoryChanged(QString path); void popupMenu(QPoint pos); signals: void changeColumnVisible(int index, bool visible, QList columnVisible); //private: // bool event(QEvent *event); private: FileSystemWorker *m_fileSystemWorker = nullptr; // QFileSystemWatcher *m_fileSystemMonitor = nullptr; // QString m_monitorFile; QSettings *proSettings = nullptr; FileSystemListWidget *m_fileSysListWidget = nullptr; QAction *m_refreshAction = nullptr; QMenu *m_menu = nullptr; QVBoxLayout *m_layout = nullptr; QTimer *m_timer = nullptr; FileSystemWatcher *m_fileSystemWatcher = nullptr; }; ukui-system-monitor/src/linebandwith.cpp0000644000175000017500000000401213755714021017427 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "linebandwith.h" #include //int lineBandwith::countMap[0] = 0; lineBandwith::lineBandwith(int pid,QWidget *parent) :QLineEdit(parent) { // countMap = new QMap; time_prev = QDateTime::currentDateTime(); count_prev = 0; // countMap[pid] = 0; } QString lineBandwith::new_count(qint64 count ,int pid) { qint64 bandwith = count - countMap[pid]; // qDebug() <<"bandwidth: "<< bandwith; QDateTime now = QDateTime::currentDateTime(); quint64 ms_lapse = time_prev.msecsTo(now); if (ms_lapse < 1000) ms_lapse = 1000; // prevent division by 0 ;-) quint64 speed = bandwith * 1000 / ms_lapse; if (speed == 0 || speed < 0) { speedPerSec = "0 KB/S"; } else if (speed < 1900) { speedPerSec.setNum(speed); speedPerSec.append(" B/s"); } else if (speed < 1900000) { speedPerSec.setNum(speed/1024); speedPerSec.append(" kB/s"); } else if (speed < 1900000000) { speedPerSec.setNum(speed/(1024*1024)); speedPerSec.append(" MB/s"); } else { speedPerSec.setNum(speed/(1024*1024*1024)); speedPerSec.append(" GB/s"); } // qDebug() << "sprrdPerSec: " << speedPerSec; time_prev.swap(now); countMap[pid] = count; return speedPerSec; } ukui-system-monitor/src/processlistitem.cpp0000644000175000017500000004446113764070001020215 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processlistitem.h" #include #include #include #include "util.h" #include "../shell/macro.h" static int number = 0; ProcessListItem::ProcessListItem(ProcData info) :qtSettings(nullptr) ,fontSettings(nullptr) { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } initFontSize(); m_data = info; iconSize = 20; padding = 14; textPadding = 10; //initThemeMode(); } ProcessListItem::~ProcessListItem() { if (qtSettings) { qtSettings->deleteLater(); } if (fontSettings) { fontSettings->deleteLater(); } } void ProcessListItem::initThemeMode() { if (!qtSettings) { return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); qDebug() << "Current theme mode: "<< currentThemeMode << endl; // repaint(); } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); } void ProcessListItem::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings, &QGSettings::changed, this, [=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } bool ProcessListItem::isSameItem(ProcessListItem *item) { return m_data.pid == ((static_cast(item)))->m_data.pid; } void ProcessListItem::drawCellBackground(QRect rect, QPainter *painter, int level) { QPainterPath path; path.addRect(QRectF(rect.x(), rect.y(), rect.width(), rect.height())); painter->setOpacity(0.5);//0.1 } void ProcessListItem::drawBackground(QRect rect, QPainter *painter, int index, bool isSelect ,QString currentThemeMode) { QPainterPath path; path.addRect(QRectF(rect)); if (isSelect) { painter->setOpacity(0.08); painter->fillPath(path,QColor("palette(windowText)")); } else { painter->setOpacity(0.08); if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { painter->fillPath(path, QColor("#ffffff")); } else if (currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { painter->fillPath(path,QColor("#131414")); } else { painter->fillPath(path, QColor("000000")); } } } void ProcessListItem::drawForeground(QRect rect, QPainter *painter, int column, int, bool isSelect, bool isSeparator) { setFontSize(*painter, fontSize + 2); painter->setOpacity(0.85); //painter->setPen(QPen(QColor(QPalette::Base))); if (column == 0) { painter->drawPixmap(QRect(rect.x() + padding, rect.y() + (rect.height() - iconSize) / 2, iconSize, iconSize), m_data.iconPixmap); QString name = m_data.processName; if (m_data.m_status == tr("Stopped")) {//已停止 painter->setPen(QPen(QColor("#fca71d"))); name = QString("(%1) %2").arg(tr("Suspend")).arg(m_data.processName); } else if (m_data.m_status == tr("Zombie")) {//僵死 painter->setPen(QPen(QColor("#808080"))); name = QString("(%1) %2").arg(tr("No response")).arg(m_data.processName); } else if (m_data.m_status == tr("Uninterruptible")) {//不可中断 painter->setPen(QPen(QColor("#ff6a6a"))); name = QString("(%1) %2").arg(tr("Uninterruptible")).arg(m_data.processName); } else {//Sleeping 睡眠中 Running 运行中 } int nameMaxWidth = rect.width() - iconSize - padding * 3; QFont font = painter->font(); QFontMetrics fm(font); QString procName = fm.elidedText(name, Qt::ElideRight, nameMaxWidth); painter->drawText(QRect(rect.x() + iconSize + padding * 2, rect.y(), nameMaxWidth, rect.height()), Qt::AlignCenter, procName); if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 1) { if (!m_data.user.isEmpty()) { QString name = m_data.user; int userMaxWidth = rect.width() - padding * PADDING ; QFont font = painter->font(); QFontMetrics fm(font); QString userName = fm.elidedText(name, Qt::ElideRight, userMaxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, userName); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 2) { // if (!m_data.m_status.isEmpty()) { painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, m_data.m_diskio); // } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 3) { if (m_data.cpu < 10) { //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 0); } else if (m_data.cpu < 33) { //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 1); } else { //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 2); } painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, QString("%1%").arg(m_data.cpu)); if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 4) { painter->drawText(QRect(rect.x(), rect.y(), rect.width() - padding, rect.height()), Qt::AlignCenter, QString("%1").arg(m_data.pid)); if (!isSeparator) { painter->setOpacity(0.8); // QPainterPath separatorPath; // separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); // painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 5) { int flownetMaxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString flownet = fm.elidedText(m_data.m_flownet, Qt::ElideRight, flownetMaxWidth); painter->drawText(QRect(rect.x(), rect.y(), flownetMaxWidth, rect.height()), Qt::AlignCenter, flownet); if (!isSeparator) { painter->setOpacity(0.8); // QPainterPath separatorPath; // separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); // painter->fillPath(separatorPath, QColor("#CC00FF")); //e0e0e0 } } else if (column == 6) { if (m_data.m_memory > 0) { painter->setOpacity(1); char *memory = g_format_size_full(m_data.m_memory, G_FORMAT_SIZE_IEC_UNITS); QString Memory = QString(memory); if (m_data.m_memory < 102400000) {//<100M //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 0); } else if (m_data.m_memory < 1024000000) {//1G //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 1); } else { //this->drawCellBackground(QRect(rect.x(), rect.y(), rect.width(), rect.height()), painter, 2); } painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, Memory); g_free(memory); } else { QString Memory = "0 MiB"; painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, Memory); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 7) { painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, getNiceLevel(m_data.m_nice)); if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } } bool ProcessListItem::doSearch(const ProcessListItem *item, QString text) { const ProcessListItem *procItem = static_cast(item); QString content = text.toLower(); return procItem->getProcessName().toLower().contains(content) || QString::number(procItem->getPid()).contains(content) || procItem->getDisplayName().toLower().contains(content) || procItem->getUser().toLower().contains(content); } bool ProcessListItem::sortByDiskIo(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { // QString diskIo1 = (static_cast(item1))->getDiskIo(); // QString diskIo2 = (static_cast(item2))->getDiskIo(); int numDiskIo1 = (static_cast(item1))->getNumDiskIo(); int numDiskIo2 = (static_cast(item2))->getNumDiskIo(); bool isSort; if (numDiskIo1 == numDiskIo2) { long memory1 = static_cast(item1)->getMemory(); long memory2 = (static_cast(item2))->getMemory(); isSort = memory1 > memory2; } else { isSort = numDiskIo1 > numDiskIo2; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByFlowNet(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { int numFlowNet1 = (static_cast(item1))->getNumFlowNet(); int numFlowNet2 = (static_cast(item2))->getNumFlowNet(); bool isSort; if (numFlowNet1 == numFlowNet2) { long memory1 = static_cast(item1)->getMemory(); long memory2 = (static_cast(item2))->getMemory(); isSort = memory1 > memory2; } else { isSort = numFlowNet1 > numFlowNet2; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByName(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { QString name1 = (static_cast(item1))->getDisplayName(); QString name2 = (static_cast(item2))->getDisplayName(); bool isSort; if (name1 == name2) { double cpu1 = static_cast(item1)->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); isSort = cpu1 > cpu2; } else { QCollator qco(QLocale::system()); int result = qco.compare(name1, name2); isSort = result < 0; // char *nameString1; // char *nameString2; // QByteArray s1 = name1.toLatin1(); // QByteArray s2 = name2.toLatin1(); // nameString1 = s1.data(); // nameString2 = s2.data(); // int result = strcmp(nameString1,nameString2); } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByUser(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { QString user1 = (static_cast(item1))->getUser(); QString user2 = (static_cast(item2))->getUser(); bool isSort; if (user1 == user2) { double cpu1 = static_cast(item1)->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); isSort = cpu1 > cpu2; } else { QCollator qco(QLocale::system()); int result = qco.compare(user1, user2); isSort = result < 0; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByStatus(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { QString status1 = (static_cast(item1))->getStatus(); QString status2 = (static_cast(item2))->getStatus(); bool isSort; if (status1 == status2) { double cpu1 = static_cast(item1)->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); isSort = cpu1 > cpu2; } else { QCollator qco(QLocale::system()); int result = qco.compare(status1, status2); isSort = result < 0; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByCPU(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { double cpu1 = (static_cast(item1))->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); bool isSort; if (cpu1 == cpu2) { long memory1 = static_cast(item1)->getMemory(); long memory2 = (static_cast(item2))->getMemory(); isSort = memory1 > memory2; } else { isSort = cpu1 > cpu2; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByPid(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { bool isSort = (static_cast(item1))->getPid() > (static_cast(item2))->getPid(); return descendingSort ? isSort : !isSort; } //bool ProcessListItem::sortByCommand(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) //{ // QString command1 = (static_cast(item1))->getCommandLine(); // QString command2 = (static_cast(item2))->getCommandLine(); // bool isSort; // if (command1 == command2) { // double cpu1 = static_cast(item1)->getCPU(); // double cpu2 = (static_cast(item2))->getCPU(); // isSort = cpu1 > cpu2; // } // else { // QCollator qco(QLocale::system()); // int result = qco.compare(command1, command2); // isSort = result < 0; // } // return descendingSort ? isSort : !isSort; //} bool ProcessListItem::sortByMemory(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { long memory1 = (static_cast(item1))->getMemory(); long memory2 = (static_cast(item2))->getMemory(); bool isSort; if (memory1 == memory2) { double cpu1 = static_cast(item1)->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); isSort = cpu1 > cpu2; } else { isSort = memory1 > memory2; } return descendingSort ? isSort : !isSort; } bool ProcessListItem::sortByPriority(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort) { long nice1 = (static_cast(item1))->getNice(); long nice2 = (static_cast(item2))->getNice(); bool isSort; if (nice1 == nice2) { double cpu1 = static_cast(item1)->getCPU(); double cpu2 = (static_cast(item2))->getCPU(); isSort = cpu1 > cpu2; } else { isSort = nice1 < nice2; } return descendingSort ? isSort : !isSort; } QString ProcessListItem::getProcessName() const { return m_data.processName; } QString ProcessListItem::getDisplayName() const { return m_data.displayName; } QString ProcessListItem::getUser() const { return m_data.user; } QString ProcessListItem::getStatus() const { return m_data.m_status; } double ProcessListItem::getCPU() const { return m_data.cpu; } pid_t ProcessListItem::getPid() const { return m_data.pid; } long ProcessListItem::getMemory() const { return m_data.m_memory; } long ProcessListItem::getNice() const { return m_data.m_nice; } QString ProcessListItem::getFlowNet() const { return m_data.m_flownet; } QString ProcessListItem::getDiskIo() const { return m_data.m_diskio; } int ProcessListItem::getNumFlowNet() const { return m_data.m_numFlowNet; } int ProcessListItem::getNumDiskIo() const { return m_data.m_numDiskIo; } //QString ProcessListItem::getCommandLine() const //{ // return m_data.commandLine; //} ukui-system-monitor/src/processlistitem.h0000644000175000017500000000647413755705142017677 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCESSLISTITEM_H #define PROCESSLISTITEM_H #include #include #include #include #include #include #include #include "shell/customstyle.h" #include "processdata.h" #include "../shell/macro.h" class ProcessListItem : public QObject { Q_OBJECT public: ProcessListItem(ProcData info); ~ProcessListItem(); bool isSameItem(ProcessListItem *item); void drawCellBackground(QRect rect, QPainter *painter, int level); void drawBackground(QRect rect, QPainter *painter, int index, bool isSelect ,QString currentTheme); void drawForeground(QRect rect, QPainter *painter, int column, int index, bool isSelect, bool isSeparator); static bool doSearch(const ProcessListItem *item, QString text); static bool sortByName(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByUser(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByStatus(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByCPU(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByPid(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); // static bool sortByCommand(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByMemory(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByPriority(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByFlowNet(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); static bool sortByDiskIo(const ProcessListItem *item1, const ProcessListItem *item2, bool descendingSort); QString getProcessName() const; QString getDisplayName() const; QString getUser() const; double getCPU() const; pid_t getPid() const; long getMemory() const; QString getStatus() const; long getNice() const; // QString getCommandLine() const; QString getFlowNet() const; QString getDiskIo() const; int getNumFlowNet() const; int getNumDiskIo() const; void initThemeMode(); void initFontSize(); private: ProcData m_data; int iconSize; int padding; int textPadding; float fontSize; QGSettings *qtSettings; QGSettings *fontSettings; QString currentThemeMode; }; #endif // PROCESSLISTITEM_H ukui-system-monitor/src/filesystemwatcher.cpp0000644000175000017500000000531413746753504020540 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemwatcher.h" #include "util.h" #include FileSystemWatcher *FileSystemWatcher::m_watcher = NULL; FileSystemWatcher *FileSystemWatcher::instance() { if (!m_watcher) { m_watcher = new FileSystemWatcher; m_watcher->initWatcher(); } return m_watcher; } FileSystemWatcher::FileSystemWatcher(QObject *parent) : QObject(parent) ,m_fd(-1) { } FileSystemWatcher::~FileSystemWatcher() { this->clearWatcher(); } bool FileSystemWatcher::initWatcher() { m_origFileSet = getFileContentsLineByLine(DEVICE_MOUNT_PONINT_RECORD_FILE); m_fd = open(DEVICE_MOUNT_PONINT_RECORD_FILE, O_RDONLY); if (m_fd == -1) { qDebug() << QString("open %1 failed!").arg(DEVICE_MOUNT_PONINT_RECORD_FILE); return false; } m_socketNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Write, this); m_socketNotifier->setEnabled(true); connect(m_socketNotifier, &QSocketNotifier::activated, this, &FileSystemWatcher::onMountDeviceFileContentsChanged); return true; } bool FileSystemWatcher::watcherInitSuccess() { if (m_fd != -1 && m_socketNotifier) { return true; } else { return false; } } bool FileSystemWatcher::clearWatcher() { if (this->watcherInitSuccess()) { close(m_fd); m_fd = -1; delete m_socketNotifier; m_socketNotifier = nullptr; return true; } else { return false; } } void FileSystemWatcher::onMountDeviceFileContentsChanged() //emit the signal if the devie is added or removed { QSet nowFileSet = getFileContentsLineByLine(DEVICE_MOUNT_PONINT_RECORD_FILE); for(const QString &mountPath: nowFileSet - m_origFileSet) { emit this->deviceAdded(getDeviceMountedPointPath(mountPath)); } for(const QString &mountPath: m_origFileSet - nowFileSet) { emit this->deviceRemoved(getDeviceMountedPointPath(mountPath)); } m_origFileSet = nowFileSet; } ukui-system-monitor/src/QtSingleApplication/0000755000175000017500000000000013746753570020204 5ustar fengfengukui-system-monitor/src/QtSingleApplication/qtsinglecoreapplication.pri0000644000175000017500000000050413746753570025642 0ustar fengfengINCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp QT *= network win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) } ukui-system-monitor/src/QtSingleApplication/qtsingleapplication.h0000644000175000017500000000761713746753570024442 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLEAPPLICATION_H #define QTSINGLEAPPLICATION_H #include class QtLocalPeer; #if defined(Q_OS_WIN) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) # if defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # endif # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) # endif #else # define QT_QTSINGLEAPPLICATION_EXPORT #endif class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication { Q_OBJECT public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); #if QT_VERSION < 0x050000 QtSingleApplication(int &argc, char **argv, Type type); # if defined(Q_WS_X11) QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 bool isRunning(); QString id() const; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; // Obsolete: void initialize(bool dummy = true) { isRunning(); Q_UNUSED(dummy) } public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); void activateWindow(); Q_SIGNALS: void messageReceived(const QString &message); private: void sysInit(const QString &appId = QString()); QtLocalPeer *peer; QWidget *actWin; }; #endif // QTSINGLEAPPLICATION_H ukui-system-monitor/src/QtSingleApplication/qtsinglecoreapplication.h0000644000175000017500000000502513746753570025302 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLECOREAPPLICATION_H #define QTSINGLECOREAPPLICATION_H #include class QtLocalPeer; class QtSingleCoreApplication : public QCoreApplication { Q_OBJECT public: QtSingleCoreApplication(int &argc, char **argv); QtSingleCoreApplication(const QString &id, int &argc, char **argv); bool isRunning(); QString id() const; public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); Q_SIGNALS: void messageReceived(const QString &message); private: QtLocalPeer* peer; }; #endif // QTSINGLECOREAPPLICATION_H ukui-system-monitor/src/QtSingleApplication/qtsingleapplication.pri0000644000175000017500000000106113746753570024770 0ustar fengfengINCLUDEPATH += $$PWD DEPENDPATH += $$PWD QT *= network greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets qtsingleapplication-uselib:!qtsingleapplication-buildlib { LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME } else { SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h } win32 { contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT } ukui-system-monitor/src/QtSingleApplication/qtlockedfile_win.cpp0000644000175000017500000001466113746753570024243 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" #include #include #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS #if QT_VERSION >= 0x050000 #define QT_WA(unicode, ansi) unicode #endif Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { QFileInfo fi(*this); mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower(); } QString mname(mutexname); if (idx >= 0) mname += QString::number(idx); Qt::HANDLE mutex; if (doCreate) { QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; } } else { QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); return 0; } } return mutex; } bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { Q_ASSERT(mutex); DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); switch (res) { case WAIT_OBJECT_0: case WAIT_ABANDONED: return true; break; case WAIT_TIMEOUT: break; default: qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); } return false; } bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); if (!wmutex && !(wmutex = getMutexHandle(-1, true))) return false; if (!waitMutex(wmutex, block)) return false; if (mode == ReadLock) { int idx = 0; for (; idx < MAX_READERS; idx++) { rmutex = getMutexHandle(idx, false); if (!rmutex || waitMutex(rmutex, false)) break; CloseHandle(rmutex); } bool ok = true; if (idx >= MAX_READERS) { qWarning("QtLockedFile::lock(): too many readers"); rmutex = 0; ok = false; } else if (!rmutex) { rmutex = getMutexHandle(idx, true); if (!rmutex || !waitMutex(rmutex, false)) ok = false; } if (!ok && rmutex) { CloseHandle(rmutex); rmutex = 0; } ReleaseMutex(wmutex); if (!ok) return false; } else { Q_ASSERT(rmutexes.isEmpty()); for (int i = 0; i < MAX_READERS; i++) { Qt::HANDLE mutex = getMutexHandle(i, false); if (mutex) rmutexes.append(mutex); } if (rmutexes.size()) { DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0); if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { if (res != WAIT_TIMEOUT) qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky unlock(); return false; } } } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; if (m_lock_mode == ReadLock) { ReleaseMutex(rmutex); CloseHandle(rmutex); rmutex = 0; } else { foreach(Qt::HANDLE mutex, rmutexes) { ReleaseMutex(mutex); CloseHandle(mutex); } rmutexes.clear(); ReleaseMutex(wmutex); } m_lock_mode = QtLockedFile::NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); if (wmutex) CloseHandle(wmutex); } ukui-system-monitor/src/QtSingleApplication/qtlocalpeer.h0000644000175000017500000000520513746753570022672 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCALPEER_H #define QTLOCALPEER_H #include #include #include #include "qtlockedfile.h" class QtLocalPeer : public QObject { Q_OBJECT public: QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); bool isClient(); bool sendMessage(const QString &message, int timeout); QString applicationId() const { return id; } Q_SIGNALS: void messageReceived(const QString &message); protected Q_SLOTS: void receiveConnection(); protected: QString id; QString socketName; QLocalServer* server; QtLP_Private::QtLockedFile lockFile; private: static const char* ack; }; #endif // QTLOCALPEER_H ukui-system-monitor/src/QtSingleApplication/qtlocalpeer.cpp0000644000175000017500000001543413746753570023232 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include #include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegExp("[^a-zA-Z]")); prefix.truncate(6); QByteArray idc = id.toUtf8(); quint16 idNum = qChecksum(idc.constData(), idc.size()); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QString &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for(int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif } if (!connOk) return false; QByteArray uMsg(message.toUtf8()); QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); if (!socket) return; while (true) { if (socket->state() == QLocalSocket::UnconnectedState) { qWarning("QtLocalPeer: Peer disconnected"); delete socket; return; } if (socket->bytesAvailable() >= qint64(sizeof(quint32))) break; socket->waitForReadyRead(); } QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } QString message(QString::fromUtf8(uMsg)); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(message); //### (might take a long time to return) } ukui-system-monitor/src/QtSingleApplication/qtlockedfile.h0000644000175000017500000000630713746753570023031 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H #include #ifdef Q_OS_WIN #include #endif #if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) # if defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # endif # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) # elif defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) # endif #else # define QT_QTLOCKEDFILE_EXPORT #endif namespace QtLP_Private { class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: enum LockMode { NoLock = 0, ReadLock, WriteLock }; QtLockedFile(); QtLockedFile(const QString &name); ~QtLockedFile(); bool open(OpenMode mode); bool lock(LockMode mode, bool block = true); bool unlock(); bool isLocked() const; LockMode lockMode() const; private: #ifdef Q_OS_WIN Qt::HANDLE wmutex; Qt::HANDLE rmutex; QVector rmutexes; QString mutexname; Qt::HANDLE getMutexHandle(int idx, bool doCreate); bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif LockMode m_lock_mode; }; } #endif ukui-system-monitor/src/QtSingleApplication/QtSingleApplication0000644000175000017500000000004113746753570024034 0ustar fengfeng#include "qtsingleapplication.h" ukui-system-monitor/src/QtSingleApplication/qtlockedfile.cpp0000644000175000017500000001374213746753570023365 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" /*! \class QtLockedFile \brief The QtLockedFile class extends QFile with advisory locking functions. A file may be locked in read or write mode. Multiple instances of \e QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file. The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost. The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode This enum describes the available lock modes. \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() */ QtLockedFile::QtLockedFile() : QFile() { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in the same way as \e QFile::QFile(const QString&). \sa QFile::QFile() */ QtLockedFile::QtLockedFile(const QString &name) : QFile(name) { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Opens the file in OpenMode \a mode. This is identical to QFile::open(), with the one exception that the Truncate mode flag is disallowed. Truncation would conflict with the advisory file locking, since the file would be modified before the write lock is obtained. If truncation is required, use resize(0) after obtaining the write lock. Returns true if successful; otherwise false. \sa QFile::open(), QFile::resize() */ bool QtLockedFile::open(OpenMode mode) { if (mode & QIODevice::Truncate) { qWarning("QtLockedFile::open(): Truncate mode not allowed."); return false; } return QFile::open(mode); } /*! Returns \e true if this object has a in read or write lock; otherwise returns \e false. \sa lockMode() */ bool QtLockedFile::isLocked() const { return m_lock_mode != NoLock; } /*! Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. \sa isLocked() */ QtLockedFile::LockMode QtLockedFile::lockMode() const { return m_lock_mode; } /*! \fn bool QtLockedFile::lock(LockMode mode, bool block = true) Obtains a lock of type \a mode. The file must be opened before it can be locked. If \a block is true, this function will block until the lock is aquired. If \a block is false, this function returns \e false immediately if the lock cannot be aquired. If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock is first released and then a new lock is obtained. This function returns \e true if, after it executes, the file is locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() */ /*! \fn bool QtLockedFile::unlock() Releases a lock. If the object has no lock, this function returns immediately. This function returns \e true if, after it executes, the file is not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. */ ukui-system-monitor/src/QtSingleApplication/qtsingleapplication.cpp0000644000175000017500000002704613746753570024773 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" #include /*! \class QtSingleApplication qtsingleapplication.h \brief The QtSingleApplication class provides an API to detect and communicate with running instances of an application. This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server. By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead. The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal. The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot. If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode). If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen. Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that). \code // Original int main(int argc, char **argv) { QApplication app(argc, argv); MyMainWidget mmw; mmw.show(); return app.exec(); } // Single instance int main(int argc, char **argv) { QtSingleApplication app(argc, argv); if (app.isRunning()) return !app.sendMessage(someDataString); MyMainWidget mmw; app.setActivationWindow(&mmw); mmw.show(); return app.exec(); } \endcode Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance. For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library. \sa QtSingleCoreApplication */ void QtSingleApplication::sysInit(const QString &appId) { actWin = 0; peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a GUIenabled are passed on to the QAppliation constructor. If you are creating a console application (i.e. setting \a GUIenabled to false), you may consider using QtSingleCoreApplication instead. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) : QApplication(argc, argv, GUIenabled) { sysInit(); } /*! Creates a QtSingleApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) : QApplication(argc, argv) { sysInit(appId); } #if QT_VERSION < 0x050000 /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a type are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) : QApplication(argc, argv, type) { sysInit(); } # if defined(Q_WS_X11) /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be \a appId. \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(appId); } # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleApplication::id() const { return peer->applicationId(); } /*! Sets the activation window of this application to \a aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window. If \a activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted. \sa activateWindow(), messageReceived() */ void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) { actWin = aw; if (activateOnMessage) connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); else disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); } /*! Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0. \sa setActivationWindow() */ QWidget* QtSingleApplication::activationWindow() const { return actWin; } /*! De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set. This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance. This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set. \sa setActivationWindow(), messageReceived(), initialize() */ void QtSingleApplication::activateWindow() { if (actWin) { actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); actWin->raise(); actWin->showNormal(); actWin->activateWindow(); } } /*! \fn void QtSingleApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage(), setActivationWindow(), activateWindow() */ /*! \fn void QtSingleApplication::initialize(bool dummy = true) \obsolete */ ukui-system-monitor/src/QtSingleApplication/qtsinglecoreapplication.cpp0000644000175000017500000001235513746753570025641 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" /*! \class QtSingleCoreApplication qtsinglecoreapplication.h \brief A variant of the QtSingleApplication class for non-GUI applications. This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library. The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage. A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application. \sa QtSingleApplication */ /*! Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleCoreApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleCoreApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleCoreApplication::id() const { return peer->applicationId(); } /*! \fn void QtSingleCoreApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage() */ ukui-system-monitor/src/QtSingleApplication/QtLockedFile0000644000175000017500000000003213746753570022430 0ustar fengfeng#include "qtlockedfile.h" ukui-system-monitor/src/QtSingleApplication/qtlockedfile_unix.cpp0000644000175000017500000000661413746753570024430 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "qtlockedfile.h" bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; int cmd = block ? F_SETLKW : F_SETLK; int ret = fcntl(handle(), cmd, &fl); if (ret == -1) { if (errno != EINTR && errno != EAGAIN) qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = F_UNLCK; int ret = fcntl(handle(), F_SETLKW, &fl); if (ret == -1) { qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); } ukui-system-monitor/src/translation/0000755000175000017500000000000013764070001016605 5ustar fengfengukui-system-monitor/src/translation/ukui-system-monitor_de.qm0000644000175000017500000000002713746753504023617 0ustar fengfeng O wkziΉpqJII3]ϕf߶߶ba P l v  vk l L w6  $ t ܊ n { n  X X yj: R y L %1t .KCyڍiR7eRefreshFileSystemDialogSu( AvailableFileSystemListWidgetYDeviceFileSystemListWidget_ DirectoryFileSystemListWidgetzzFreeFileSystemListWidgetlg SseN|~O`oNo File System InfoFileSystemListWidget`;[TotalFileSystemListWidget|{WTypeFileSystemListWidget]u(UsedFileSystemListWidget m;Rvz Active ProcessesMonitorTitleWidgetQhz  All ProcessMonitorTitleWidgetd}""Enter the relevant info of processMonitorTitleWidgeteN|~ File SystemsMonitorTitleWidget |~vщVhKylin System MonitorMonitorTitleWidgetbvz  My ProcessesMonitorTitleWidgetz  ProcessesMonitorTitleWidgetDn ResourcesMonitorTitleWidgetQscloseMonitorTitleWidget gY'S/Smaximize/restoreMonitorTitleWidgetg\SminimizeMonitorTitleWidget CPUSS CPU historyNewResouresDialogQ[XTNcbzzSSmemory and swap historyNewResouresDialogQ[X:memory:NewResouresDialogQ~SSnet work historyNewResouresDialogce6:receive:NewResouresDialogSѐ:send:NewResouresDialog Ncbzz:swap:NewResouresDialog m;Rvz Active ProcessesProcessCategoryQhz  All ProcessesProcessCategorybvz  My ProcessesProcessCategorySmCancel ProcessDialog e9SOQH~Change Priority ProcessDialog(fe9z %1 (PID%2)vOQH~'Change Priority of Process %1 (PID: %2) ProcessDialog~~z Continue process ProcessDialog[NICustom ProcessDialog~g_z  End process ProcessDialogb~g_z S[epcnc_WO N-eOb^&ge[QhΖi0`^S~g_eT^vz 0 `xn[~~dO\Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? ProcessDialogHigh ProcessDialogg@k{z  Kill process ProcessDialogbg@k{z S[epcnc_WO N-eOb^&ge[QhΖi0`^Sg@k{eT^vz 0 `xn[~~dO\Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? ProcessDialogONLow ProcessDialogfnNormal ProcessDialog\^`' Properties ProcessDialogP\kbz  Stop process ProcessDialog^^8 Very High ProcessDialog^^8ONVery Low ProcessDialogeS^ No responseProcessListItem]P\kbStoppedProcessListItemP\kbSuspendProcessListItemN SN-eUninterruptibleProcessListItemPk{ZombieProcessListItem%CPUCPUProcessListWidgetxvDiskProcessListWidgetQ~Flownet PersecProcessListWidgetIDIDProcessListWidgetQ[XMemoryProcessListWidget ed}"~gNo search resultProcessListWidgetOQH~PriorityProcessListWidgetz T y Process NameProcessListWidgetu(b7T UserProcessListWidget^.Ru(b7{tz Help user to kill processProcessManager |~vщVhSystem MonitorProcessManagerxn[OKPropertiesDialogCPU e CPU Time:QObjectT}NL Command line:QObjectGiBGiBQObject GiB/yGiB/sQObjectHighQObjectOQH~ High PriorityQObjectKBKiBQObjectKB/yKiB/sQObjectONLowQObjectONOQH~ Low PriorityQObjectMiBMiBQObject MiB/yMiB/sQObjectfnNormalQObject fnOQH~Normal PriorityQObjectz T  Process name:QObjectЈLN-RunningQObjectwaw N-SleepingQObject_YN Started Time:QObject]P\kbStoppedQObjectTiBTiBQObject TiB/yTiB/sQObjectN SN-eUninterruptibleQObjectu(b7T  User name:QObject^^8 Very HighQObject ^^8OQH~Very High PriorityQObject^^8ONVery LowQObject ^^8ONOQH~Very Low PriorityQObjectPk{ZombieQObjectSmCancel ReniceDialog e9SOQH~Change Priority ReniceDialogNice P< Nice value: ReniceDialogY_Note: ReniceDialogLz vOQH~u1[v nice P CpuRateWidget CPU Occupancy rate Idle rate The running time of system The idle time of system FileSystemDialog Refresh FileSystemListWidget Device Directory Type Total Free Available Used No File System Info MemoryCircle Memory Swap Used(Percent) Total %1(%2%) MemoryWidget Memory MonitorTitleWidget Active Processes My Processes All Process UKUI System Monitor :/img/minimize.png :/img/fullscreen.png :/img/close.png Processes Resources File Systems Enter the relevant info of process NetworkFlow Receiving Total Received Sending Receive Send Total Sent NetworkWidget Network ProcessCategory Active Processes My Processes All Processes ProcessDialog End process Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Cancel Kill process Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Stop process Continue process Very High High Normal Low Very Low Custom Change Priority Properties Change Priority of Process %1 (PID: %2) ProcessListItem Stopped Suspend Zombie No response Uninterruptible ProcessListWidget Process Name User Status CPU ID Command Line Memory Priority No search result ProcessManager System Monitor Help user to kill process PropertiesDialog OK QObject Running Stopped Zombie Uninterruptible Sleeping Very High High Normal Low Very Low Very High Priority High Priority Normal Priority Low Priority Very Low Priority byte byte/s bytes bytes/s KiB KiB/s MiB MiB/s GiB GiB/s TiB TiB/s %1hours %1hour %1minutes %1minute %1seconds %1second %1day %1days User name: Process name: Command line: CPU Time: Started Time: ReniceDialog Nice value: Note: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Cancel Change Priority ResourcesCategory CPU Memory Network SystemMonitor UKUI System Monitor ukui-system-monitor/src/translation/ukui-system-monitor_es.ts0000644000175000017500000006067213746753504023663 0ustar fengfeng CpuRateWidget CPU Occupancy rate Idle rate The running time of system The idle time of system FileSystemDialog Refresh FileSystemListWidget Device Directory Type Total Free Available Used No File System Info MemoryCircle Memory Swap Used(Percent) Total %1(%2%) MemoryWidget Memory MonitorTitleWidget Active Processes My Processes All Process UKUI System Monitor :/img/minimize.png :/img/fullscreen.png :/img/close.png Processes Resources File Systems Enter the relevant info of process NetworkFlow Receive Send Receiving Sending Total Received Total Sent NetworkWidget Network ProcessCategory Active Processes My Processes All Processes ProcessDialog End process Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Cancel Kill process Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Stop process Continue process Very High High Normal Low Very Low Custom Change Priority Properties Change Priority of Process %1 (PID: %2) ProcessListItem Stopped Suspend Zombie No response Uninterruptible ProcessListWidget Process Name User Status CPU ID Command Line Memory Priority No search result ProcessManager System Monitor Help user to kill process PropertiesDialog OK QObject %1hours %1hour %1minutes %1minute %1seconds %1second %1day %1days byte bytes KiB MiB GiB TiB byte/s bytes/s KiB/s MiB/s GiB/s TiB/s User name: Process name: Command line: CPU Time: Started Time: Running Stopped Zombie Uninterruptible Sleeping Very High High Normal Low Very Low Very High Priority High Priority Normal Priority Low Priority Very Low Priority ReniceDialog Nice value: Note: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Cancel Change Priority ResourcesCategory CPU Memory Network SystemMonitor UKUI System Monitor ukui-system-monitor/src/translation/ukui-system-monitor_bo.ts0000644000175000017500000006067213746753504023654 0ustar fengfeng CpuRateWidget CPU Occupancy rate Idle rate The running time of system The idle time of system FileSystemDialog Refresh FileSystemListWidget Device Directory Type Total Free Available Used No File System Info MemoryCircle Memory Swap Used(Percent) Total %1(%2%) MemoryWidget Memory MonitorTitleWidget Active Processes My Processes All Process UKUI System Monitor :/img/minimize.png :/img/fullscreen.png :/img/close.png Processes Resources File Systems Enter the relevant info of process NetworkFlow Receive Send Receiving Sending Total Received Total Sent NetworkWidget Network ProcessCategory Active Processes My Processes All Processes ProcessDialog End process Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Cancel Kill process Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Stop process Continue process Very High High Normal Low Very Low Custom Change Priority Properties Change Priority of Process %1 (PID: %2) ProcessListItem Stopped Suspend Zombie No response Uninterruptible ProcessListWidget Process Name User Status CPU ID Command Line Memory Priority No search result ProcessManager System Monitor Help user to kill process PropertiesDialog OK QObject %1hours %1hour %1minutes %1minute %1seconds %1second %1day %1days byte bytes KiB MiB GiB TiB byte/s bytes/s KiB/s MiB/s GiB/s TiB/s User name: Process name: Command line: CPU Time: Started Time: Running Stopped Zombie Uninterruptible Sleeping Very High High Normal Low Very Low Very High Priority High Priority Normal Priority Low Priority Very Low Priority ReniceDialog Nice value: Note: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Cancel Change Priority ResourcesCategory CPU Memory Network SystemMonitor UKUI System Monitor ukui-system-monitor/src/translation/ukui-system-monitor_tr.qm0000644000175000017500000002263213746753504023662 0ustar fengfengw3lkJzvΉCqJeI IQ] ;ϕ !bW  İ P W . l v v l\ 2 2!M  P ܊ n n& X X yjz R = - yL  > %1t.ڍi!0_lemciCPU CpuRateWidgetBo_luk oran1 Idle rate CpuRateWidgetDoluluk oran1Occupancy rate CpuRateWidget6Sistemin bo_ta kalma sresiThe idle time of system CpuRateWidget.Sistemin al1_ma sresiThe running time of system CpuRateWidget YenileRefreshFileSystemDialog Mevcut AvailableFileSystemListWidget Ayg1tDeviceFileSystemListWidget Dizin DirectoryFileSystemListWidgetBo_FreeFileSystemListWidget2Dosya Sistemi Bilgisi YokNo File System InfoFileSystemListWidget ToplamTotalFileSystemListWidgetTrTypeFileSystemListWidgetKullan1lanUsedFileSystemListWidget%1(%2%) MemoryCircle Haf1zaMemory MemoryCircleSwapSwap MemoryCircle ToplamTotal MemoryCircle"Kullan1lan(Yzde) Used(Percent) MemoryCircle Haf1zaMemory MemoryWidget:/img/close.pngMonitorTitleWidget:/img/fullscreen.pngMonitorTitleWidget:/img/minimize.pngMonitorTitleWidgetAktif SrelerActive ProcessesMonitorTitleWidgetTm 0_lemler All ProcessMonitorTitleWidget<0_lemle ilgili bilgileri girin"Enter the relevant info of processMonitorTitleWidgetDosya Sistemi File SystemsMonitorTitleWidgetSrelerim My ProcessesMonitorTitleWidgetSreler ProcessesMonitorTitleWidgetKaynaklar ResourcesMonitorTitleWidget&Ukui Sistem MonitorUKUI System MonitorMonitorTitleWidget Al1nanReceive NetworkFlowAl1n1yor Receiving NetworkFlow GnderSend NetworkFlowGnderiliyorSending NetworkFlowToplam Al1nanTotal Received NetworkFlow"Toplam Gnderilen Total Sent NetworkFlowANetwork NetworkWidgetAktif SrelerActive ProcessesProcessCategoryTm Sreler All ProcessesProcessCategorySrelerim My ProcessesProcessCategory 0ptalCancel ProcessDialog"ncelii Dei_tirChange Priority ProcessDialogR%1 Srecinin nceliini Dei_tir (PID:%2)'Change Priority of Process %1 (PID: %2) ProcessDialog0_leme devam etContinue process ProcessDialogzelCustom ProcessDialog0_lemi bitir End process ProcessDialogtBir i_lemi sonland1rmak verileri yok edebilir, oturumu bozabilir veya gvenlik riski olu_turabilir. Sadece tepkisiz sreler sona erdirilmelidir. Devam etmek istediinizden emin misiniz?Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? ProcessDialog YksekHigh ProcessDialog0_lemi ldr Kill process ProcessDialogbBir i_lemi ldrmek verileri yok edebilir, oturumu bozabilir veya gvenlik riski olu_turabilir. Sadece tepkisiz sreler ldrlmelidir. Devam etmek istediinizden emin misiniz?Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? ProcessDialog D_kLow ProcessDialog NormalNormal ProcessDialogzellikler Properties ProcessDialog0_lemi durdur Stop process ProcessDialogok Yksek Very High ProcessDialogok d_kVery Low ProcessDialogCevap yok No responseProcessListItemDurdurulduStoppedProcessListItemAsk1ya alSuspendProcessListItemKesintisizUninterruptibleProcessListItemZombieProcessListItem0_lemciCPUProcessListWidgetKomut Sat1r1 Command LineProcessListWidgetIDIDProcessListWidget Haf1zaMemoryProcessListWidget Arama sonucu yokNo search resultProcessListWidgetncelikPriorityProcessListWidget0_lem Ad1 Process NameProcessListWidget DurumStatusProcessListWidgetKullan1c1UserProcessListWidgetZKullan1c1n1n i_lemi ldrmesine yard1mc1 olunHelp user to kill processProcessManagerSistem MonitorSystem MonitorProcessManager TamamOKPropertiesDialog%1dayQObject%1daysQObject%1hourQObject%1hoursQObject%1minuteQObject %1minutesQObject%1secondQObject %1secondsQObject CPU Time:QObject Command line:QObjectGBGiBQObjectGB/sGiB/sQObject YksekHighQObjectYksek ncelik High PriorityQObjectKBKiBQObjectKB/sKiB/sQObject D_kLowQObjectD_k ncelik Low PriorityQObjectMBMiBQObjectMB/sMiB/sQObject NormalNormalQObjectNormal ncelikNormal PriorityQObject Process name:QObjectYrtlyorRunningQObject UyuyorSleepingQObject Started Time:QObjectDurdurulduStoppedQObjectTBTiBQObjectTB/sTiB/sQObjectKesintisizUninterruptibleQObject User name:QObjectok Yksek Very HighQObject$ok Yksek ncelikVery High PriorityQObjectok D_kVery LowQObject"ok D_k ncelikVery Low PriorityQObjectlZombieQObjectbaytbyteQObjectbyte/sQObjectbytesQObjectbytes/sQObject 0ptalCancel ReniceDialog"ncelii Dei_tirChange Priority ReniceDialogGzel deer: Nice value: ReniceDialogNot:Note: ReniceDialogBir srecin ncelii ho_ deeri ile verilir. Daha d_k bir ho_ deer daha yksek bir ncelie kar_1l1k gelir.jThe priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. ReniceDialog0_lemciCPUResourcesCategory Haf1zaMemoryResourcesCategoryANetworkResourcesCategory&Ukui Sistem MonitorUKUI System Monitor SystemMonitorukui-system-monitor/src/translation/ukui-system-monitor_de.ts0000644000175000017500000006067213746753504023644 0ustar fengfeng CpuRateWidget CPU Occupancy rate Idle rate The running time of system The idle time of system FileSystemDialog Refresh FileSystemListWidget Device Directory Type Total Free Available Used No File System Info MemoryCircle Memory Swap Used(Percent) Total %1(%2%) MemoryWidget Memory MonitorTitleWidget Active Processes My Processes All Process UKUI System Monitor :/img/minimize.png :/img/fullscreen.png :/img/close.png Processes Resources File Systems Enter the relevant info of process NetworkFlow Receiving Total Received Sending Receive Send Total Sent NetworkWidget Network ProcessCategory Active Processes My Processes All Processes ProcessDialog End process Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Cancel Kill process Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Stop process Continue process Very High High Normal Low Very Low Custom Change Priority Properties Change Priority of Process %1 (PID: %2) ProcessListItem Stopped Suspend Zombie No response Uninterruptible ProcessListWidget Process Name User Status CPU ID Command Line Memory Priority No search result ProcessManager System Monitor Help user to kill process PropertiesDialog OK QObject Running Stopped Zombie Uninterruptible Sleeping Very High High Normal Low Very Low Very High Priority High Priority Normal Priority Low Priority Very Low Priority byte byte/s bytes bytes/s KiB KiB/s MiB MiB/s GiB GiB/s TiB TiB/s %1hours %1hour %1minutes %1minute %1seconds %1second %1day %1days User name: Process name: Command line: CPU Time: Started Time: ReniceDialog Nice value: Note: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Cancel Change Priority ResourcesCategory CPU Memory Network SystemMonitor UKUI System Monitor ukui-system-monitor/src/translation/ukui-system-monitor_bo.qm0000644000175000017500000000002013746753504023620 0ustar fengfeng AboutDialog About us 关于我们 Kylin Assistant 麒麟助手 About 关于本软件 关于 Maintainer: Kylin Team <ubuntukylin-members@list.launchpad.net> 维护者: 麒麟团队 <ubuntukylin-members@list.launchpad.net> Kylin Assistant is a powerful system supporting software which is developed by Kylin team. Mainly for the naive user, it can help users manage the system. At present, It provides system junk scanning and cleaning, viewing the system hardware and software information, task manager, and some other functions. 麒麟助手是由麒麟团队开发的一款功能强大的系统辅助软件。主要面向初级用户,能够帮助用户对系统进行管理。目前已具备了系统垃圾扫描与清理、系统软硬件信息查看、系统全方位定制、任务管理器等功能。 for more information. Welcome everyone to join with us. ukui-system-monitor Homepage: 了解软件的最新进展并反馈问题,欢迎广大用户和爱好者一起参与。麒麟助手主页: The software is still under development. Please visit 各项功能还在不断完善,更多功能也将陆续开发,敬请关注 Ubuntu Kylin 官网 Contributor 贡献者 Close 关闭 关闭 BoxWidget Kylin Software Center 麒麟软件中心 No software center was found! 没有找到软件中心 ! CleanSubGroup Custom 自定义 CleanerDetailWidget Apt Cache Clean Items Apt缓存清理项 Apt Cache count: Apt缓存总数: Software Cache Clean Items 软件中心缓存清理项 Software Cache count: 软件中心缓存总数: Thumbnails Cache Clean Items 缩略图缓存清理项 Thumbnails Cache Count: 缩略图缓存总数: Firefox Cache Count: Firefox浏览器缓存总数: Chromium Cache Count: Chromium浏览器缓存总数: Firefox Cookies Clean Items Firefox Cookies 清理项 Firefox Cookies Count: Firefox Cookies总数: Chromium Cookies Clean Items Chromium Cookies 清理项 Chromium Cookies Count: Chromium Cookies总数: No garbage 没有扫描到垃圾 Firefox History Count: Firefox 历史记录总数: Chromium History Count: Chromium历史记录总数: System History Count: 系统历史痕迹总数: Command history size: 命令历史记录大小: Firefox Cache Clean Items Firefox 缓存清理项 Chromium Cache Clean Items Chromium 缓存清理项 Debug log Items 调试日志项 Debug log: 调试日志: Clean args is empty! 清理参数为空! CleanerMainWidget Cleans up cache of system 清理系统缓存 Cleans up cookies in browser 清理浏览器缓存 Cleans up records of history 清理历史记录 Cleanup Package Cache 清理包缓存 Cleanup Software Center Cache 清理软件中心缓存 Cleanup Thumbnails Cache 清理缩略图缓存 Cleanup FireFox Cache 清理火狐浏览器缓存 Cleanup Chromium Cache 清理chromium缓存 Cache Items 缓存选项 System Cache 系统缓存 Cleanup cache of system, software-center, thumbnails and browser 清除包、缩略图和浏览器缓存等 Cleanup the Cookies saving in Firefox 清理火狐浏览器的Cookies Cleanup the Cookies saving in Chromium 清理Chromium浏览器的Cookies Cookies Items Cookies选项 Cookies Cookies Clean up user login information, support Firefox and Chromium browser 清除上网、游戏、购物等记录 Clean up the Firefox Internet records 清理火狐访问记录 Clean up the Chromium Internet records 清理Chromium访问记录 Clean up the recently opened documents records 清理最近打开的文件记录 Delete the command history 删除命令历史记录 Delete the debug logs 删除调试日志 Trace Items 访问痕迹选项 History trace 历史痕迹 Cleaning the internet and opened documents recently records 清除浏览器和系统使用痕迹 Please select the items you want to clean 请选择您想清理的选项 Scan args is empty! 扫描参数为空! CpuRateWidget CPU 处理器 Occupancy rate 占用率 Idle rate 空闲率 The running time of system 系统运行时间 The idle time of system 系统空闲时间 EnergyWidget CPU FM mode: CPU调频模式: Ondemand 自动调频 Powersave 省电模式 Performance 性能模式 Adjust gamma 调整伽马值 Adjust brightness 调整屏幕亮度 Time before session is considered idle 在此时间范围内无操作则关闭屏幕 Lock screen 锁定屏幕 Lock delay 锁定延时 Battery critical low action 电池严重不足时 Laptop lid close action on battery 使用电池合上盖子时 Laptop lid close action on AC 使用电源合上盖子时 Sleep timeout PC when on battery 使用电池,空闲此时间后电脑转入睡眠 Sleep timeout PC when on AC 使用电源,空闲此时间后电脑转入睡眠 Sleep timeout display when on battery 使用电池,空闲此时间后屏幕转入睡眠 Sleep timeout display when on AC 使用电源,空闲此时间后屏幕转入睡眠 suspend 挂起 shutdown 电源关闭 nothing 不处理 5 minutes 5 分钟 10 minutes 10 分钟 20 minutes 20 分钟 Half an hour 半小时 1 hour 1 小时 2 hours 2 小时 never 从不 1 minute 1 分钟 2 minutes 2 分钟 3 minutes 3 分钟 30 seconds 30 秒 Turn off the screen 关闭屏幕 FileManagerWidget Display entry location 路径输入框取代路径栏 Automatically mount media 自动挂载媒体 Automatically open a folder 自动打开文件夹 Prompt autorun programs 提示自动运行的程序 Thumbnail icon size (pixels) 缩略图图标尺寸(像素) Thumbnail cache time (days) 缩略图缓存时间(天数) Maximum thumbnail cache size (MB) 最大缩略图缓存尺寸(MB) FileSystemDialog Refresh 刷新 FileSystemListWidget Device 设备 Directory 路径 Type 类型 Total 总容量 Free 空闲 Available 可用 Used 已用 No File System Info 没有发现文件系统信息 FontWidget Click here to change font 点击此处更换字体 Default Font 默认字体 Desktop Font 桌面字体 Monospace Font 等宽字体 Document Font 文档字体 Titlebar Font 标题栏字体 Global Font Scaling 全局字体缩放 Hinting 平滑 Antialiasing 反锯齿 Restore 恢复默认 IconWidget Icon theme 图标主题 Computer 计算机 Home Folder 用户主目录 Network 网络 Trash 回收站 Mounted Volumes 挂载卷 InfoGui Failed to obtain information 获取信息失败 InfoWidget Computer 电脑概述 Desktop 桌面环境 CPU 处理器 Memory 内存 Motherboard 主板 HD 硬盘 NIC 网卡 VGA 显卡 Audio 声卡 Computer Info 电脑概述 Desktop Info 桌面环境信息 CPU Info 处理器信息 Memory Info 内存条信息 Memory Info %1 内存信息 %1 Board Info 主板信息 HardWare Info 硬盘信息 HardWare Info %1 硬盘信息 %1 NIC Info 网卡信息 NIC Info %1 网卡信息 %1 Monitor Info 显示器和显卡信息 Monitor Info %1 显示器和显卡信息 %1 Audio Info 声卡信息 Audio Info %1 声卡信息%1 Battery Info 电池信息 Driver Info 驱动信息 Battery 电池 Device Driver 设备驱动 Sensor 硬件传感 KylinFontDialog Current Font 当前字体 Font 字体 Style 风格 Size 大小 View 视图 OK 确定 Cancel 取消 Tips 提示 You haven't change the font, please choose the font! 您没有更改字体,请选择需要更改的字体! Font Dialog 字体对话框 KylinMenu Check and update 检查更新 Forum Help 论坛求助 Feedback 问题反馈 About us 关于我们 KylinSwitcher ON 已开启 OFF 已关闭 MainBottomWidget Current Version Number 当前版本号 Update to the lastest version, make it work better 更新至最新版本,使软件更好用 updating on the backend 正在后台升级 Common toolbox 工具箱 Fast and practical, making the system more personalized 更快更好,让系统更具个性化 Upgrade is complete 升级完成 Updating on the backend 正在后台升级 MainTopWidget The lastest cleanup time is 上一次清理时间是 The lastest scan time is 上一次扫描时间是 You have not implemented the one key scan and clean-up operation. 您还没有执行过一键扫描和一键清理操作。 Kylin Assistant 麒麟助手 Start Scan 开始扫描 Start Cleanup 开始清理 Back 返回 Scanning...... 正在扫描..... Quick clean up system trash, saving disk space and improving the system efficiency! 一键清理系统垃圾,帮您节省磁盘空间,让系统运行更加有效率! Scan Over 扫描完成 Regular cleaning, let your computer remains the relaxed state 经常清理,让电脑保持最轻松的状态 Scans 扫描 Cleans up 清理 Cleans up history and caches 清理历史记录及系统缓存 Clean OK 清理完毕 Cleaning: 正在清理: , Percent is: ,进度为: %, Status is: %,状态为: Clean Firefox history...... 清理Firefox浏览器历史记录...... Clean Chromium history...... 清理Chromium浏览器历史记录...... Clean system history...... 清理系统历史痕迹...... Clean apt...... 清理Apt...... Start clean apt...... 开始清理Apt...... Clean Firefox Cookie: 清理Firefox浏览器Cookie: Clean Chromium Cookie: 清理Chromium浏览器Cookie: does not exist 不存在 Chromium Browser is running...... Chromium浏览器正在运行中...... Cache Scan OK 缓存扫描完成 Cookies Scan OK Cookies扫描完成 History Scan OK 历史记录扫描完成 Packages Scan OK 包扫描完成 Error: 错误: Firefox Browser does not be installed 没有安装Firefox浏览器 Chromium Browser does not be installed 没有安装Chromium浏览器 Chromium Browser is running Chromium浏览器正在运行中 Scanning: 正在扫描: history trace; 条历史痕迹; browser cookies. 条浏览器Cookies。 browser cookies; 条浏览器Cookies; garbage. 垃圾。 history trace. 条历史痕迹。 No garbage. 没有扫描到垃圾。 Cleaning...... 正在清理....... Garbage Cleanup OK...... 垃圾清理完成...... History Cleanup OK...... 历史记录清理完成...... Cookies Cleanup OK...... Cookies清理完成...... Cleanup Cookies: 清理了Cookies: ; Garbage: ;垃圾: ; Historical records: ;历史记录: Cleaning up history trace of Firefox... 正在清理Firefox浏览器的历史痕迹...... Firefox history trace had been cleared! Firefox浏览器历史痕迹清理完成! Cleaning up history trace of Chromium... 正在清理Chromium浏览器的历史痕迹...... Chromium history trace had been cleared! Chromium浏览器的历史痕迹清理完成! Cleaning up Cookies of Firefox... 正在清理Firefox浏览器的Cookies...... Firefox Cookies had been cleared! Firefox浏览器的Cookies清理完成! Cleaning up Cookies of Chromium... 正在清理Chromium浏览器的Cookies...... Chromium Cookies had been cleared! Chromium浏览器的Cookies清理完成! Apt cache had been cleared! Apt缓存清理完成! Cleaning up Apt cache: 正在清理Apt缓存: Software Center cache had been cleared! 软件中心缓存清理完成! Cleaning up Software Center cache: 正在清理软件中心缓存: Ready to Cleanup...... 准备清理...... MainWindow Kylin Assistant 麒麟助手 Understand hardware information, provide more convenient channel to obtain hardware information 了解电脑硬件详细信息,为用户提供更加方便的获取硬件信息渠道 perform a full range of customizations systems based on your own personal preferences 根据个人喜好对系统进行全方位的定制 Provides lightweight tool and creates fast and convenient experience 提供轻量化工具,打造快捷方便的体验 You can perform a full range of customized systems based on personal preferences 您可以根据个人喜好对系统进行全方位的定制 Provide a practical and lightweight tool, create fast and convenient experience for you 提供轻巧使用工具,为您打造快捷方便的体验 MemoryCircle Memory 内存 Swap 交换 Used(Percent) 已使用(百分比) Total 总量 MemoryWidget Memory 内存 MenuWidget Launcher icon size 启动器图标尺寸 Launcher hide mode 启动器自动隐藏 Display desktop icon 显示桌面图标 Launcher Transparency 启动器透明度 Icon Background 图标背景 Top panel icon size 顶部面板图标大小 Top panel auto hide 顶部面板自动隐藏 Bottom panel icon size 底部面板图标大小 Bottom panel auto hide 底部面板自动隐藏 Launcher position 启动器位置 MiddleWidget Home 麒麟首页 Cleanup 系统清理 Sysinfo 系统信息 Feature 系统美化 Toolkits 功能大全 MonitorTitleWidget Active Processes 活动的进程 My Processes 我的进程 All Process 全部进程 Kylin System Monitor 系统监视器 minimize 最小化 maximize/restore 最大化/还原 close 关闭 Processes 进程 Resources 资源 File Systems 文件系统 Cancel 取消 Enter the relevant info of process 搜索 MouseWidget Mouse Pointer Theme 鼠标指针主题 Cursor Pointer Size 光标指针大小 Small Size 小号 Big Size 大号 NetworkFlow Receiving 正在接收 Total Received 总计已接收 Sending 正在发送 Receive 接收 Send 发送 Total Sent 总计已发送 NetworkIndicator net 网络 recv: 接收: send: 发送: NetworkWidget Network 网络 NewResouresDialog 10Mib 7.5Mib 5.0Mib 2.5Mib 0.0Mib 1000Byte 750Byte 500Byte 250Byte 0Byte 20Kib 15Kib 10Kib 5Kib 0Kib 100Kib 75Kib 50Kib 25Kib 1000Kib 750Kib 500Kib 250Kib memory: 内存: swap: 交换空间: receive: 接收: send: 发送: CPU history CPU历史 memory and swap history 内存和交换空间历史 net work history 网络历史 PanelWidget Dash background blur type 搜索框背景模糊类型 Panel Transparency 面板透明度 Date & time format 日期时间格式 Display seconds 显示秒数 Display week 显示星期 Display the date 显示日期 Display battery icon 显示电池图标 Display battery percentage 显示电池百分比 Display battery remaining time 显示电池电量时间 Smart blur 活动模糊 Static blur 静态模糊 Clear 非模糊 Show applications 显示应用程序 Show system 显示系统 Show places 显示位置 Show icon 显示图标 ProcessCategory Active Processes 活动的进程 My Processes 我的进程 All Processes 全部进程 ProcessDialog End process 结束进程 Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? 结束进程可能导致数据损坏,中断会话或带来安全风险。您应该只结束无响应的进程。 您确定要继续该操作? Cancel 取消 Kill process 杀死进程 Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? 杀死进程可能导致数据损坏,中断会话或带来安全风险。您应该只杀死无响应的进程。 您确定要继续该操作? Stop process 停止进程 Continue process 继续进程 Very High 非常高 High Normal 普通 Low Very Low 非常低 Custom 自定义 Change Priority 改变优先级 Properties 属性 Change Priority of Process %1 (PID: %2) 更改进程“%1”(PID:%2)的优先级 ProcessListItem Stopped 已停止 Suspend 停止 Zombie 僵死 No response 无反应 Uninterruptible 不可中断 ProcessListWidget Process Name 进程名称 User 用户名 Status 状态 CPU %CPU ID ID Flownet Persec 网络 Memory 内存 Disk 磁盘 Priority 优先级 No search result 无搜索结果 ProcessManager System Monitor 系统监视器 Help user to kill process 帮助用户管理进程 PropertiesDialog OK 确定 QObject Running 运行中 Stopped 已停止 Zombie 僵死 Uninterruptible 不可中断 Sleeping 睡眠中 Very High 非常高 High Normal 普通 Low Very Low 非常低 Very High Priority 非常高优先级 High Priority 高优先级 Normal Priority 普通优先级 Low Priority 低优先级 Very Low Priority 非常低优先级 Choose the theme what you want 选择您需要的主题 Set the desktop icon theme and the visibility of desktop icons 设置桌面图标主题和桌面图标的可见性 Replace the theme and size of the mouse pointer, and theme change need to restart system 更换鼠标指针主题和大小,主题更改需要重启系统才能生效 Set the sound theme you want 设置您需要的声音主题 Setting the panel mode of auto hide and icon size 设置面板自动隐藏模式和面板图标大小 Manage display of the start menu 管理启动菜单的显示 Window Manager settings 窗口管理器设置 According to personal preferences to set the system default font, click the 'Restore' button, can be restored to the state before the font settings 根据个人喜好设置系统默认字体,单击"恢复默认"按钮,可以将对应的字体恢复到设置前状态 Setting the relevant properties of your touchpad,make the operation more convenient 通过调整您触摸板的相关设置,使操作更加便捷 Save energy to let the computer longer standby time 节省电量,让电脑待机时间更长 Manage the file manager. Tips: if the thumbnail's cache time or size is set to -1, it will not be checked 管理文件管理器。注意:如果缩略图缓存时间或尺寸被设置为-1,缩略图将不会被清理 Audio Model 声卡型号 Vendor 制造商 Bus Address 总线地址 Audio Driver 声卡驱动 Device Name 设备名 Manufacturer 发行商 Model 型号 Technology 技术 Voltage 电压 Energy Designed 能量(设计) Energy Full 满时能量 Energy Now 能量 Serial Number 序列号 Motherboard Model 主板型号 Motherboard Vendor 主板产商 BIOS Vendor BIOS产商 BIOS Version BIOS版本 Release Date 发布日期 CD-ROM Model 光驱型号 Firmware Version 固件版本 CPU 处理器 Socket/Slot 插座/插槽 Maximum Frequency 最大主频 Current Frequency 当前主频 FSB 前端总线 Core Number 核心数目 Thread 线程 L1 Cache 1级缓存 L2 Cache 2级缓存 phytium 飞腾 4 cores 4核 4 thread/core 4线程/核 Desktop Environment 桌面环境 Host Name 主机名 Memery Capacity 内存容量 Terminal 用户命令解释器 Distribution 发行版 Language 语言 User 用户 Home Folder 用户主目录 Host bridge 主桥 VGA Model VGA兼容控制器 USB Model USB控制器 Communication Model 通信控制器 Ethernet Model 以太网控制器 PCI bridge PCI桥 ISA bridge ISA桥 SATA Model SATA控制器 SMBus 系统管理总线 System peripheral 系统外围 Driver in use 使用的驱动 existing drivers 可选的驱动 IDE interface IDE接口 SP controller 信号处理控制器 Network controller 网络控制器 Multimedia audio controller 多媒体音频控制器 HDD Model 硬盘型号 HDD Vendor 硬盘厂商 HDD Capacity 硬盘容量 Slot Number 插槽号 Memory Model 内存型号 Memory Size 内存大小 Data Width 数据宽度 Memory Info 内存条信息 Graphics Card Model 显卡型号 Current Graphics Card 当前显卡 Graphics Card Vendor 显卡制造商 Graphics Driver 显卡驱动 Gamma 伽马值 Screen Size(inch) 屏幕尺寸(英寸) Max Resolution 最大分辨率 Current Interface 当前接口 Monitor Model 显示器型号 Visual Area 可视面积 Support Interface 支持接口 Monitor Manufacturers 显示器制造商 Date of production/Week 生产日期/周 Date of production/Year 生产日期/年 NIC Model 网卡型号 NIC Driver 网卡驱动 IP Address IP地址 Mac Address MAC地址 Connection Status 连接状态 Max Bandwidth 最大带宽 WLan NIC Driver 无线网卡驱动 WLan NIC Model 网卡型号 Device Name: 设备名称: VNIC 虚拟网卡 NetType 网卡类型 Ethernet interface 以太网接口 Wireless interface 无线网接口 Version 电脑版本 Hostname 主机名 Running Time 持续运行时间 OS Types 操作系统类型 OS Version 操作系统版本 Kernel Bit 系统位数 Kernel Version 内核版本 Kernel Arch 内核架构 32bit 32位 64bit 64位 YHKylin community 银河麒麟社区版 Memory reference voltage 内存参考电压 SATA controller voltage SATA控制器电压 Memory voltage 内存电压 CPU pin voltage CPU管脚电压 Bridge voltage 桥片电压 CPU core voltage CPU核电压 CPU temperature CPU温度 Motherboard temperature 主板温度 CPU fan speed CPU风扇转速 ThemeSetting 主题设置 IconSetting 图标设置 MousePointer 鼠标设置 SoundEffect 声音效果 Panel 面板 StartMenu 启动菜单 Window 窗口 FontSetting 字体设置 Touchpad 触摸板 Energy saving 省电设置 File manager 文件管理器 byte 字节 byte/s 字节/秒 bytes 字节 bytes/s 字节/秒 KiB KB KiB/s KB/秒 MiB MiB MiB/s MiB/秒 GiB GiB GiB/s GiB/秒 TiB TiB TiB/s TiB/秒 net 网络 recv: 接收: sent: 发送: %1hours %1小时 %1hour %1小时 %1minutes %1分 %1minute %1分 %1seconds %1秒 %1second %1秒 %1day %1天 %1days %1天 User name: 用户名: Process name: 进程名: Command line: 命令行: CPU Time: CPU 时间: Started Time: 开始于: ukui-system-monitor is already running! bit bits bits/s command line: 命令行 ReniceDialog Nice value: Nice 值: Note: 备忘: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. 进程的优先级由它的 nice 值指定。较低的 nice 值对应较高的优先级。 Cancel 取消 Change Priority 改变优先级 ResourcesCategory CPU 处理器 Memory 内存 Network 网络 SelectListWidget Clean Items: 清理项: ShredDialog Kylin Shred Manager 麒麟文件粉碎机 Shred Manager 文件粉碎机 No select any file which need to be shredded 没有选择需要粉碎的文件 Shred File 粉碎文件 Deselect 取消粉碎 Select file 选择文件 All Files(*) 全部文件(*) Select file! 选择文件! Shred successfully! 粉碎成功! Shred failed! 粉碎失败! ShredManager Shred Manager 文件粉碎机 Delete files makes it unable to recover 彻底删除文件使其无法恢复 SoundWidget Sound theme 声音主题 Login tone 登录提示音 Event sounds 事件声音 Input feedback sounds 输入反馈声音 StartupManager Startup Manager 启动项管理器 Help user to manager application startup items 帮助用户管理应用程序开机启动项 StartupTitleWidget Kylin Startup Manager 麒麟启动项管理器 StartupWidget Kylin Startup Manager 麒麟启动项管理器 StartupWorker No name 无名称 No description 无描述 SystemMonitor UKUI System Monitor 系统监视器 Kylin System Monitor 系统监视器 ThemeWidget Please choose theme which you need 选择您需要的主题 TopBaseWidget There may be a mistake. 可能发生了错误。 Kylin Assistant 麒麟助手 Back 返回 TouchpadWidget Enable touchpad 启用/禁用触摸板 Enable horizontal scrolling 触摸板横向滚动 Scrollbar type 滚动条类型 Touchpad scrolling mode 触摸板滚动模式 Features Type 特色类型 Standard Type 标准类型 Disabled 禁用 Edge Scrolling 边界滚动 Two-finger Scrolling 双指滚动 WindowWidget Arrangement of buttons on the titlebar 标题栏按钮布局 Menu with icons 菜单项旁显示图标 Titlebar mouse wheel action 标题栏鼠标滚轮动作 Titlebar double-click action 标题栏双击动作 Titlebar middle-click action 标题栏中键动作 Titlebar right-click action 标题栏右键动作 Left 左边 Right 右边 ukui-system-monitor/src/translation/ukui-system-monitor_ru.qm0000644000175000017500000000004213746753504023652 0ustar fengfeng AboutDialog About Hakkında Close Kapat CleanSubGroup Custom Özel CleanerMainWidget Cookies Cookies CpuRateWidget CPU İşlemci Occupancy rate Doluluk oranı Idle rate Boşluk oranı The running time of system Sistemin çalışma süresi The idle time of system Sistemin boşta kalma süresi EnergyWidget Performance Performans 5 minutes 5 dakika 10 minutes 10 dakika 20 minutes 20 dakika 1 hour 1 saat 2 hours 2 saat never asla 1 minute 1 dakika 2 minutes 2 dakika 3 minutes 3 dakika 30 seconds 30 samiye FileSystemDialog Refresh Yenile FileSystemListWidget Device Aygıt Directory Dizin Type Tür Total Toplam Free Boş Available Mevcut Used Kullanılan No File System Info Dosya Sistemi Bilgisi Yok InfoWidget Computer Bilgisayar Desktop Masaüstü CPU İşlemci Memory Hafıza Motherboard Anakart HD HD NIC NIC VGA VGA Audio Ses Battery Batarya Sensor Sensör KylinFontDialog OK Tamam Cancel İptal KylinSwitcher ON Açık OFF Kapalı MainTopWidget Back Geri Scanning...... Taranıyor..... MemoryCircle Memory Hafıza Swap Takas Used(Percent) Kullanılan(Yüzde) Total Toplam %1(%2%) %1(%2%) %1(%2%) MemoryWidget Memory Hafıza MonitorTitleWidget Active Processes Aktif Süreçler My Processes Süreçlerim All Process Tüm İşlemler UKUI System Monitor Ukui Sistem Monitor :/img/minimize.png :/img/minimize.png :/img/fullscreen.png :/img/fullscreen.png :/img/close.png :/img/close.png Processes Süreçler Resources Kaynaklar File Systems Dosya Sistemi Cancel İptal Enter the relevant info of process İşlemle ilgili bilgileri girin NetworkFlow Receiving Alınıyor Total Received Toplam Alınan Sending Gönderiliyor Receive Alınan Send Gönder Total Sent Toplam Gönderilen NetworkWidget Network ProcessCategory Active Processes Aktif Süreçler My Processes Süreçlerim All Processes Tüm Süreçler ProcessDialog End process İşlemi bitir Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Bir işlemi sonlandırmak verileri yok edebilir, oturumu bozabilir veya güvenlik riski oluşturabilir. Sadece tepkisiz süreçler sona erdirilmelidir. Devam etmek istediğinizden emin misiniz? Cancel İptal Kill process İşlemi öldür Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Bir işlemi öldürmek verileri yok edebilir, oturumu bozabilir veya güvenlik riski oluşturabilir. Sadece tepkisiz süreçler öldürülmelidir. Devam etmek istediğinizden emin misiniz? Stop process İşlemi durdur Continue process İşleme devam et Very High Çok Yüksek High Yüksek Normal Normal Low Düşük Very Low Çok düşük Custom Özel Change Priority Önceliği Değiştir Properties Özellikler Change Priority of Process %1 (PID: %2) %1 Sürecinin Önceliğini Değiştir (PID:%2) ProcessListItem Stopped Durduruldu Suspend Askıya al Zombie Zombi No response Cevap yok Uninterruptible Kesintisiz ProcessListWidget Process Name İşlem Adı User Kullanıcı Status Durum CPU İşlemci ID ID Command Line Komut Satırı Memory Hafıza Priority Öncelik No search result Arama sonucu yok ProcessManager System Monitor Sistem Monitor Help user to kill process Kullanıcının işlemi öldürmesine yardımcı olun PropertiesDialog OK Tamam QObject Running Yürütülüyor Stopped Durduruldu Zombie Ölü Uninterruptible Kesintisiz Sleeping Uyuyor Very High Çok Yüksek High Yüksek Normal Normal Low Düşük Very Low Çok Düşük Very High Priority Çok Yüksek Öncelik High Priority Yüksek Öncelik Normal Priority Normal Öncelik Low Priority Düşük Öncelik Very Low Priority Çok Düşük Öncelik BIOS Version BIOS Sürümü Language Dil User Kullanıcı 32bit 32 bit 64bit 64 bit Panel Panel byte bayt byte/s bayt/s bytes bayt bytes/s bayt/s KiB KB KiB/s KB/s MiB MB MiB/s MB/s GiB GB GiB/s GB/s TiB TB TiB/s TB/s %1hours %1 saat %1hour %1 saat %1minutes %1 dakika %1minute %1 dakika %1seconds %1 saniye %1second %1 saniye %1day %1 gün %1days %1 gün User name: Kullanıcı Adı: Process name: İşlem Adı: Command line: Komut Satırı: CPU Time: CPU Zamanı: Started Time: Başlama Zamanı: ReniceDialog Nice value: Güzel değer: Note: Not: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Bir sürecin önceliği hoş değeri ile verilir. Daha düşük bir hoş değer daha yüksek bir önceliğe karşılık gelir. Cancel İptal Change Priority Önceliği Değiştir ResourcesCategory CPU İşlemci Memory Hafıza Network ShredDialog All Files(*) Tüm Dosyalar(*) SystemMonitor UKUI System Monitor Ukui Sistem Monitor TopBaseWidget Back Geri WindowWidget Left Sol Right Sağ ukui-system-monitor/src/translation/ukui-system-monitor_fr.ts0000644000175000017500000006067213746753504023663 0ustar fengfeng CpuRateWidget CPU Occupancy rate Idle rate The running time of system The idle time of system FileSystemDialog Refresh FileSystemListWidget Device Directory Type Total Free Available Used No File System Info MemoryCircle Memory Swap Used(Percent) Total %1(%2%) MemoryWidget Memory MonitorTitleWidget Active Processes My Processes All Process UKUI System Monitor :/img/minimize.png :/img/fullscreen.png :/img/close.png Processes Resources File Systems Enter the relevant info of process NetworkFlow Receiving Total Received Sending Receive Send Total Sent NetworkWidget Network ProcessCategory Active Processes My Processes All Processes ProcessDialog End process Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended. Are you sure to continue? Cancel Kill process Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed. Are you sure to continue? Stop process Continue process Very High High Normal Low Very Low Custom Change Priority Properties Change Priority of Process %1 (PID: %2) ProcessListItem Stopped Suspend Zombie No response Uninterruptible ProcessListWidget Process Name User Status CPU ID Command Line Memory Priority No search result ProcessManager System Monitor Help user to kill process PropertiesDialog OK QObject Running Stopped Zombie Uninterruptible Sleeping Very High High Normal Low Very Low Very High Priority High Priority Normal Priority Low Priority Very Low Priority byte byte/s bytes bytes/s KiB KiB/s MiB MiB/s GiB GiB/s TiB TiB/s %1hours %1hour %1minutes %1minute %1seconds %1second %1day %1days User name: Process name: Command line: CPU Time: Started Time: ReniceDialog Nice value: Note: The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority. Cancel Change Priority ResourcesCategory CPU Memory Network SystemMonitor UKUI System Monitor ukui-system-monitor/src/translation/ukui-system-monitor_fr.qm0000644000175000017500000000002713746753504023636 0ustar fengfeng. */ #include "../component/utils.h" #include "../widgets/mydialog.h" #include "../widgets/myactiongroup.h" #include "../widgets/myactiongroupitem.h" #include "../widgets/myaction.h" #include "processworker.h" #include "processlistitem.h" #include "processlistwidget.h" #include "monitortitlewidget.h" #include "singleProcessNet/scanthread.h" #include "singleProcessNet/refreshthread.h" #include "linebandwith.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ProcessManager; class ProcessCategory; class ProcessDialog : public QWidget { Q_OBJECT public: explicit ProcessDialog(QList toBeDisplayedColumns, int currentSortIndex, bool isSort, QSettings *settings, QWidget* parent = 0); ~ProcessDialog(); ProcessListWidget* getProcessView(); void displayAllProcess(); void displayActiveProcess(); void displayCurrentUserProcess(); void clearOriginProcList(); signals: void changeColumnVisible(int index, bool visible, QList columnVisible); void changeSortStatus(int index, bool isSort); void activeWhoseProcessList(int index); void closeDialog(); public slots: void focusProcessView(); void onSearch(QString text); void stopProcesses(); void continueProcesses(); void endProcesses(); void killProcesses(); void popupMenu(QPoint pos, QList items); void showPropertiesDialog(); void showEndProcessDialog(); void showKillProcessDialog(); void endDialogButtonClicked(int index, QString buttonText); void killDialogButtonClicked(int index, QString buttonText); void updateStatus(QList items); void onActiveWhoseProcess(int index); void changeProcPriority(int nice); void refreshProcessList(); //for renewe single process net information void refreshLine(const QString& procname, quint64 rcv, quint64 sent, int pid, unsigned int uid, const QString& devname); void onSearchFocusIn(); void onSearchFocusOut(); // void newSpeedRefresh(); protected: // void paintEvent(QPaintEvent *event); private: QTimer *timer = nullptr; // QTimer *netSpeedTimer = nullptr; QSettings *proSettings = nullptr; guint64 cpu_total_time; guint64 cpu_total_time_last; MyDialog *killProcessDialog = nullptr; MyDialog *endProcessDialog = nullptr; ProcessListWidget *m_processListWidget = nullptr; QAction *m_propertiyAction = nullptr; QAction *m_stopAction = nullptr;//停止 QAction *m_continueAction = nullptr;//继续进程 QAction *m_endAction = nullptr;//结束 QAction *m_killAction = nullptr;//杀死 ProcessCategory *processCategory = nullptr; ProcessListItem *item = nullptr; QMenu *m_priorityMenu; MyActionGroup * priorityGroup; MyAction *veryHighAction; MyAction *highAction; MyAction *normalAction; MyAction *lowAction; MyAction *veryLowAction; MyAction *customAction; QList *actionPids; QMenu *m_menu = nullptr; QString whose_processes; gint num_cpus; unsigned frequency; QVBoxLayout *m_layout = nullptr; QHBoxLayout *m_categoryLayout = nullptr; ScanThread *scanThread = nullptr; RefreshThread *refreshThread = nullptr; pid_t haveNetPid; QMap pidMap; QMap flowNetPrevMap; QMap calDiskIoMap; QString addFlowNetPerSec; QString addDiskIoPerSec; int numAddFlowNetPerSec; lineBandwith *speedLineBandFlowNet; lineBandwith *speedLineBandDiskIo; guint64 disk_io_bytes_total; // guint64 disk_read_bytes_current; // guint64 disk_write_bytes_current; }; ukui-system-monitor/src/maincontroller.h0000644000175000017500000000271513746753504017475 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _MAINCONTROL_H_ #define _MAINCONTROL_H_ #include #include #include #include #include #include #include #include "systemmonitor.h" #include "../shell/macro.h" #include "framelessExtended/framelesshandle.h" class MainController : public QObject { Q_OBJECT public: static MainController* self(); virtual ~MainController(); private: explicit MainController(); void init(); void creatDBusService(); int IsNotRunning(); private: static MainController *mSelf; SystemMonitor * monitor; }; #endif //_MAINCONTROL_H_ ukui-system-monitor/src/util.h0000644000175000017500000000411413764070001015375 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #define MONITOR_TITLE_WIDGET_HEIGHT 97 #define TITLE_WIDGET_HEIGHT 39 #define DEVICE_MOUNT_PONINT_RECORD_FILE "/proc/mounts" using std::string; std::string getDesktopFileAccordProcName(QString procName, QString cmdline); QPixmap getAppIconFromDesktopFile(std::string desktopFile, int iconSize = 24); QString getDisplayNameAccordProcName(QString procName, std::string desktopFile); std::string make_string(char *c_str); QString formatProcessState(guint state); QString getNiceLevel(int nice); QString getNiceLevelWithPriority(int nice); QString formatUnitSize(double v, const char** orders, int nb_orders); QString formatByteCount(double v); void setFontSize(QPainter &painter, int textSize); QString formatDurationForDisplay(unsigned centiseconds); QString getDeviceMountedPointPath(const QString &line); QString getFileContent(const QString &filePath); QSet getFileContentsLineByLine(const QString &filePath); const QPixmap loadSvg(const QString &fileName, const int size); //图片反白 QPixmap drawSymbolicColoredPixmap(const QPixmap &source); //图片反黑 QPixmap drawSymbolicBlackColoredPixmap(const QPixmap &source); ukui-system-monitor/src/monitortitlewidget.cpp0000644000175000017500000005442113764070001020716 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "monitortitlewidget.h" #include "../widgets/mytristatebutton.h" #include "../widgets/myunderlinebutton.h" #include "../widgets/mysearchedit.h" #include "../shell/macro.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #define MENU_SCHEMA "org.ukui.system-monitor.menu" #define WHICH_MENU "which-menu" MonitorTitleWidget::MonitorTitleWidget(QSettings *settings, QWidget *parent) :QFrame(parent) ,proSettings(settings) ,fontSettings(nullptr) ,qtSettings(nullptr) { m_animation = nullptr; this->setAttribute(Qt::WA_TranslucentBackground); m_queryIcon=new QLabel(); QIcon queryIcon; queryIcon = QIcon::fromTheme("preferences-system-search-symbolic"); pixmap = queryIcon.pixmap(QSize(21, 21)); whichBox = new QList(); const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } const QByteArray ifid(MENU_SCHEMA); if(QGSettings::isSchemaInstalled(ifid)) { ifsettings = new QGSettings(ifid); } const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { opacitySettings = new QGSettings(idtrans); } initFontSize(); m_changeBox = new QComboBox(); m_changeBox->setFixedSize(NORMALWIDTH,NORMALHEIGHT+2); m_changeBox->addItem(tr("Active Processes")); m_changeBox->addItem(tr("My Processes")); m_changeBox->addItem(tr("All Process")); m_changeBox->setFocusPolicy(Qt::NoFocus); m_changeBox->setView(new QListView()); QFont changeBoxFont; changeBoxFont.setPointSize(fontSize); m_changeBox->setFont(changeBoxFont); initThemeMode(); getTransparentData(); this->setWindowFlags(Qt::FramelessWindowHint);//this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint | Qt::WindowCloseButtonHint); installEventFilter(this); setFixedHeight(MONITOR_TITLE_WIDGET_HEIGHT); this->setAutoFillBackground(true); m_searchTimer = new QTimer(this); m_searchTimer->setSingleShot(true); connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(onRefreshSearchResult())); initWidgets(); this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); this->installEventFilter(this); } void MonitorTitleWidget::getTransparentData() { if (!opacitySettings) { m_transparency = 0.95; return; } connect(opacitySettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "transparency") { QStringList keys = opacitySettings->keys(); if (keys.contains("transparency")) { m_transparency = opacitySettings->get("transparency").toString().toDouble(); } } repaint(); }); QStringList keys = opacitySettings->keys(); if(keys.contains("transparency")) { m_transparency = opacitySettings->get("transparency").toString().toDouble(); } } void MonitorTitleWidget::initThemeMode() { //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); if (currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { qDebug() << "The theme change to white"; this->setObjectName("MonitorTitle"); this->setStyleSheet("QFrame#MonitorTitle{background:rgba(255,255,255,0);border-top-left-radius:6px;border-top-right-radius:6px;color: palette(windowText);}"); m_queryIcon->setPixmap(drawSymbolicBlackColoredPixmap(pixmap)); } else/*(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black")*/ { this->setObjectName("MonitorTitle"); this->setStyleSheet("QFrame#MonitorTitle{background:rgba(13,14,14,0);border-top-left-radius:6px;border-top-right-radius:6px;color: palette(windowText);}"); m_queryIcon->setPixmap(drawSymbolicColoredPixmap(pixmap)); } } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); if (currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { this->setObjectName("MonitorTitle"); this->setStyleSheet("QFrame#MonitorTitle{background:rgba(255,255,255,0);border-top-left-radius:6px;border-top-right-radius:6px;color: palette(windowText);}"); m_queryIcon->setPixmap(drawSymbolicBlackColoredPixmap(pixmap)); } if (currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { this->setObjectName("MonitorTitle"); this->setStyleSheet("QFrame#MonitorTitle{background:rgba(13,14,14,0);border-top-left-radius:6px;border-top-right-radius:6px;color: palette(windowText);}"); m_queryIcon->setPixmap(drawSymbolicColoredPixmap(pixmap)); } } void MonitorTitleWidget::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } QFont font; font.setPointSize(fontSize); titleLabel->setFont(font); QFont changeBoxFont; changeBoxFont.setPointSize(fontSize); m_changeBox->setFont(changeBoxFont); }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } MonitorTitleWidget::~MonitorTitleWidget() { delete emptyLabel; delete maxBtn; if (m_searchTimer) { disconnect(m_searchTimer, SIGNAL(timeout()), this, SLOT(onRefreshSearchResult())); if(m_searchTimer->isActive()) { m_searchTimer->stop(); } delete m_searchTimer; m_searchTimer = nullptr; } //Segmentation fault QLayoutItem *child; while ((child = m_titleLeftLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_titleMiddleLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_titleRightLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_toolLeftLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_toolRightLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_topLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = m_bottomLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } delete m_layout; if(fontSettings) { delete fontSettings; } if(qtSettings) { delete qtSettings; } if(m_animation) { delete m_animation; } } bool MonitorTitleWidget::eventFilter(QObject *obj, QEvent *event) //set the esc and tab pressbutton effect { if (event->type() == QEvent::KeyPress) { if (obj == this) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Escape || keyEvent->key() == Qt::Key_Tab) { // m_searchEdit->clearEdit(); m_searchEditNew->clear(); emit canelSearchEditFocus(); } } else if (obj == m_searchEditNew) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Tab) { // m_searchEdit->clearEdit(); m_searchEditNew->clear(); emit canelSearchEditFocus(); } } } if (obj == m_searchEditNew) { if (event->type() == QEvent::FocusIn) { emit SearchFocusIN(); if(m_searchEditNew->text().isEmpty()) { qDebug()<<"it is real"; m_animation->stop(); m_animation->setStartValue(QRectF((m_searchEditNew->width() - (m_queryIcon->width()+m_queryText->width()+10))/2,0, m_queryIcon->width()+m_queryText->width()+10,(m_searchEditNew->height() + 20)/2)); m_animation->setEndValue(QRectF(0,0, m_queryIcon->width()+3,(m_searchEditNew->height()+20)/2)); m_animation->setEasingCurve(QEasingCurve::OutQuad); m_animation->start(); } m_isSearching=true; } else if(event->type() == QEvent::FocusOut) { emit SearchFocusOut(); m_searchEditNew->clear(); m_searchEditNew->clearFocus(); if(m_searchEditNew->text().isEmpty()) { m_queryText->adjustSize(); m_animation->setStartValue(QRectF(0,0, m_queryIcon->width()+3,(m_searchEditNew->height()+20)/2)); m_animation->setEndValue(QRectF((m_searchEditNew->width() - (m_queryIcon->width()+m_queryText->width()+10))/2,0, m_queryIcon->width()+m_queryText->width()+10,(m_searchEditNew->height()+20)/2)); m_animation->setEasingCurve(QEasingCurve::InQuad); m_animation->start(); } m_isSearching=false; } } if(obj != m_searchEditNew && event->type() == QEvent::MouseButtonPress) { m_searchEditNew->clear(); m_searchEditNew->clearFocus(); } return QFrame::eventFilter(obj, event); } void MonitorTitleWidget::setSearchEditFocus() { // if (m_searchEdit->searchedText() != "") { // m_searchEdit->getLineEdit()->setFocus(); // } else { // m_searchEdit->setFocus(); // } } void MonitorTitleWidget::onRefreshSearchResult() { // if (m_searchEdit->searchedText() == searchTextCache) { // emit this->searchSignal(searchTextCache); // } if (m_searchEditNew->text() == searchTextCache) { emit this->searchSignal(searchTextCache); } } void MonitorTitleWidget::handleSearchTextChanged() { // searchTextCache = m_searchEdit->searchedText(); searchTextCache = m_searchEditNew->text(); if (m_searchTimer->isActive()) { m_searchTimer->stop(); } m_searchTimer->start(300); } void MonitorTitleWidget::onCancelSearchBtnClicked(bool b) { // m_searchEdit->clearAndFocusEdit(); emit canelSearchEditFocus(); } void MonitorTitleWidget::mouseDoubleClickEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { if (window()->isMaximized()) window()->showNormal(); else if (! window()->isFullScreen()) window()->showMaximized(); } QFrame::mouseDoubleClickEvent(e); } void MonitorTitleWidget::initTitlebarLeftContent() { QWidget *w = new QWidget; m_titleLeftLayout = new QHBoxLayout(w); m_titleLeftLayout->setContentsMargins(6, 0, 0, 0); m_titleLeftLayout->setSpacing(0); emptyLabel = new QLabel; emptyLabel->setStyleSheet("QLabel{background-color:transparent;}"); m_titleLeftLayout->addWidget(emptyLabel); m_topLayout->addWidget(w, 1, Qt::AlignLeft); } void MonitorTitleWidget::initTitlebarMiddleContent() { QWidget *w = new QWidget; m_titleMiddleLayout = new QHBoxLayout(w); m_titleMiddleLayout->setContentsMargins(0, 0, 0, 0); titleLabel = new QLabel; QLabel *picLabel = new QLabel; QFont font; font.setPointSize(fontSize-2); titleLabel->setFont(font); titleLabel->setText(tr("Kylin System Monitor")); picLabel->setPixmap(QPixmap(":img/ukui-system-monitor.png")); m_titleMiddleLayout->addWidget(picLabel); m_titleMiddleLayout->addWidget(titleLabel); m_topLayout->addWidget(w); } void MonitorTitleWidget::initTitlebarRightContent() { QWidget *w = new QWidget; m_titleRightLayout = new QHBoxLayout(w); m_titleRightLayout->setContentsMargins(0, 8, 8, 0); m_titleRightLayout->setSpacing(0); m_topLayout->addWidget(w, 1, Qt::AlignRight); QPushButton *minBtn = new QPushButton(this); minBtn->setToolTip(tr("minimize")); minBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic")); minBtn->setProperty("isWindowButton", 0x1); minBtn->setProperty("useIconHighlightEffect", 0x2); minBtn->setFlat(true); connect(minBtn, SIGNAL(clicked()), this, SLOT(onMinBtnClicked())); maxTitleBtn = new QPushButton(); maxTitleBtn->setToolTip(tr("maximize/restore")); maxTitleBtn->setProperty("isWindowButton", 0x1); maxTitleBtn->setProperty("useIconHighlightEffect", 0x2); maxTitleBtn->setFlat(true); maxTitleBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic")); connect(maxTitleBtn, SIGNAL(clicked()), this, SLOT(onMaxBtnClicked())); QPushButton *closeBtn = new QPushButton(this); closeBtn->setToolTip(tr("close")); closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); closeBtn->setFlat(true); closeBtn->setProperty("isWindowButton", 0x2); closeBtn->setProperty("useIconHighlightEffect", 0x8); connect(closeBtn, SIGNAL(clicked()), this, SLOT(onCloseBtnClicked())); //进行GSettings设置,记忆用户选择的combox的内容 whichNum = ifsettings->get(WHICH_MENU).toInt(); m_changeBox->setCurrentIndex(whichNum); connect(m_changeBox,SIGNAL(currentIndexChanged(int)),this,SLOT(switchChangeItemProcessSignal(int))); m_titleRightLayout->addWidget(minBtn); m_titleRightLayout->addWidget(maxTitleBtn); m_titleRightLayout->addWidget(closeBtn); } void MonitorTitleWidget::onMinBtnClicked() { emit minimizeWindow(); } void MonitorTitleWidget::onMaxBtnClicked() { emit maximizeWindow(); } void MonitorTitleWidget::resizeEvent(QResizeEvent *event) { if(window()->isMaximized()) { maxTitleBtn->setIcon(QIcon::fromTheme("window-restore-symbolic")); } else { maxTitleBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic")); } } void MonitorTitleWidget::onCloseBtnClicked() { window()->close(); } void MonitorTitleWidget::switchChangeItemProcessSignal(int a) { qDebug()<<"whichNum----"<get(WHICH_MENU).toInt(); ifsettings->set(WHICH_MENU,a); } void MonitorTitleWidget::onUpdateMaxBtnStatusChanged() { } void MonitorTitleWidget::initToolbarLeftContent() { QWidget *w = new QWidget; w->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_toolLeftLayout = new QHBoxLayout(w); m_toolLeftLayout->setContentsMargins(0, 0, 0, 0); QPushButton *processButton = new QPushButton(); processButton->setText(tr("Processes")); processButton->setChecked(true); processButton->setFixedSize(NORMALWIDTH,NORMALHEIGHT+2); QPushButton *resourcesButton = new QPushButton(); resourcesButton->setText(tr("Resources")); resourcesButton->setChecked(false); resourcesButton->setFixedSize(NORMALWIDTH,NORMALHEIGHT+2); QPushButton *disksButton = new QPushButton(); disksButton->setText(tr("File Systems")); disksButton->setChecked(false); disksButton->setFixedSize(NORMALWIDTH,NORMALHEIGHT+2); connect(processButton, &QPushButton::clicked, this, [=] { emit this->changePage(0); processButton->setChecked(true); resourcesButton->setChecked(false); disksButton->setChecked(false); // if (!m_searchEdit->isVisible()) // m_searchEdit->setVisible(true); if (!m_changeBox->isVisible()) m_changeBox->setVisible(true); if (!m_searchEditNew->isVisible()) m_searchEditNew->setVisible(true); }); connect(resourcesButton, &QPushButton::clicked, this, [=] { emit this->changePage(1); processButton->setChecked(false); resourcesButton->setChecked(true); disksButton->setChecked(false); // if (m_searchEdit->isVisible()) // m_searchEdit->setVisible(false); if (m_changeBox->isVisible()) m_changeBox->setVisible(false); if (m_searchEditNew->isVisible()) m_searchEditNew->setVisible(false); // m_searchEdit->clearEdit(); m_searchEditNew->clear(); emit canelSearchEditFocus(); }); connect(disksButton, &QPushButton::clicked, this, [=] { emit this->changePage(2); processButton->setChecked(false); resourcesButton->setChecked(false); disksButton->setChecked(true); // if (m_searchEdit->isVisible()) // m_searchEdit->setVisible(false); if (m_changeBox->isVisible()) m_changeBox->setVisible(false); if (m_searchEditNew->isVisible()) m_searchEditNew->setVisible(false); // m_searchEdit->clearEdit(); m_searchEditNew->clear(); emit canelSearchEditFocus(); }); emptyWidget = new QWidget(); processButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); resourcesButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); disksButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); emptyWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_bottomLayout->addWidget(processButton); m_bottomLayout->addWidget(resourcesButton); m_bottomLayout->addWidget(disksButton); m_bottomLayout->addWidget(emptyWidget, 3); } void MonitorTitleWidget::initToolbarRightContent() { // connect(m_searchEdit, &MySearchEdit::textChanged, this, &MonitorTitleWidget::handleSearchTextChanged, Qt::QueuedConnection); connect(m_searchEditNew,&QLineEdit::textChanged,this,&MonitorTitleWidget::handleSearchTextChanged,Qt::QueuedConnection); emptyWidget2 = new QWidget(); emptyWidget2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_bottomLayout->addWidget(m_changeBox); m_bottomLayout->addWidget(emptyWidget2, 1); m_bottomLayout->addWidget(m_searchEditNew); } void MonitorTitleWidget::initWidgets() { //新的搜索框设置 m_searchEditNew = new QLineEdit(); m_searchEditNew->setFixedSize(SPECIALWIDTH, NORMALHEIGHT +2); m_searchEditNew->installEventFilter(this); m_searchEditNew->setContextMenuPolicy(Qt::NoContextMenu); m_queryText=new QLabel(); m_queryText->setText(tr("Enter the relevant info of process")); m_queryWid=new QWidget(m_searchEditNew); m_queryWid->setFocusPolicy(Qt::NoFocus); QHBoxLayout* queryWidLayout = new QHBoxLayout; queryWidLayout->setContentsMargins(4,4,0,0); queryWidLayout->setAlignment(Qt::AlignJustify); queryWidLayout->setSpacing(0); m_queryWid->setLayout(queryWidLayout); queryWidLayout->addWidget(m_queryIcon); queryWidLayout->addWidget(m_queryText); m_queryWid->setGeometry(QRect((m_searchEditNew->width() - (m_queryIcon->width()+m_queryText->width()+10))/2,0, m_queryIcon->width()+m_queryText->width()-10,(m_searchEditNew->height() + 20)/2)); //设置显示label的区域 m_animation= new QPropertyAnimation(m_queryWid, "geometry"); m_animation->setDuration(50); connect(m_animation,&QPropertyAnimation::finished,this,&MonitorTitleWidget::animationFinishedSlot); ////////////////// m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); QWidget *topWidget = new QWidget; m_topLayout = new QHBoxLayout(topWidget); m_topLayout->setSpacing(0); m_layout->addWidget(topWidget, 0, Qt::AlignTop); QWidget *bottomWidget = new QWidget; m_bottomLayout = new QHBoxLayout(bottomWidget); // m_bottomLayout->setContentsMargins(10, 0, 10, 0); m_layout->addWidget(bottomWidget); // m_layout->setContentsMargins(0,0,0,0); this->setLayout(m_layout); initTitlebarLeftContent(); initTitlebarMiddleContent(); initTitlebarRightContent(); initToolbarLeftContent(); initToolbarRightContent(); } void MonitorTitleWidget::animationFinishedSlot() { if(m_isSearching) { m_queryWid->layout()->removeWidget(m_queryText); m_queryText->setParent(nullptr); m_searchEditNew->setTextMargins(30,1,0,1); } else { m_queryWid->layout()->addWidget(m_queryText); } } void MonitorTitleWidget::paintEvent(QPaintEvent *event) { // QPainterPath path; // auto rect = this->rect(); // rect.adjust(1, 1, -1, -1); // path.addRoundedRect(rect, 6, 6); // setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); // QStyleOption opt; // opt.init(this); // QPainter p(this); // QRect rectReal = this->rect(); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.setBrush(opt.palette.color(QPalette::Base)); // p.setOpacity(m_transparency); // qDebug()<<"real transparency"<winId(), true, QRegion(path.toFillPolygon().toPolygon())); } ukui-system-monitor/src/processdialog.cpp0000644000175000017500000010363113764070001017615 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processdialog.h" #include "propertiesdialog.h" #include "processdata.h" #include "processcategory.h" #include "renicedialog.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //for setpriority using std::string; QDataStream &operator<<(QDataStream &dataStream, const ProcDataPtr &object) { auto ptr = object.data(); auto ptrval = reinterpret_cast(ptr); auto var = QVariant::fromValue(ptrval); dataStream << var; return dataStream; } QDataStream &operator>>(QDataStream &dataStream, ProcDataPtr &object) { QVariant var; dataStream >> var; qulonglong ptrval = var.toULongLong(); auto ptr = reinterpret_cast(ptrval); object = ProcDataPtr(ptr); return dataStream; } ProcessDialog::ProcessDialog(QList toBeDisplayedColumns, int currentSortIndex, bool isSort, QSettings *settings, QWidget *parent) :QWidget(parent) ,num_cpus(0) ,frequency(0U) ,proSettings(settings) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setAttribute(Qt::WA_NoMousePropagation); qRegisterMetaType(); //注册信号槽,实现线程间通信 qRegisterMetaTypeStreamOperators(); qRegisterMetaType(); qRegisterMetaType>(); actionPids = new QList(); m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); m_processListWidget = new ProcessListWidget(toBeDisplayedColumns); connect(m_processListWidget, SIGNAL(changeColumnVisible(int,bool,QList)), this, SIGNAL(changeColumnVisible(int,bool,QList))); connect(m_processListWidget, SIGNAL(changeSortStatus(int,bool)), this, SIGNAL(changeSortStatus(int,bool))); connect(m_processListWidget, &ProcessListWidget::rightMouseClickedItems, this, &ProcessDialog::popupMenu, Qt::QueuedConnection); m_layout->addWidget(m_processListWidget); //记录要显示进程的内容类别 whose_processes = "user"; proSettings->beginGroup("PROCESS"); whose_processes = proSettings->value("WhoseProcesses", whose_processes).toString(); proSettings->endGroup(); // int tabIndex = 1; // if (whose_processes == "active") { // tabIndex = 0; // } // else if (whose_processes == "all") { // tabIndex = 2; // } // else { // tabIndex = 1; // } // QWidget *w = new QWidget; // w->setFixedHeight(0); // m_categoryLayout = new QHBoxLayout(w); //give up adding new widget // m_categoryLayout->setContentsMargins(0, 0, 6, 3); // m_categoryLayout->setSpacing(10); //// processCategory = new ProcessCategory(tabIndex); // connect(processCategory, SIGNAL(activeWhoseProcessList(int)), this, SLOT(onActiveWhoseProcess(int))); //// m_categoryLayout->addWidget(processCategory, 0, Qt::AlignRight); // m_layout->addWidget(w); QList *sortFuncList = new QList(); sortFuncList->append(&ProcessListItem::sortByName); sortFuncList->append(&ProcessListItem::sortByUser); sortFuncList->append(&ProcessListItem::sortByDiskIo); sortFuncList->append(&ProcessListItem::sortByCPU); sortFuncList->append(&ProcessListItem::sortByPid); sortFuncList->append(&ProcessListItem::sortByFlowNet); sortFuncList->append(&ProcessListItem::sortByMemory); sortFuncList->append(&ProcessListItem::sortByPriority); m_processListWidget->setProcessSortFunctions(sortFuncList, currentSortIndex, isSort); m_processListWidget->setSearchFunction(&ProcessListItem::doSearch); m_menu = new QMenu(); m_menu->setObjectName("MonitorMenu"); m_stopAction = new QAction(tr("Stop process"), this); connect(m_stopAction, &QAction::triggered, this, &ProcessDialog::stopProcesses); m_continueAction = new QAction(tr("Continue process"), this); connect(m_continueAction, &QAction::triggered, this, &ProcessDialog::continueProcesses); m_endAction = new QAction(tr("End process"), this); connect(m_endAction, &QAction::triggered, this, &ProcessDialog::showEndProcessDialog); m_killAction = new QAction(tr("Kill process"), this); connect(m_killAction, &QAction::triggered, this, &ProcessDialog::showKillProcessDialog); priorityGroup = new MyActionGroup(this); veryHighAction = new MyActionGroupItem(this, priorityGroup, "very_high_action", -20); highAction = new MyActionGroupItem(this, priorityGroup, "high_action", -5); normalAction = new MyActionGroupItem(this, priorityGroup, "normal_action", 0); lowAction = new MyActionGroupItem(this, priorityGroup, "low_action", 5); veryLowAction = new MyActionGroupItem(this, priorityGroup, "very_low_action", 19); customAction = new MyActionGroupItem(this, priorityGroup, "custom_action", 32); { QAction *sep = new QAction(priorityGroup); sep->setSeparator(true); } veryHighAction->change(tr("Very High")); highAction->change(tr("High")); normalAction->change(tr("Normal")); lowAction->change(tr("Low")); veryLowAction->change(tr("Very Low")); customAction->change(tr("Custom")); connect(priorityGroup, SIGNAL(activated(int)), this, SLOT(changeProcPriority(int))); m_priorityMenu = new QMenu(); m_priorityMenu->setObjectName("MonitorMenu"); m_priorityMenu->addActions(priorityGroup->actions()); m_priorityMenu->menuAction()->setText(tr("Change Priority")); m_propertiyAction = new QAction(tr("Properties"), this); connect(m_propertiyAction, &QAction::triggered, this, &ProcessDialog::showPropertiesDialog); m_menu->addAction(m_stopAction);//停止 m_menu->addAction(m_continueAction);//继续进程 m_menu->addAction(m_endAction);//结束 m_menu->addAction(m_killAction);//杀死 m_menu->addSeparator(); m_menu->addMenu(m_priorityMenu); m_menu->addSeparator(); m_menu->addAction(m_propertiyAction); glibtop_init(); this->num_cpus = glibtop_get_sysinfo()->ncpu; scanThread = new ScanThread(this); scanThread->start(QThread::TimeCriticalPriority); refreshThread = new RefreshThread(this); refreshThread->start(QThread::HighPriority); connect(refreshThread, SIGNAL(procDetected(const QString &, quint64 , quint64 , int , unsigned int , const QString&)), this, SLOT(refreshLine(const QString &, quint64 , quint64 , int, unsigned int , const QString&))); this->refreshProcessList(); timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(refreshProcessList())); timer->start(1500); } ProcessDialog::~ProcessDialog() { glibtop_close(); this->clearOriginProcList(); if (timer != NULL) { disconnect(timer,SIGNAL(timeout()),this,SLOT(refreshProcessList())); if(timer->isActive()) { timer->stop(); } delete timer; timer = NULL; } delete processCategory; delete endProcessDialog; delete killProcessDialog; delete m_processListWidget; delete m_stopAction; delete m_continueAction; delete m_endAction; delete m_killAction; delete veryHighAction; delete highAction; delete normalAction; delete lowAction; delete veryLowAction; delete customAction; delete m_priorityMenu; delete m_propertiyAction; delete m_menu; delete actionPids; delete item; if(scanThread) { delete scanThread; } if(refreshThread) { delete refreshThread; } QLayoutItem *child; while ((child = m_categoryLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } delete m_layout; } void ProcessDialog::displayAllProcess() { timer->stop(); this->clearOriginProcList(); whose_processes = "all"; this->refreshProcessList(); timer->start(3000); } void ProcessDialog::displayActiveProcess() { timer->stop(); this->clearOriginProcList(); whose_processes = "active"; this->refreshProcessList(); timer->start(3000); } void ProcessDialog::displayCurrentUserProcess() { timer->stop(); this->clearOriginProcList(); whose_processes = "user"; this->refreshProcessList(); timer->start(3000); } void ProcessDialog::onActiveWhoseProcess(int index) { if (index == 0) { if (this->whose_processes != "active") this->displayActiveProcess(); } else if (index == 1) { if (this->whose_processes != "user") this->displayCurrentUserProcess(); } else { if (this->whose_processes != "all") this->displayAllProcess(); } proSettings->beginGroup("PROCESS"); proSettings->setValue("WhoseProcesses", whose_processes); proSettings->endGroup(); proSettings->sync(); } void ProcessDialog::clearOriginProcList() { for (ProcessWorker::Iterator it(ProcessWorker::begin()); it != ProcessWorker::end(); ++it) delete it->second; ProcessWorker::all.clear(); } void ProcessDialog::changeProcPriority(int nice) { if (nice == 32) { //show renice dialog pid_t cur_pid = -1; for (pid_t pid : *actionPids) { cur_pid = pid; break; } if (cur_pid > -1) { ProcessWorker *info = ProcessWorker::find(cur_pid); if (!info) { actionPids->clear(); return; } QString name = QString::fromStdString(info->name); ReniceDialog *w = new ReniceDialog(tr("Change Priority of Process %1 (PID: %2)").arg(name).arg(QString::number(cur_pid))); w->loadData(info->nice); connect(w, &ReniceDialog::resetReniceValue, [=] (int value) { this->changeProcPriority(value); }); w->exec(); } } else { pid_t cur_pid = -1; for (pid_t pid : *actionPids) { cur_pid = pid; break; } if (cur_pid > -1) { ProcessWorker *info = ProcessWorker::find(cur_pid); if (!info) { actionPids->clear(); return; } if (info->nice == nice) { actionPids->clear(); return; } int saved_errno; int error = setpriority(PRIO_PROCESS, cur_pid, nice); //success if(error != -1) { actionPids->clear(); return; } saved_errno = errno; //need to be root if(errno == EPERM || errno == EACCES) { qDebug() << "Change priority need to be root!!!"; /* * renice: sudo apt install bsdutils * Maybe: QProcess::startDetached(command) * QProcess::start()与QProcess::execute()都能完成启动外部程序的任务,区别在于start()是非阻塞的,而execute()是阻塞的: execute()=start()+waitforFinished() */ if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1 QProcess process; process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("renice").arg(nice).arg(cur_pid)); /*process.start(QString("pkexec --disable-internal-agent %1 %2 %3").arg("renice").arg(nice).arg(cur_pid)); process.waitForStarted(1000); process.waitForFinished(20*1000);*/ } else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksudo \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid)); /*process.start(QString("gksudo \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid)); process.waitForStarted(1000); process.waitForFinished(20*1000);*/ } else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksu \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid)); // process.start(QString("gksu \"%1 %2 %3\"").arg("renice").arg(nice).arg(cur_pid)); // process.waitForStarted(1000); // process.waitForFinished(20*1000); } else { // } } } } actionPids->clear(); } //void ProcessDialog::onCloseButtonClicked() //{ // this->close(); //} //void ProcessDialog::closeEvent(QCloseEvent *event) //{ // event->accept(); //} void ProcessDialog::refreshProcessList() { pid_t* pid_list; glibtop_proclist proclist; glibtop_cpu cpu; int which = 0; int arg = 0; if (whose_processes == "all") { which = GLIBTOP_KERN_PROC_ALL; arg = 0; } else if (whose_processes == "active") { which = GLIBTOP_KERN_PROC_ALL | GLIBTOP_EXCLUDE_IDLE; arg = 0; } else if (whose_processes == "user") { which = GLIBTOP_KERN_PROC_UID; arg = getuid(); } pid_list = glibtop_get_proclist(&proclist, which, arg); /* FIXME: total cpu time elapsed should be calculated on an individual basis here ** should probably have a total_time_last gint in the ProcInfo structure */ glibtop_get_cpu(&cpu); this->frequency = cpu.frequency; this->cpu_total_time = MAX(cpu.total - this->cpu_total_time_last, 1); this->cpu_total_time_last = cpu.total; // FIXME: not sure if glibtop always returns a sorted list of pid // but it is important otherwise refresh_list won't find the parent std::sort(pid_list, pid_list + proclist.number); typedef std::list ProcList; ProcList addition; guint i; for(i = 0; i < proclist.number; ++i) { ProcessWorker *info = ProcessWorker::find(pid_list[i]); // qDebug()<<"Map size: "<< pidMap.size() << info; if (info) { if(pidMap.contains(pid_list[i])) { this->addFlowNetPerSec = pidMap[pid_list[i]]; info = new ProcessWorker(pid_list[i], this->num_cpus, this->cpu_total_time,this->addFlowNetPerSec); ProcessWorker::all[info->pid] = info; info->mNumFlownet = numAddFlowNetPerSec; } } //不存在时创建该进程的对象 //create the process object when the pid's object doesn't exist else { info = new ProcessWorker(pid_list[i], this->num_cpus, this->cpu_total_time, "0 KB/S"); ProcessWorker::all[info->pid] = info; info->mNumFlownet = 0; } //当进程对象存在时,更新该进程对象的相关数据信息 glibtop_proc_state procstate; glibtop_proc_uid procuid; glibtop_proc_time proctime; glibtop_proc_io procio; // info->mNumFlownet = numAddFlowNetPerSec; glibtop_get_proc_io(&procio,info->pid); glibtop_get_proc_state (&procstate, info->pid); info->status = procstate.state; glibtop_get_proc_uid (&procuid, info->pid); glibtop_get_proc_time (&proctime, info->pid); glibtop_proc_mem procmem; glibtop_get_proc_mem(&procmem, info->pid); info->mem = procmem.resident - procmem.share; glibtop_get_proc_state(&procstate, info->pid); info->status = procstate.state; info->set_user(procstate.uid); guint64 difference = proctime.rtime - info->cpu_time; if (difference > 0) info->status = GLIBTOP_PROCESS_RUNNING; info->pcpu = difference * 100 / this->cpu_total_time; info->pcpu = MIN(info->pcpu, 100); //CPU 百分比使用 Solaris 模式,工作在“Solaris 模式”,其中任务的 CPU 使用量将被除以总的 CPU 数目。否则它将工作在“Irix 模式”。 info->pcpu *= this->num_cpus; info->frequency = this->frequency; ProcessWorker::cpu_times[info->pid] = info->cpu_time = proctime.rtime; info->nice = procuid.nice; if(!calDiskIoMap.contains(info->pid)) { calDiskIoMap[info->pid] = 0; } speedLineBandDiskIo = new lineBandwith(info->pid,this); disk_io_bytes_total = procio.disk_wbytes+procio.disk_rbytes; addDiskIoPerSec = speedLineBandDiskIo->new_count(disk_io_bytes_total-calDiskIoMap[info->pid],info->pid); info->diskio_persec = addDiskIoPerSec; info->mNumDiskIo = disk_io_bytes_total-calDiskIoMap[info->pid]; calDiskIoMap[info->pid] = disk_io_bytes_total; delete speedLineBandDiskIo; } // Remove dead processes from the process list and from the // tree. children are queued to be readded at the right place // in the tree. const std::set pids(pid_list, pid_list + proclist.number); ProcessWorker::Iterator it(ProcessWorker::begin()); while (it != ProcessWorker::end()) { ProcessWorker * const info = it->second; ProcessWorker::Iterator next(it); ++next; if (pids.find(info->pid) == pids.end() || info->status == GLIBTOP_PROCESS_ZOMBIE) { addition.remove(info); ProcessWorker::all.erase(it); delete info; } it = next; } QList items; for (ProcessWorker::Iterator it(ProcessWorker::begin()); it != ProcessWorker::end(); ++it) { QString username = QString::fromStdString(it->second->user); long nice = it->second->nice; QString name = QString::fromStdString(it->second->name); QString session; if (it->second->session) { session = QString(it->second->session); } QString status = formatProcessState(it->second->status); uint cpu = it->second->pcpu; long memory = it->second->mem; pid_t pid = it->second->pid; QString flownetpersec = it->second->flownet_persec; QString diskiopersec = it->second->diskio_persec; int numFlowNetPersec = it->second->mNumFlownet; int numDiskioPersec = it->second->mNumDiskIo; /*---------------------kobe test string--------------------- //QString to std:string QString test_QString = "lixiang"; std::string test_string = test_QString.toStdString(); //std::string to QString QString result = QString::fromStdString(test_string) QString::fromStdString(test_QString.toStdString()); ----------------------------------------------------------*/ std::string desktopFile; desktopFile = getDesktopFileAccordProcName(name, ""); // qDebug() << "****************"<< QString::fromStdString(desktopFile); QPixmap icon_pixmap; int iconSize = 24 * qApp->devicePixelRatio(); QIcon defaultExecutableIcon = QIcon::fromTheme("application-x-executable");//gnome-mine-application-x-executable if (defaultExecutableIcon.isNull()) { defaultExecutableIcon = QIcon("/usr/share/icons/kylin-icon-theme/48x48/mimetypes/application-x-executable.png"); if (defaultExecutableIcon.isNull()) defaultExecutableIcon = QIcon(":/res/autostart-default.png"); } QPixmap defaultPixmap = defaultExecutableIcon.pixmap(iconSize, iconSize); // QPixmap defaultPixmap = QIcon::fromTheme("application-x-executable").pixmap(iconSize, iconSize); if (desktopFile.size() == 0) { icon_pixmap = defaultPixmap; icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); } else { icon_pixmap = getAppIconFromDesktopFile(desktopFile, 24); if (icon_pixmap.isNull()) { icon_pixmap = defaultPixmap; icon_pixmap.setDevicePixelRatio(qApp->devicePixelRatio()); } //QPixmap pixmap = QPixmap::fromImage(img).scaled(iconSize, iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } QString title = getDisplayNameAccordProcName(name, desktopFile); QString displayName; if (whose_processes == "all") { displayName = QString("[%1] %2").arg(username).arg(title); } else { displayName = title; } ProcData info; // info.pidt = it->second->pid; info.user = username; // 用户名 info.iconPixmap = icon_pixmap; // 进程加载的图片 info.displayName = displayName; info.cpu = cpu; info.m_memory = memory; //内存 info.pid = pid; info.m_status = status; //状态 info.m_nice = nice; //优先级 info.m_session = session; info.m_flownet = flownetpersec; //单个进程流量 info.cpu_duration_time = formatDurationForDisplay(100 * it->second->cpu_time / this->frequency); //CPU占用你时间 info.processName = QString::fromStdString(it->second->name); //进程名称 info.m_diskio = diskiopersec; //单个进程磁盘io速率 info.m_numFlowNet = numFlowNetPersec; //网络流量整数值 info.m_numDiskIo = numDiskioPersec; //磁盘读写整数值 // info.commandLine = QString::fromStdString(it->second->arguments); //命令行 item = new ProcessListItem(info); items << item; } this->updateStatus(items); g_free (pid_list); } void ProcessDialog::onSearchFocusIn() { qDebug()<<"focusin---"; timer->stop(); // disconnect(refreshThread, SIGNAL(procDetected(const QString &, quint64 , quint64 , int , unsigned int , const QString&)), // this, SLOT(refreshLine(const QString &, quint64 , quint64 , int, unsigned int , const QString&))); } void ProcessDialog::onSearchFocusOut() { qDebug()<<"focusout---"; timer->start(1500); } void ProcessDialog::refreshLine(const QString &procname, quint64 rcv, quint64 sent, int pid, unsigned int uid, const QString &devname) { // pidList<new_count(tmptotalFlowNetPerSec - flowNetPrevMap[pid],pid); // qDebug() << "ProcessDialog::refreshLine:deltaFlowNetPerSec" << tmptotalFlowNetPerSec - flowNetPrevMap[pid]; flowNetPrevMap[pid] = tmptotalFlowNetPerSec; // qDebug() << "ProcessDialog::refreshLine:after flowNetPrevMap" << flowNetPrevMap[pid]; if(!pidMap.contains(pid)) { pidMap[pid] = addFlowNetPerSec; } QMap::const_iterator it = pidMap.find(pid); // qDebug() << "ProcessDialog::pidMap" << it.value(); if(it.value() != addFlowNetPerSec) { pidMap[pid] = addFlowNetPerSec; } delete speedLineBandFlowNet; } ProcessListWidget* ProcessDialog::getProcessView() { return m_processListWidget; } void ProcessDialog::endDialogButtonClicked(int index, QString) { emit closeDialog(); if (index == 1) {//cancel:0 ok:1 endProcesses(); } } void ProcessDialog::killDialogButtonClicked(int index, QString) { emit closeDialog(); if (index == 1) {//cancel:0 ok:1 killProcesses(); } } void ProcessDialog::focusProcessView() { QTimer::singleShot(100, m_processListWidget, SLOT(setFocus())); } void ProcessDialog::onSearch(QString text) { m_processListWidget->doSearch(text); } //杀死 SIGSTOP,SIGCONT,SIGTERM,SIGKILL void ProcessDialog::killProcesses() { // int error; // for (pid_t pid : *actionPids) { // // Resume process first, otherwise kill process too slow. // kill(pid, SIGCONT); // error = kill(pid, SIGKILL); // if(error != -1) { // qDebug() << "success....."; // } else { // //need to be root // if(errno == EPERM) {//(kill -s %d %d", sig, pid) // qWarning() << QString("Kill process %1 failed, permission denied.").arg(pid); // if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1 // QProcess process; // process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGKILL).arg(pid)); // } else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu // QProcess process; // process.execute(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid)); // } else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu // QProcess process; // process.execute(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGKILL).arg(pid)); // } else { // qWarning() << "Failed to choose a tool to kill " << pid; // } // } // } // } // actionPids->clear(); int error; for (pid_t pid : *actionPids) { error = kill(pid, SIGTERM); if(error != -1) { qDebug() << "success....."; } else { //need to be root if(errno == EPERM) { qDebug() << QString("End process %1 failed, permission denied.").arg(pid); if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1 QProcess process; process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGTERM).arg(pid)); } else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid)); } else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid)); } else { qWarning() << "Failed to choose a tool to end process " << pid; } } } } actionPids->clear(); } //结束 void ProcessDialog::endProcesses() { int error; for (pid_t pid : *actionPids) { error = kill(pid, SIGTERM); if(error != -1) { qDebug() << "success....."; } else { //need to be root if(errno == EPERM) { qDebug() << QString("End process %1 failed, permission denied.").arg(pid); if (QFileInfo("/usr/bin/pkexec").exists()) {//sudo apt install policykit-1 QProcess process; process.execute(QString("pkexec --disable-internal-agent %1 %2 %3").arg("kill").arg(SIGTERM).arg(pid)); } else if (QFileInfo("/usr/bin/gksudo").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksudo \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid)); } else if (QFileInfo("/usr/bin/gksu").exists()) {//sudo apt install gksu QProcess process; process.execute(QString("gksu \"%1 %2 %3\"").arg("kill").arg(SIGTERM).arg(pid)); } else { qWarning() << "Failed to choose a tool to end process " << pid; } } } } actionPids->clear(); } void ProcessDialog::popupMenu(QPoint pos, QList items) { actionPids->clear(); int count = 0; pid_t cur_pid = -1; for (ProcessListItem *item : items) { count ++; ProcessListItem *procItem = static_cast(item); cur_pid = procItem->getPid(); actionPids->append(cur_pid); } if (count == 1) { ProcessWorker *info = ProcessWorker::find(cur_pid); if (!info) { priorityGroup->setActionsEnabled(false); } else { priorityGroup->setActionsEnabled(true); gint nice = info->nice; int priority; if (nice < -7) priority = -20; else if (nice < -2) priority = -5; else if (nice < 3) priority = 0; else if (nice < 7) priority = 5; else priority = 19; priorityGroup->setChecked(priority); } } else { priorityGroup->setActionsEnabled(false); } m_menu->exec(pos); } void ProcessDialog::continueProcesses() { for (pid_t pid : *actionPids) { if (kill(pid, SIGCONT) != 0) { qDebug() << QString("Resume process %1 failed, permission denied.").arg(pid); } } actionPids->clear(); } void ProcessDialog::showPropertiesDialog() { for (pid_t pid : *actionPids) { foreach (QWidget *widget, QApplication::topLevelWidgets()) { // Show attribute dialog if it has create, avoid create attribute dialog duplicate. if (qobject_cast(widget) != 0) { PropertiesDialog *dialog = qobject_cast(widget); if (dialog->getPid() == pid) { dialog->show(); actionPids->clear(); return; } } } PropertiesDialog *dialog = new PropertiesDialog(this, pid); dialog->show(); } actionPids->clear(); } void ProcessDialog::showKillProcessDialog() { // killProcessDialog->exec(); // killProcessDialog->show(); killProcessDialog = new MyDialog(QString(tr("Kill process")), QString(tr("Killing a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be killed.\nAre you sure to continue?"))); // killProcessDialog->setWindowFlags(killProcessDialog->windowFlags() | Qt::WindowStaysOnTopHint); killProcessDialog->addButton(QString(tr("Cancel")), false); killProcessDialog->addButton(QString(tr("Kill process")), true); connect(killProcessDialog, &MyDialog::buttonClicked, this, &ProcessDialog::killDialogButtonClicked); killProcessDialog->show(); connect(this,&ProcessDialog::closeDialog,killProcessDialog,&MyDialog::onButtonClicked); } void ProcessDialog::showEndProcessDialog() { // endProcessDialog->exec(); // endProcessDialog->show(); endProcessDialog = new MyDialog(QString(tr("End process")), QString(tr("Ending a process may destroy data, break the session or introduce a security risk. Only unresponsive processes should be ended.\nAre you sure to continue?"))); // endProcessDialog->setWindowFlags(endProcessDialog->windowFlags() | Qt::WindowStaysOnTopHint); endProcessDialog->addButton(QString(tr("Cancel")), false); endProcessDialog->addButton(QString(tr("End process")), true); connect(endProcessDialog, &MyDialog::buttonClicked, this, &ProcessDialog::endDialogButtonClicked); endProcessDialog->show(); connect(this,&ProcessDialog::closeDialog,endProcessDialog,&MyDialog::onButtonClicked); } //停止 void ProcessDialog::stopProcesses() { pid_t currentPid = getpid(); for (pid_t pid : *actionPids) { if (pid != currentPid) { if (kill(pid, SIGSTOP) != 0) { qDebug() << QString("Stop process %1 failed, permission denied.").arg(pid); } } } actionPids->clear(); } void ProcessDialog::updateStatus(QList items) { m_processListWidget->refreshItems(items); } /*void ProcessDialog::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //绘制背景色 // QPainterPath path; // path.addRect(QRectF(rect())); // painter.setOpacity(1); // painter.fillPath(path, QColor("#FFFFFF")); //绘制圆角矩形 // painter.setPen(QPen(QColor("#0d87ca"), 0));//边框颜色 QColor(255, 255, 255, 153) // painter.setBrush(QColor("#e9eef0"));//背景色 #0d87ca painter.setPen(QPen(QColor("#0000FF"), 0));//边框颜色 QColor(255, 255, 255, 153) painter.setBrush(QColor("#B22222"));//背景色 #0d87ca painter.setOpacity(1); // QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边 QRectF r(2, 2, width() - 0, height() - 0);//左边 上边 右边 下边 painter.drawRoundedRect(r, 10, 10); QWidget::paintEvent(event); }*/ ukui-system-monitor/src/renicedialog.cpp0000644000175000017500000002242413763560717017425 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "renicedialog.h" #include "../component/utils.h" #include "util.h" #include #include #include #include #include #include #include ReniceDialog::ReniceDialog(const QString &title, QWidget *parent) : QDialog(parent) , m_mousePressed(false) { this->setWindowFlags(Qt::FramelessWindowHint); this->setFixedSize(464, 240); this->setFixedSize(464+SHADOW_LEFT_TOP_PADDING+SHADOW_LEFT_TOP_PADDING, 300+SHADOW_RIGHT_BOTTOM_PADDING+SHADOW_RIGHT_BOTTOM_PADDING); // this->setContentsMargins(SHADOW_LEFT_TOP_PADDING,SHADOW_LEFT_TOP_PADDING,SHADOW_RIGHT_BOTTOM_PADDING,SHADOW_RIGHT_BOTTOM_PADDING); // this->setStyleSheet("QDialog{border: 1px solid white;border-radius:1px;background-color: #ffffff;}"); this->setWindowIcon(QIcon(":/res/ukui-system-monitor.png")); this->setAttribute(Qt::WA_DeleteOnClose); QWidget *containerWidget = new QWidget(this); // containerWidget->setContentsMargins(SHADOW_LEFT_TOP_PADDING,SHADOW_LEFT_TOP_PADDING,SHADOW_RIGHT_BOTTOM_PADDING,SHADOW_RIGHT_BOTTOM_PADDING); m_mainLayout = new QVBoxLayout(containerWidget); m_mainLayout->setContentsMargins(0,0,0,0); m_mainLayout->setSpacing(20); m_mainLayout->setMargin(0); // m_titleBar = new MyTitleBar(title, false, this); QLabel *titleLabel = new QLabel; titleLabel->setText(title); QPushButton *closeButton = new QPushButton(this); closeButton->setFlat(true); closeButton->setIcon(QIcon::fromTheme("window-close-symbolic")); closeButton->setProperty("isWindowButton", 0x2); closeButton->setProperty("useIconHighlightEffect", 0x8); QHBoxLayout *title_H_BoxLayout = new QHBoxLayout(); QHBoxLayout *closeBtn_H_BoxLayout = new QHBoxLayout(); title_H_BoxLayout->setContentsMargins(0,0,0,0); title_H_BoxLayout->setSpacing(0); title_H_BoxLayout->addSpacing(15); title_H_BoxLayout->addWidget(titleLabel); closeBtn_H_BoxLayout->addWidget(closeButton,1,Qt::AlignRight); closeBtn_H_BoxLayout->setContentsMargins(0,8,17,0); // m_titleBar->setFixedSize(this->width(), TITLE_BAR_HEIGHT); m_titleLabel = new QLabel(); m_titleLabel->setFixedWidth(80); m_titleLabel->setText(tr("Nice value:")); m_valueLabel = new QLabel(); m_slider = new QSlider(Qt::Horizontal); m_slider->setFocusPolicy(Qt::NoFocus); m_slider->setRange(-20, 19); m_slider->setSingleStep(1); h_layout = new QHBoxLayout(); h_layout->setSpacing(10); h_layout->setMargin(0); h_layout->setContentsMargins(20,0,20,0); h_layout->addWidget(m_titleLabel); h_layout->addWidget(m_slider); h_layout->addWidget(m_valueLabel); m_valueStrLabel = new QLabel; // m_valueStrLabel->setStyleSheet("QLabel{background-color:transparent;color:#000000;font-size:13px;font-weight:bold;}"); m_valueStrLabel->setAlignment(Qt::AlignCenter); m_valueStrLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_tipTitle = new QLabel; // m_tipTitle->setStyleSheet("QLabel{background-color:transparent;color:#000000;font-size:12px;font-weight:bold;}"); m_tipTitle->setText(tr("Note:")); m_tipLabel = new QLabel; m_tipLabel->setWordWrap(true);//QLabel自动换行 m_tipLabel->setFixedWidth(388); m_tipLabel->setText(tr("The priority of a process is given by its nice value. A lower nice value corresponds to a higher priority.")); tip_layout = new QHBoxLayout(); tip_layout->setSpacing(5); tip_layout->setMargin(0); tip_layout->setContentsMargins(20,0,20,0); tip_layout->addWidget(m_tipTitle); tip_layout->addWidget(m_tipLabel); m_cancelbtn = new QPushButton; m_cancelbtn->setFixedSize(91, 25); m_cancelbtn->setObjectName("blackButton"); m_cancelbtn->setFocusPolicy(Qt::NoFocus); m_cancelbtn->setText(tr("Cancel")); m_changeBtn = new QPushButton; m_changeBtn->setFixedSize(91, 25); m_changeBtn->setObjectName("blackButton"); m_changeBtn->setFocusPolicy(Qt::NoFocus); m_changeBtn->setText(tr("Change Priority")); btn_layout = new QHBoxLayout(); btn_layout->setMargin(0); btn_layout->setSpacing(10); btn_layout->setContentsMargins(0,0,20,0); btn_layout->addStretch(); btn_layout->addWidget(m_cancelbtn); btn_layout->addWidget(m_changeBtn); QVBoxLayout *v_layout = new QVBoxLayout(); v_layout->setMargin(0); v_layout->setSpacing(15); v_layout->setContentsMargins(0,0,0,0); v_layout->addLayout(h_layout); v_layout->addWidget(m_valueStrLabel, 0, Qt::AlignHCenter); v_layout->addLayout(tip_layout); v_layout->addLayout(btn_layout); m_mainLayout->addLayout(closeBtn_H_BoxLayout); m_mainLayout->addLayout(title_H_BoxLayout); m_mainLayout->addLayout(v_layout); connect(m_slider, &QSlider::valueChanged, [=] (int value) { m_valueLabel->setText(QString::number(value)); QString levelStr = getNiceLevelWithPriority(value); m_valueStrLabel->setText(levelStr); }); // connect(m_titleBar, SIGNAL(minSignal()), this, SLOT(hide())); // connect(m_titleBar, SIGNAL(closeSignal()), this, SLOT(onClose())); connect(m_cancelbtn, SIGNAL(clicked(bool)), this, SLOT(onClose())); connect(closeButton,SIGNAL(clicked(bool)),this,SLOT(onClose())); connect(m_changeBtn, &QPushButton::clicked, [=] (bool b) { emit this->resetReniceValue(m_slider->value()); }); //边框阴影效果 // QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect(this); // shadow_effect->setBlurRadius(5); // shadow_effect->setColor(QColor(0, 0, 0, 127)); // shadow_effect->setOffset(2, 4); // this->setGraphicsEffect(shadow_effect); // this->moveCenter(); QDesktopWidget* desktop = QApplication::desktop(); this->move((desktop->width() - this->width())/2, (desktop->height() - this->height())/3); } ReniceDialog::~ReniceDialog() { // delete m_titleBar; delete m_valueStrLabel; QLayoutItem *child; while ((child = h_layout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = tip_layout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } while ((child = btn_layout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } delete m_mainLayout; } void ReniceDialog::onClose() { this->close(); } void ReniceDialog::loadData(int nice) { m_slider->setValue(nice); m_valueLabel->setText(QString::number(nice)); QString levelStr = getNiceLevelWithPriority(nice); m_valueStrLabel->setText(levelStr); } void ReniceDialog::moveCenter() { /*QPoint pos = QCursor::pos(); QRect primaryGeometry; for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { primaryGeometry = screen->geometry(); } } if (primaryGeometry.isEmpty()) { primaryGeometry = qApp->primaryScreen()->geometry(); } this->move(primaryGeometry.x() + (primaryGeometry.width() - this->width())/2, primaryGeometry.y() + (primaryGeometry.height() - this->height())/2); this->show(); this->raise();*/ } void ReniceDialog::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->m_dragPosition = event->globalPos() - frameGeometry().topLeft(); this->m_mousePressed = true; } QDialog::mousePressEvent(event); } void ReniceDialog::mouseReleaseEvent(QMouseEvent *event) { this->m_mousePressed = false; setWindowOpacity(1); QDialog::mouseReleaseEvent(event); } void ReniceDialog::mouseMoveEvent(QMouseEvent *event) { if (this->m_mousePressed) { move(event->globalPos() - this->m_dragPosition); setWindowOpacity(0.9); } QDialog::mouseMoveEvent(event); } void ReniceDialog::paintEvent(QPaintEvent *event) { QPainter painter(this); //绘制圆角矩形 painter.setPen(QPen(QColor("#808080"), 0));//边框颜色 // painter.setBrush(QColor("#e9eef0"));//背景色 #0d87ca painter.setBrush(this->palette().base()); painter.setRenderHint(QPainter::Antialiasing, true); painter.setOpacity(1); QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边 painter.drawRoundedRect(r, 4, 4); //绘制背景色 // QPainterPath path; // path.addRect(QRectF(rect())); // painter.setOpacity(1); // painter.fillPath(path, QColor("#ffffff")); QDialog::paintEvent(event); } ukui-system-monitor/src/filesystemworker.h0000644000175000017500000000277213746753504020066 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FILESYSTEMWORKER_H #define FILESYSTEMWORKER_H #include #include #include #include "filesystemdata.h" class FileSystemWorker : public QObject { Q_OBJECT public: explicit FileSystemWorker(QObject *parent = 0); ~FileSystemWorker(); void removeDiskItem(const QString &devname); FileSystemData *getDiskInfo(const QString &devname); QList diskInfoList() const; void addDiskInfo(const QString &devname, FileSystemData *info); void removeDiskInfo(const QString &devname); bool isDeviceContains(const QString &devname); public slots: void onFileSystemListChanged(); private: QMap m_diskInfoList; }; #endif // FILESYSTEMWORKER_H ukui-system-monitor/src/processmanager.h0000644000175000017500000000276113746753504017457 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include //#include "../../component/plugininterface.h" #include "systemmonitor.h" //插件入口 class ProcessManager : public QObject//, PluginInterface { Q_OBJECT // Q_INTERFACES(PluginInterface) #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) Q_PLUGIN_METADATA(IID "com.ukui.Plugin.PluginInterface" FILE "systemmonitor.json")//指定IID和.json文件 #endif public: explicit ProcessManager(QObject* parent = 0); virtual ~ProcessManager(); QWidget *centralWidget(); public: virtual QString getGuid(); virtual QString getName(); virtual QString getDescribe(); virtual QString getPicture(); virtual void doAction(); private: SystemMonitor *process_dialog = nullptr; }; ukui-system-monitor/src/newresource/0000755000175000017500000000000013764351135016622 5ustar fengfengukui-system-monitor/src/newresource/sigcheck.h0000644000175000017500000000220413764112246020547 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _SIGCHECK_H_ #define _SIGCHECK_H_ #include #include #include #include #include "../shell/macro.h" class sigCheck : public QWidget{ public: sigCheck(QWidget * parent=0,int whichSig = 0); ~sigCheck(); protected: void paintEvent(QPaintEvent *event) override; private : int sig; }; #endif //_SIGCHECK_H_ ukui-system-monitor/src/newresource/swapandmemorychart.h0000644000175000017500000000364113764112246022705 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _SWAPANDMEMORYCHART_H #define _SWAPANDMEMORYCHART_H #include #include #include #include #include #include #include #include "smoothlinegenerator.h" class SwapAndMemoryChart : public QWidget { Q_OBJECT public: SwapAndMemoryChart(QWidget *parent = 0); ~SwapAndMemoryChart(); void refreshMemoryAndSwapData(float,double,float,double); protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); private: QColor m_outsideBorderColor; QColor m_memoryColor; QColor m_swapColor; QColor m_bgColor; float m_memoryData; float m_swapData; QList *m_memoryDataList; QList *m_swapDataList; int m_pointsCount; int m_pointSpace; int m_memoryMaxHeight; int m_swapMaxHeight; QPainterPath m_memoryPath; QPainterPath m_swapPath; int countWidth; QList xList; //x数据链 QList yDrawList; //y数据链 int showValue; public slots: void onUpdateMemoryAndSwapData(float,double,float,double); }; #endif //#define _SWAPANDMEMORYCHART_H ukui-system-monitor/src/newresource/sigcheck.cpp0000644000175000017500000000352713764112246021113 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "sigcheck.h" sigCheck::sigCheck(QWidget *parent,int whichSig) : QWidget(parent),sig(whichSig) { this->setFixedSize(14,14); } sigCheck::~sigCheck() { } void sigCheck::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); if(sig == REDTYPE) { p.setBrush(QBrush(QColor(246,79,61))); } if(sig == PURPLETYPE) { p.setBrush(QBrush(QColor(204,72,255))); } if(sig == GREENTYPE) { p.setBrush(QBrush(QColor(26,195,161))); } if(sig == BLUETYPE) { p.setBrush(QBrush(QColor(42,177,232))); } if(sig == YELLOWTYPE) { p.setBrush(QBrush(QColor(241,191,48))); } p.setPen(Qt::NoPen); QPainterPath path; opt.rect.adjust(0,0,0,0); path.addRoundedRect(opt.rect,2,2); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,2,2); setProperty("blurRegion",QRegion(path.toFillPolygon().toPolygon())); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-system-monitor/src/newresource/networkchart.h0000644000175000017500000000322413764070001021475 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _NETWORKCHART_H_ #define _NETWORKCHSRT_H_ #include #include #include class NetWorkChart : public QWidget { Q_OBJECT public: NetWorkChart(QWidget *parent = 0); ~NetWorkChart(); protected: void paintEvent(QPaintEvent *event); private: QColor m_outsideBorderColor; QColor m_downLoadColor; QColor m_upLoadColor; QPainterPath m_downLoadPath; QPainterPath m_upLoadPath; int m_pointsCount; QColor m_bgColor; double m_downLoadSpeed; double m_downLoadMaxHeight; double m_upLoadSpeed; double m_upLoadMaxHeight; QList *m_downLoadList; QList *m_upLoadList; public slots: void onUpdateDownloadAndUploadData(long,long,long,long); signals: // void speedToMib(); void speedToLowKib(); // void speedToMiddleKib(); void speedToHighKib(); }; #endif //_NETWORKCHSRT_H_ ukui-system-monitor/src/newresource/newresourcesdialog.h0000644000175000017500000001061413764070001022667 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "../shell/macro.h" #include "sigcheck.h" #include "cpuhistorychart.h" #include "swapandmemorychart.h" #include "networkchart.h" typedef struct MemoryInfo { float total; float free; float cached; float used; float user; float percent; float swaptotal; float swapfree; float swapcached; float swapused; float swappercent; }Meminfo; class NewResouresDialog : public QWidget { Q_OBJECT public: explicit NewResouresDialog(QWidget* parent = 0); ~NewResouresDialog(); void startCpuTimer(); void stopCpuTimer(); void initFontSize(); void tosetFontSize(); void setChangeNetSpeedLabel(); private: //cpu unsigned long long m_prevCpuTotalTime; unsigned long long m_prevCpuWorkTime; unsigned long long m_cpuTotalTime; unsigned long long m_cpuworkTime; //network unsigned long long int m_totalRecvBytes; unsigned long long int m_totalSentBytes; unsigned long long int m_rateRecvBytes; unsigned long long int m_rateSentBytes; QTimer *updateStatusTimer = nullptr; QHBoxLayout *m_hlayout = nullptr; QLabel *cpuHistoryLabel = nullptr; QLabel *memoryAndSwapLabel = nullptr; QLabel *netWorkFlowLabel = nullptr; QLabel *cpuUnitDataLabel = nullptr; QLabel *memoryUnitDataLabel = nullptr; QLabel *swapUnitDataLabel = nullptr; QLabel *netrecvUnitDataLabel = nullptr; QLabel *netsentUnitDataLabel = nullptr; QLabel *theFirtSpeedLabel = nullptr; QLabel *theSecondSpeedLabel = nullptr; QLabel *theThirdSpeedLabel = nullptr; QLabel *theFourthSpeedLabel = nullptr; QLabel *theFifthSpeedLabel = nullptr; QWidget *cpuWidget = nullptr; QWidget *swapmemoryWiget = nullptr; QWidget *networkWidget = nullptr; QGSettings *fontSettings; sigCheck *typeCheckCpu; sigCheck *typeCheckMemory; sigCheck *typeCheckSwap; sigCheck *typeCheckNetRecv; sigCheck *typeCheckNetSent; CpuHistoryChart *histoyChart; SwapAndMemoryChart *swapandmemoryChart; NetWorkChart *networkChart; Meminfo mi; QPalette pe; QHBoxLayout *cputitle_H_BoxLayout; QHBoxLayout *cpuUnit_H_BoxLayout; QHBoxLayout *cpuChart_H_BoxLayout; QHBoxLayout *swapmemoryTitle_H_BoxLayout; QHBoxLayout *swapmemoryUnit_H_BoxLayout; QHBoxLayout *memoryswapChart_H_BoxLayout; QHBoxLayout *netWorkTitle_H_BoxLayout; QHBoxLayout *networkUnit_H_BoxLayout; QHBoxLayout *networkChart_H_BoxLayout; QVBoxLayout *main_V_BoxLayout; public: int fontSize; private: void initWidget(); void initCpuHistory(); void initSwapMeomoryHistory(); void initNetSpeedHistory(); public slots: void updateResourceStatus(); void cpuHistoySetText(double percent); void memoryandswapSetText(const QString &infoMemory, double percentMemory,const QString &infoSwap, double percentSwap); void networkSetText(long recvTotalBytes, long sentTotalBytes, long recvRateBytes, long sentRateBytes); void onUpdateMemoryAndSwapStatus(); signals: void updateCpuStatus(double percent); void rebackMemoryAndSwapInfo(const QString &infoMemory, double percentMemory,const QString &infoSwap, double percentSwap); void rebackMemoryAndSwapData(float memory,double percentMemory,float swap,double percentSwap); void updateMemoryAndSwapStatus(); void updateNetworkStatus(long recvTotalBytes, long sentTotalBytes, long recvRateBytes, long sentRateBytes); void resetWidget(); }; ukui-system-monitor/src/newresource/swapandmemorychart.cpp0000644000175000017500000002127013764350634023243 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "swapandmemorychart.h" #include "../shell/macro.h" #include inline double formatMemory(double size) { enum { K_INDEX, M_INDEX, G_INDEX, T_INDEX }; QList factorList; factorList.append(G_GUINT64_CONSTANT(1) << 10);//KiB factorList.append(G_GUINT64_CONSTANT(1) << 20);//MiB factorList.append(G_GUINT64_CONSTANT(1) << 30);//GiB factorList.append(G_GUINT64_CONSTANT(1) << 40);//TiB guint64 factor; if (size < factorList.at(T_INDEX)) { factor = factorList.at(G_INDEX); } else { factor = factorList.at(T_INDEX); } return size/(double)factor; } SwapAndMemoryChart::SwapAndMemoryChart(QWidget *parent):QWidget(parent) ,m_outsideBorderColor("transparent") ,m_memoryColor(QColor("#cc72ff")) ,m_swapColor(QColor("#26c3a1")) { this->setMinimumSize(680,90); this->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Expanding); m_pointsCount = int(this->width() / POINTSPACE); m_memoryDataList = new QList(); m_swapDataList = new QList(); m_memoryMaxHeight = this->width()/2; m_swapMaxHeight = this->width()/2; } SwapAndMemoryChart::~SwapAndMemoryChart() { if(m_memoryDataList) { delete m_memoryDataList; } if(m_swapDataList) { delete m_swapDataList; } } void SwapAndMemoryChart::onUpdateMemoryAndSwapData(float memoryData,double memoryPercent,float swapData,double swapPercent) { refreshMemoryAndSwapData(memoryData,memoryPercent,swapData,swapPercent); } void SwapAndMemoryChart::refreshMemoryAndSwapData(float memoryData, double memoryPercent, float swapData, double swapPercent) { m_memoryData = formatMemory(memoryData) * 9 *(rect().height() / 90); // qDebug()<<"m_memoryData"< memoryPoints; m_memoryDataList->append(m_memoryData); while (m_memoryDataList->size() > m_pointsCount) { m_memoryDataList->pop_front(); } //计算出Cpu历史占用率的最大的值 double memoryMaxHeight = 0.0; for (int i = 0; i < m_memoryDataList->size(); i++) { if (m_memoryDataList->at(i) > memoryMaxHeight) { memoryMaxHeight = m_memoryDataList->at(i); } } for (int i = 0; i < m_memoryDataList->size(); i++) { // qDebug() << "m_CpuHistoryList.size" << m_memoryDataList->size(); if (memoryMaxHeight < m_memoryMaxHeight) { memoryPoints.append(QPointF((m_memoryDataList->size() - i -2) * POINTSPACE, m_memoryDataList->at(i))); } else { memoryPoints.append(QPointF((m_memoryDataList->size() - i -2) * POINTSPACE, m_memoryDataList->at(i) * m_memoryMaxHeight /memoryMaxHeight)); } } m_memoryPath = SmoothLineGenerator::generateSmoothCurve(memoryPoints); QList swapPoints; m_swapDataList->append(m_swapData); while (m_swapDataList->size() > m_pointsCount) { m_swapDataList->pop_front(); } double swapMaxHeight = 0.0; for (int i = 0; i < m_swapDataList->size(); i++) { if (m_swapDataList->at(i) > swapMaxHeight) { swapMaxHeight = m_swapDataList->at(i); } } for (int i = 0; i < m_swapDataList->size(); i++) { // qDebug() << "m_CpuHistoryList.size" << m_swapDataList->size(); if (swapMaxHeight < m_swapMaxHeight) { swapPoints.append(QPointF((m_swapDataList->size() - i -2) * POINTSPACE, m_swapDataList->at(i))); } else { swapPoints.append(QPointF((m_swapDataList->size() - i -2) * POINTSPACE, m_swapDataList->at(i) * m_swapMaxHeight /swapMaxHeight)); } } m_swapPath = SmoothLineGenerator::generateSmoothCurve(swapPoints); } void SwapAndMemoryChart::resizeEvent(QResizeEvent *event) { m_pointsCount = int(this->width() / POINTSPACE); } void SwapAndMemoryChart::paintEvent(QPaintEvent *event) { QPainter painter(this); //background of rect painter.save(); painter.setOpacity(0.08); QPainterPath framePath; QStyleOption opt; opt.init(this); m_bgColor = (QColor("#131414")); framePath.addRoundedRect(rect(),4,4); painter.fillPath(framePath, this->m_bgColor);//painter.drawPath(framePath); painter.restore(); //draw separate line painter.save(); painter.setOpacity(0.3); int distance = this->rect().height()/4; painter.setPen(this->palette().color(QPalette::Base)); painter.setBrush(Qt::NoBrush); painter.drawLine(rect().x(), rect().y() + distance, rect().right(), rect().y() + distance); painter.drawLine(rect().x(), rect().y() + distance * 2, rect().right(), rect().y() + distance * 2); painter.drawLine(rect().x(), rect().y() + distance * 3, rect().right(), rect().y() + distance * 3); painter.restore(); //draw memory line /************************* old draw memory line ************************ painter.save(); painter.setOpacity(1); painter.translate((rect().width() - m_pointsCount * POINTSPACE - 2) / 2 + 6, 89);//将坐标的原点移动到该点 painter.scale(1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 QPen pen(this->m_memoryColor,1); pen.setWidth(5); painter.setPen(pen); painter.setBrush(QBrush());//painter.setBrush(QBrush(QColor("#f4f2f4"))); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_memoryPath);//绘制前面创建的path:m_downloadPath painter.restore(); ////////////////////////////old tu painter.save(); painter.translate(rect().right(),rect().bottom() - 1); painter.setRenderHint(QPainter::Antialiasing, true); //设置折线反锯齿 painter.scale(-1,-1); QPen pen(m_memoryColor,1); pen.setWidth(3); painter.setPen(pen); for(int i = 0; i < m_pointsCount - 1; i++) { qDebug()<<"m_pointsCount---"<at(i+1)); painter.drawLine(QPointF(i*POINTSPACE,m_memoryDataList->at(i)),point); } painter.restore(); ******************************** old draw memory line *****************/ painter.save(); painter.translate(rect().right(),rect().bottom()); painter.scale(-1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 // painter.translate((rect().width() - m_pointsCount * POINTSPACE - 2) / 2 + 6, 89);//将坐标的原点移动到该点 QPen pen(this->m_memoryColor,5); painter.setPen(pen); painter.setBrush(QBrush());//painter.setBrush(QBrush(QColor("#f4f2f4"))); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_memoryPath);//绘制前面创建的path:m_downloadPath painter.restore(); //draw swap line /*********** old draw swap line *************** painter.save(); painter.translate(0,rect().bottom() - 3); painter.setRenderHint(QPainter::Antialiasing, true); //设置折线反锯齿 painter.scale(1,-1); QPen penSwap(m_swapColor,1); penSwap.setWidth(3); painter.setPen(penSwap); for(int i = 0; i < m_pointsCount - 1; i++) { qDebug()<<"m_pointsCount---"<at(i+1)); painter.drawLine(QPointF(i*POINTSPACE,m_swapDataList->at(i)),point); } painter.restore(); ******************** old draw swap line**************/ painter.save(); painter.translate(rect().right(),rect().bottom()); painter.scale(-1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 QPen penSwap(this->m_swapColor,5); painter.setPen(penSwap); painter.setBrush(QBrush());//painter.setBrush(QBrush(QColor("#f4f2f4"))); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_swapPath);//绘制前面创建的path:m_downloadPath painter.restore(); QWidget::paintEvent(event); } ukui-system-monitor/src/newresource/cpuhistorychart.h0000644000175000017500000000315213764112246022225 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _CPUHISTORYCHART_H_ #define _CPUHISTORYCHART_H_ #include #include #include #include class CpuHistoryChart : public QWidget { Q_OBJECT public: CpuHistoryChart(QWidget *parent = 0); ~CpuHistoryChart(); void refreshCpuHistoryData(double cpu); protected: void paintEvent(QPaintEvent *event); private: QPointF point; QColor m_outsideBorderColor; QColor m_cpuHistoryColor; QPainterPath m_cpuHistoryPath; QList *m_CpuHistoryList; QList xList; //x数据链 QList yDrawList; //y数据链 int m_pointsCount; QColor m_bgColor; double m_Cpu; double m_cpuMaxHeight; int showValue; public slots: void onUpdateCpuPercent(double value); // void onUpdateCpuHistoryStatus(double value); }; #endif //_CPUHISTORYCHART_H_ ukui-system-monitor/src/newresource/networkchart.cpp0000644000175000017500000001567213764350474022061 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "networkchart.h" #include "../shell/macro.h" #include "smoothlinegenerator.h" #include #include NetWorkChart::NetWorkChart(QWidget *parent):QWidget(parent) ,m_outsideBorderColor("transparent") ,m_downLoadColor(QColor("#42b1eb")) ,m_upLoadColor(QColor("#f1bf48")) { this->setMinimumSize(680,90); this->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding); m_pointsCount = int((this->width()) /10); m_downLoadMaxHeight = int(this->width()/2); m_downLoadList = new QList(); m_upLoadMaxHeight = int(this->width()/2); m_upLoadList = new QList(); } NetWorkChart::~NetWorkChart() { if(m_downLoadList) { delete m_downLoadList; } if(m_upLoadList) { delete m_upLoadList; } } void NetWorkChart::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.save(); painter.setOpacity(0.08); QPainterPath framePath; QStyleOption opt; opt.init(this); m_bgColor = (QColor("#131414")); framePath.addRoundedRect(rect(),4,4); painter.fillPath(framePath, this->m_bgColor);//painter.drawPath(framePath); painter.restore(); //draw separate lines painter.save(); painter.setOpacity(0.3); int distance = this->rect().height()/4; painter.setPen(this->palette().color(QPalette::Base)); painter.setBrush(Qt::NoBrush); painter.drawLine(rect().x(), rect().y() + distance, rect().right(), rect().y() + distance); painter.drawLine(rect().x(), rect().y() + distance * 2, rect().right(), rect().y() + distance * 2); painter.drawLine(rect().x(), rect().y() + distance * 3, rect().right(), rect().y() + distance * 3); painter.restore(); //draw download line painter.save(); // painter.translate((rect().width() - m_pointsCount * POINTSPACE - 2) / 2 + 6, 89);//将坐标的原点移动到该点 painter.translate(rect().right(),rect().bottom() - 2); painter.scale(-1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 QPen pen(this->m_downLoadColor,2); painter.setPen(pen); painter.setBrush(QBrush());//painter.setBrush(QBrush(QColor("#f4f2f4"))); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_downLoadPath);//绘制前面创建的path:m_downloadPath painter.restore(); //draw upload line painter.save(); painter.setOpacity(1); painter.translate(rect().right(),rect().bottom());//将坐标的原点移动到该点 painter.scale(-1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 QPen penUpload(this->m_upLoadColor,2); painter.setPen(penUpload); painter.setBrush(QBrush());//painter.setBrush(QBrush(QColor("#f4f2f4"))); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_upLoadPath);//绘制前面创建的path:m_downloadPath painter.restore(); QWidget::paintEvent(event); } void NetWorkChart::onUpdateDownloadAndUploadData(long recvTotalBytes, long sentTotalBytes, long recvRateBytes, long sentRateBytes) { // qDebug()<<"recvRateBytes"<= 1024 * 1024) // { // emit this->speedToMib(); // } if( recvRateBytes + sentRateBytes <= 20 * 1024) { emit this->speedToLowKib(); } // if(recvRateBytes + sentRateBytes > 20 *1024 && recvRateBytes + sentRateBytes <= 100 * 1024) // { // emit this->speedToMiddleKib(); // } if(recvRateBytes + sentRateBytes > 100 *1024 && recvRateBytes + sentRateBytes <= 1000 * 1024) { emit this->speedToHighKib(); } if(recvRateBytes+sentRateBytes < 1024 * 1024 *100) { if(recvRateBytes+sentRateBytes < 20 * 1024) { m_downLoadSpeed = (recvRateBytes/1024) * (this->height()/20); if(m_upLoadSpeed < 1024) { m_upLoadSpeed = 0; } if(m_upLoadSpeed > 1024 && m_upLoadSpeed < 20 * 1024) { m_upLoadSpeed = (sentRateBytes/1024) * this->height()/20; } } else { m_downLoadSpeed = (recvRateBytes/1000) * this->height()/1000; m_upLoadSpeed = (sentRateBytes/1024) * this->height()/1000; qDebug()<<"if i m_downLoadSpeed"<height()/1000; QList downLoadPoints; m_downLoadList->append(m_downLoadSpeed); while (m_downLoadList->size() > m_pointsCount) { m_downLoadList->pop_front(); } QList upLoadPoints; m_upLoadList->append(m_upLoadSpeed); while(m_upLoadList->size() > m_pointsCount) { m_upLoadList->pop_front(); } double downLoadMaxHeight = 0.0; for (int i = 0; i < m_downLoadList->size(); i++) { if (m_downLoadList->at(i) > downLoadMaxHeight) { downLoadMaxHeight = m_downLoadList->at(i); } } for (int i = 0; i < m_downLoadList->size(); i++) { // if (downLoadMaxHeight < m_downLoadMaxHeight) // { downLoadPoints.append(QPointF((m_downLoadList->size() - i -2) * POINTSPACE, m_downLoadList->at(i))); // } // else // { // downLoadPoints.append(QPointF((m_downLoadList->size() - i -2) * POINTSPACE, m_downLoadList->at(i) * m_downLoadMaxHeight /downLoadMaxHeight)); // } } m_downLoadPath = SmoothLineGenerator::generateSmoothCurve(downLoadPoints); double upLoadMaxHeight = 0.0; for (int i = 0; i < m_upLoadList->size(); i++) { if (m_upLoadList->at(i) > upLoadMaxHeight) { upLoadMaxHeight = m_upLoadList->at(i); } } for (int i = 0; i < m_upLoadList->size(); i++) { if (upLoadMaxHeight < m_upLoadMaxHeight) { upLoadPoints.append(QPointF((m_upLoadList->size() - i -2) * POINTSPACE, m_upLoadList->at(i))); } else { upLoadPoints.append(QPointF((m_upLoadList->size() - i -2) * POINTSPACE, m_upLoadList->at(i) * m_upLoadMaxHeight /upLoadMaxHeight)); } } m_upLoadPath = SmoothLineGenerator::generateSmoothCurve(upLoadPoints); } ukui-system-monitor/src/newresource/newresourcesdialog.cpp0000644000175000017500000005356313764351135023246 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "newresourcesdialog.h" #include "util.h" #include #include #include #include //get cpu history data static unsigned long long getCpuTimeData(unsigned long long &workTime); unsigned long long getCpuTimeData(unsigned long long &workTime) { FILE *file = fopen("/proc/stat", "r"); if (file == NULL) { return 0; } char buffer[1024] = {0}; unsigned long long user = 0, nice = 0, system = 0, idle = 0; unsigned long long iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guestnice = 0; char* ret = fgets(buffer, sizeof(buffer) - 1, file); if (ret == NULL) { fclose(file); return 0; } fclose(file); sscanf(buffer, "cpu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu", &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guestnice); workTime = user + nice + system; return user + nice + system + idle + iowait + irq + softirq + steal; } //get swap and memory data inline QString formatMemory(guint64 size) { enum { K_INDEX, M_INDEX, G_INDEX, T_INDEX }; QList factorList; factorList.append(G_GUINT64_CONSTANT(1) << 10);//KiB factorList.append(G_GUINT64_CONSTANT(1) << 20);//MiB factorList.append(G_GUINT64_CONSTANT(1) << 30);//GiB factorList.append(G_GUINT64_CONSTANT(1) << 40);//TiB if (size < factorList.at(K_INDEX)) { if ((guint) size > 1) { return QString("%1 %2").arg((guint) size).arg(QObject::tr("bit")); } else { return QString("%1 %2").arg((guint) size).arg(QObject::tr("bits")); } } else { guint64 factor; QString format; if (size < factorList.at(M_INDEX)) { factor = factorList.at(K_INDEX); format = QObject::tr("KiB"); } else if (size < factorList.at(G_INDEX)) { factor = factorList.at(M_INDEX); format = QObject::tr("MiB"); } if (size < factorList.at(T_INDEX)) { factor = factorList.at(G_INDEX); format = QObject::tr("GiB"); } else { factor = factorList.at(T_INDEX); format = QObject::tr("TiB"); } std::string formatted_result(make_string(g_strdup_printf("%.1f", size / (double)factor))); return QString::fromStdString(formatted_result) + format; } } void NewResouresDialog::onUpdateMemoryAndSwapStatus() { glibtop_mem mem; glibtop_swap swap; glibtop_get_mem(&mem); glibtop_get_swap(&swap); float swappercent = (swap.total ? (float)swap.used / (float)swap.total : 0.0f); float mempercent = (float)mem.user / (float)mem.total; mi.percent = mempercent * 100; mi.swappercent = swappercent * 100; //初始单位为字节,需要修正 mi.user = mem.user; mi.total = mem.total; mi.swapused = swap.used; mi.swaptotal = swap.total; const QString infoMemory = QString("%1/%2").arg(formatMemory(mi.user)).arg(formatMemory(mi.total)); const QString infoSwap = QString("%1/%2").arg(formatMemory(mi.swapused)).arg(formatMemory(mi.swaptotal)); emit rebackMemoryAndSwapInfo(infoMemory, mi.percent,infoSwap,mi.swappercent); emit rebackMemoryAndSwapData(mi.user,mi.percent,mi.swapused,mi.swappercent); // emit rebackSwapInfo(infoSwap,mi.swappercent); repaint();//this->update(); } //get network data typedef struct _net { guint64 last_in, last_out; GTimeVal time; } net; net netinfo; inline void getNetworkBytesData(unsigned long long int &receiveBytes, unsigned long long int &sendBytes, unsigned long long int &receiveRateBytes, unsigned long long int &sendRateBytes) { glibtop_netlist netlist; char **ifnames; guint32 i; guint64 in = 0, out = 0; GTimeVal time; guint64 din, dout; ifnames = glibtop_get_netlist(&netlist); for (i = 0; i < netlist.number; ++i) { glibtop_netload netload; glibtop_get_netload(&netload, ifnames[i]); if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK)) continue; /* Skip interfaces without any IPv4/IPv6 address (or those with only a LINK ipv6 addr) However we need to be able to exclude these while still keeping the value so when they get online (with NetworkManager for example) we don't get a suddent peak. Once we're able to get this, ignoring down interfaces will be possible too. */ if (not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6) and netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK) and not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS))) continue; /* Don't skip interfaces that are down (GLIBTOP_IF_FLAGS_UP) to avoid spikes when they are brought up */ in += netload.bytes_in; out += netload.bytes_out; } g_strfreev(ifnames); g_get_current_time(&time); if (in >= netinfo.last_in && out >= netinfo.last_out && netinfo.time.tv_sec != 0) { float dtime; dtime = time.tv_sec - netinfo.time.tv_sec + (double) (time.tv_usec - netinfo.time.tv_usec) / G_USEC_PER_SEC; din = static_cast((in - netinfo.last_in) / dtime); dout = static_cast((out - netinfo.last_out) / dtime); } else { /* Don't calc anything if new data is less than old (interface removed, counters reset, ...) or if it is the first time */ din = 0; dout = 0; } netinfo.last_in = in; netinfo.last_out = out; netinfo.time = time; receiveBytes = in; sendBytes = out; receiveRateBytes = din; sendRateBytes = dout; } inline QString formatNetworkBrandWidth(guint64 size, bool isTotal) { enum { K_INDEX, M_INDEX, G_INDEX, T_INDEX }; QList factorList; factorList.append(G_GUINT64_CONSTANT(1) << 10);//KiB factorList.append(G_GUINT64_CONSTANT(1) << 20);//MiB factorList.append(G_GUINT64_CONSTANT(1) << 30);//GiB factorList.append(G_GUINT64_CONSTANT(1) << 40);//TiB if (size < factorList.at(K_INDEX)) { if ((guint) size > 1) { return QString("%1 %2").arg((guint) size).arg(QObject::tr("bits/s")); } else { return QString("%1 %2").arg((guint) size).arg(QObject::tr("bits/s")); } } else { guint64 factor; QString format; if (size < factorList.at(M_INDEX)) { factor = factorList.at(K_INDEX); if (isTotal) format = QObject::tr("KiB"); else format = QObject::tr("KiB/s"); }else if (size < factorList.at(G_INDEX)) { factor = factorList.at(M_INDEX); if (isTotal) format = QObject::tr("MiB"); else format = QObject::tr("MiB/s"); } else if (size < factorList.at(T_INDEX)) { factor = factorList.at(G_INDEX); if (isTotal) format = QObject::tr("GiB"); else format = QObject::tr("GiB/s"); } else { factor = factorList.at(T_INDEX); if (isTotal) format = QObject::tr("TiB"); else format = QObject::tr("TiB/s"); } std::string formatted_result(make_string(g_strdup_printf("%.1f", size / (double)factor))); return QString::fromStdString(formatted_result) + format; } } inline QString formatNetworkRate(guint64 rate) { return formatNetworkBrandWidth(rate, false); } NewResouresDialog::NewResouresDialog(QWidget *parent) :QWidget(parent) { cpuUnitDataLabel = new QLabel; memoryUnitDataLabel = new QLabel; swapUnitDataLabel = new QLabel; netrecvUnitDataLabel = new QLabel; netsentUnitDataLabel = new QLabel; pe.setColor(QPalette::WindowText,QColor(13,14,13,130)); const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } initFontSize(); initWidget(); setChangeNetSpeedLabel(); tosetFontSize(); updateStatusTimer = new QTimer(this); connect(updateStatusTimer, SIGNAL(timeout()), this, SLOT(updateResourceStatus())); //cpu history conecct connect(this, SIGNAL(updateCpuStatus(double)), histoyChart, SLOT(onUpdateCpuPercent(double))); connect(this,SIGNAL(updateCpuStatus(double)),this,SLOT(cpuHistoySetText(double))); //swap and memory connect connect(this,SIGNAL(updateMemoryAndSwapStatus()),this,SLOT(onUpdateMemoryAndSwapStatus())); connect(this,SIGNAL(rebackMemoryAndSwapInfo(const QString, double,const QString, double)),this,SLOT(memoryandswapSetText(QString,double,QString,double))); connect(this,SIGNAL(rebackMemoryAndSwapData(float,double,float,double)),swapandmemoryChart,SLOT(onUpdateMemoryAndSwapData(float,double,float,double))); //network connect connect(this,SIGNAL(updateNetworkStatus(long,long,long,long)),this,SLOT(networkSetText(long,long,long,long))); connect(this,SIGNAL(updateNetworkStatus(long,long,long,long)),networkChart,SLOT(onUpdateDownloadAndUploadData(long,long,long,long))); updateStatusTimer->start(500); } NewResouresDialog::~NewResouresDialog() { QLayoutItem *child; while ((child = main_V_BoxLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } } void NewResouresDialog::setChangeNetSpeedLabel() { connect(networkChart,&NetWorkChart::speedToLowKib,this,[=](){ theFifthSpeedLabel->setText(tr("20Kib")); theFourthSpeedLabel->setText(tr("15Kib")); theThirdSpeedLabel->setText(tr("10Kib")); theSecondSpeedLabel->setText(tr("5Kib")); theFirtSpeedLabel->setText(tr("0Kib")); }); connect(networkChart,&NetWorkChart::speedToHighKib,this,[=](){ theFifthSpeedLabel->setText(tr("1000Kib")); theFourthSpeedLabel->setText(tr("750Kib")); theThirdSpeedLabel->setText(tr("500Kib")); theSecondSpeedLabel->setText(tr("250Kib")); theFirtSpeedLabel->setText(tr("0Kib")); }); } void NewResouresDialog::cpuHistoySetText(double value) { QString showValue; showValue = QString::number(value,10,0); QString s = "Cpu "+ showValue +":100%"; cpuUnitDataLabel->setText(s); // qDebug() << "cpu value: " << value; } void NewResouresDialog::memoryandswapSetText(const QString &infoMemory, double percentMemory,const QString &infoSwap, double percentSwap) { QString showMemoryValue; showMemoryValue = infoMemory; QString sMemory = tr("memory:")+infoMemory; memoryUnitDataLabel->setText(sMemory); QString showSwapValue; showSwapValue = infoSwap; QString sSwap = tr("swap:")+showSwapValue; swapUnitDataLabel->setText(sSwap); } void NewResouresDialog::networkSetText(long recvTotalBytes, long sentTotalBytes, long recvRateBytes, long sentRateBytes) { const QString downloadRate = formatNetworkRate(recvRateBytes); const QString uploadRate = formatNetworkRate(sentRateBytes); QString showReceiveValue = downloadRate; QString sRecv = tr("receive:") + showReceiveValue; QString showSendValue = uploadRate; QString sSend = tr("send:") +showSendValue; netrecvUnitDataLabel->setText(sRecv); netsentUnitDataLabel->setText(sSend); } void NewResouresDialog::initWidget() { qDebug()<height()<<"this.height-------"; initCpuHistory(); initSwapMeomoryHistory(); initNetSpeedHistory(); main_V_BoxLayout = new QVBoxLayout; main_V_BoxLayout->setSpacing(0); main_V_BoxLayout->addLayout(cputitle_H_BoxLayout); main_V_BoxLayout->addLayout(cpuUnit_H_BoxLayout); main_V_BoxLayout->addLayout(cpuChart_H_BoxLayout); main_V_BoxLayout->addLayout(swapmemoryTitle_H_BoxLayout); main_V_BoxLayout->addLayout(swapmemoryUnit_H_BoxLayout); main_V_BoxLayout->addLayout(memoryswapChart_H_BoxLayout); main_V_BoxLayout->addLayout(netWorkTitle_H_BoxLayout); main_V_BoxLayout->addLayout(networkUnit_H_BoxLayout); main_V_BoxLayout->addLayout(networkChart_H_BoxLayout); main_V_BoxLayout->addSpacing(15); this->setLayout(main_V_BoxLayout); } void NewResouresDialog::initCpuHistory() { //set the part of CPU history cputitle_H_BoxLayout = new QHBoxLayout; cputitle_H_BoxLayout->setContentsMargins(13,0,0,0); cpuHistoryLabel = new QLabel(tr("CPU history")); cputitle_H_BoxLayout->addWidget(cpuHistoryLabel); cpuUnit_H_BoxLayout = new QHBoxLayout; typeCheckCpu = new sigCheck(this,REDTYPE); cpuUnitDataLabel->setPalette(pe); QHBoxLayout *cpuSig_H_BoxLayout = new QHBoxLayout; cpuSig_H_BoxLayout->setSpacing(0); cpuSig_H_BoxLayout->addStretch(1); cpuSig_H_BoxLayout->addWidget(typeCheckCpu); cpuSig_H_BoxLayout->addSpacing(8); cpuSig_H_BoxLayout->addWidget(cpuUnitDataLabel); cpuUnit_H_BoxLayout->addLayout(cpuSig_H_BoxLayout); cpuChart_H_BoxLayout = new QHBoxLayout; histoyChart = new CpuHistoryChart; QLabel *onehundredLabel = new QLabel(); onehundredLabel->setText("100%"); QLabel *threequarterLabel = new QLabel(); threequarterLabel->setText("75%"); QLabel *halfLabel = new QLabel(); halfLabel->setText("50%"); QLabel *onequarterLabel = new QLabel(); onequarterLabel->setText("25%"); QLabel *nullLabel = new QLabel(); nullLabel->setText("0%"); onehundredLabel->setPalette(pe); threequarterLabel->setPalette(pe); halfLabel->setPalette(pe); onequarterLabel->setPalette(pe); nullLabel->setPalette(pe); cpuWidget = new QWidget(); cpuWidget->setFixedWidth(55); QVBoxLayout *cpupercent_V_BoxLayout = new QVBoxLayout(); cpupercent_V_BoxLayout->setMargin(0); cpupercent_V_BoxLayout->addWidget(onehundredLabel,1,Qt::AlignRight); cpupercent_V_BoxLayout->addWidget(threequarterLabel,1,Qt::AlignRight); cpupercent_V_BoxLayout->addWidget(halfLabel,1,Qt::AlignRight); cpupercent_V_BoxLayout->addWidget(onequarterLabel,1,Qt::AlignRight); cpupercent_V_BoxLayout->addWidget(nullLabel,1,Qt::AlignRight); cpuWidget->setLayout(cpupercent_V_BoxLayout); cpuChart_H_BoxLayout->addWidget(cpuWidget); cpuChart_H_BoxLayout->addSpacing(10); cpuChart_H_BoxLayout->addWidget(histoyChart); cpuChart_H_BoxLayout->setSpacing(0); } void NewResouresDialog::initSwapMeomoryHistory() { //set the swap and memory history swapmemoryTitle_H_BoxLayout = new QHBoxLayout; swapmemoryTitle_H_BoxLayout->setContentsMargins(13,0,0,0); memoryAndSwapLabel = new QLabel(tr("memory and swap history")); swapmemoryTitle_H_BoxLayout->addWidget(memoryAndSwapLabel); swapmemoryUnit_H_BoxLayout = new QHBoxLayout; typeCheckMemory = new sigCheck(this,PURPLETYPE); typeCheckSwap = new sigCheck(this,GREENTYPE); memoryUnitDataLabel->setPalette(pe); swapUnitDataLabel->setPalette(pe); QHBoxLayout *swapandmemory_H_BoxLayout = new QHBoxLayout; swapandmemory_H_BoxLayout->setSpacing(0); swapandmemory_H_BoxLayout->addStretch(1); swapandmemory_H_BoxLayout->addWidget(typeCheckMemory); swapandmemory_H_BoxLayout->addSpacing(8); swapandmemory_H_BoxLayout->addWidget(memoryUnitDataLabel); swapandmemory_H_BoxLayout->addSpacing(10); swapandmemory_H_BoxLayout->addWidget(typeCheckSwap); swapandmemory_H_BoxLayout->addSpacing(8); swapandmemory_H_BoxLayout->addWidget(swapUnitDataLabel); swapmemoryUnit_H_BoxLayout->addLayout(swapandmemory_H_BoxLayout); memoryswapChart_H_BoxLayout = new QHBoxLayout; swapandmemoryChart = new SwapAndMemoryChart; QVBoxLayout *swapmemory_V_BoxLayout = new QVBoxLayout(); swapmemory_V_BoxLayout->setMargin(0); QLabel *tenGibLabel = new QLabel(); tenGibLabel->setText("10.0Gib"); swapmemoryWiget = new QWidget(); swapmemoryWiget->setFixedWidth(55); swapmemory_V_BoxLayout->addWidget(tenGibLabel,1,Qt::AlignRight); tenGibLabel->setPalette(pe); QLabel *sevenpointFiveGibLabel = new QLabel(); sevenpointFiveGibLabel->setText("7.5Gib"); swapmemory_V_BoxLayout->addWidget(sevenpointFiveGibLabel,1,Qt::AlignRight); sevenpointFiveGibLabel->setPalette(pe); QLabel *fiveGibLabel = new QLabel(); fiveGibLabel->setText("5.0Gib"); swapmemory_V_BoxLayout->addWidget(fiveGibLabel,1,Qt::AlignRight); fiveGibLabel->setPalette(pe); QLabel *twopointfiveGibLabel = new QLabel(); twopointfiveGibLabel->setText("2.5Gib"); swapmemory_V_BoxLayout->addWidget(twopointfiveGibLabel,1,Qt::AlignRight); twopointfiveGibLabel->setPalette(pe); QLabel *nullGibLabel = new QLabel(); nullGibLabel->setText("0.0Gib"); swapmemory_V_BoxLayout->addWidget(nullGibLabel,1,Qt::AlignRight); nullGibLabel->setPalette(pe); swapmemoryWiget->setLayout(swapmemory_V_BoxLayout); memoryswapChart_H_BoxLayout->addWidget(swapmemoryWiget); memoryswapChart_H_BoxLayout->addSpacing(10); memoryswapChart_H_BoxLayout->addWidget(swapandmemoryChart); } void NewResouresDialog::initNetSpeedHistory() { //set net history netWorkTitle_H_BoxLayout = new QHBoxLayout; netWorkTitle_H_BoxLayout->setContentsMargins(13,0,0,0); netWorkFlowLabel = new QLabel(tr("net work history")); netWorkTitle_H_BoxLayout->addWidget(netWorkFlowLabel); networkUnit_H_BoxLayout = new QHBoxLayout; typeCheckNetRecv = new sigCheck(this,BLUETYPE); typeCheckNetSent = new sigCheck(this,YELLOWTYPE); netrecvUnitDataLabel->setPalette(pe); netsentUnitDataLabel->setPalette(pe); QHBoxLayout *netrecvsent_H_BoxLayout = new QHBoxLayout; netrecvsent_H_BoxLayout->addStretch(1); netrecvsent_H_BoxLayout->addWidget(typeCheckNetRecv); netrecvsent_H_BoxLayout->addSpacing(8); netrecvsent_H_BoxLayout->addWidget(netrecvUnitDataLabel); netrecvsent_H_BoxLayout->addSpacing(10); netrecvsent_H_BoxLayout->addWidget(typeCheckNetSent); netrecvsent_H_BoxLayout->addSpacing(8); netrecvsent_H_BoxLayout->addWidget(netsentUnitDataLabel); networkUnit_H_BoxLayout->addLayout(netrecvsent_H_BoxLayout); networkChart_H_BoxLayout = new QHBoxLayout(); QVBoxLayout *netspeed_V_BoxLayout = new QVBoxLayout(); netspeed_V_BoxLayout->setMargin(0); networkWidget = new QWidget(); networkWidget->setFixedWidth(55); theFifthSpeedLabel = new QLabel(); theFifthSpeedLabel->setPalette(pe); netspeed_V_BoxLayout->addWidget(theFifthSpeedLabel,1,Qt::AlignRight); theFourthSpeedLabel = new QLabel(); theFourthSpeedLabel->setPalette(pe); netspeed_V_BoxLayout->addWidget(theFourthSpeedLabel,1,Qt::AlignRight); theThirdSpeedLabel = new QLabel(); theThirdSpeedLabel->setPalette(pe); netspeed_V_BoxLayout->addWidget(theThirdSpeedLabel,1,Qt::AlignRight); theSecondSpeedLabel = new QLabel(); theSecondSpeedLabel->setPalette(pe); netspeed_V_BoxLayout->addWidget(theSecondSpeedLabel,1,Qt::AlignRight); theFirtSpeedLabel = new QLabel(); theFirtSpeedLabel->setPalette(pe); netspeed_V_BoxLayout->addWidget(theFirtSpeedLabel,1,Qt::AlignRight); networkWidget->setLayout(netspeed_V_BoxLayout); networkChart = new NetWorkChart(); networkChart_H_BoxLayout->addWidget(networkWidget); networkChart_H_BoxLayout->addSpacing(10); networkChart_H_BoxLayout->addWidget(networkChart); } void NewResouresDialog::tosetFontSize() { QFont fontTitle; fontTitle.setPointSize(fontSize*1.5); cpuHistoryLabel->setFont(fontTitle); memoryAndSwapLabel->setFont(fontTitle); netWorkFlowLabel->setFont(fontTitle); QFont fontContext; fontContext.setPointSize(fontSize); cpuUnitDataLabel->setFont(fontContext); swapUnitDataLabel->setFont(fontContext); memoryUnitDataLabel->setFont(fontContext); netrecvUnitDataLabel->setFont(fontContext); netsentUnitDataLabel->setFont(fontContext); } void NewResouresDialog::initFontSize() { connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toInt(); } tosetFontSize(); }); fontSize = fontSettings->get(FONT_SIZE).toInt(); } void NewResouresDialog::updateResourceStatus() { //cpu data get signal m_prevCpuWorkTime = m_cpuworkTime; m_prevCpuTotalTime = m_cpuTotalTime; m_cpuTotalTime = getCpuTimeData(m_cpuworkTime); if (m_prevCpuWorkTime != 0 && m_prevCpuTotalTime != 0) { emit updateCpuStatus((m_cpuworkTime - m_prevCpuWorkTime) * 100.0 / (m_cpuTotalTime - m_prevCpuTotalTime)); } else { emit updateCpuStatus(0); } //swap and memory data get signal emit updateMemoryAndSwapStatus(); //net work data get signal getNetworkBytesData(m_totalRecvBytes, m_totalSentBytes, m_rateRecvBytes, m_rateSentBytes); emit this->updateNetworkStatus(m_totalRecvBytes, m_totalSentBytes, m_rateRecvBytes, m_rateSentBytes); } ukui-system-monitor/src/newresource/cpuhistorychart.cpp0000644000175000017500000001250713764351015022563 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "cpuhistorychart.h" #include "../shell/macro.h" #include "smoothlinegenerator.h" CpuHistoryChart::CpuHistoryChart(QWidget *parent):QWidget(parent) ,m_outsideBorderColor("transparent") ,m_cpuHistoryColor(QColor("#F64F61")) { this->setMinimumSize(680,90); this->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Expanding); m_pointsCount = int((this->width()) /10); m_cpuMaxHeight = 50; m_CpuHistoryList = new QList(); } CpuHistoryChart::~CpuHistoryChart() { if(m_CpuHistoryList) { delete m_CpuHistoryList; } } void CpuHistoryChart::paintEvent(QPaintEvent *event) { ///*****************************原来的折线图绘制法********************************** m_pointsCount = rect().width() / POINTSPACE; QPainter painter(this); painter.save(); //background of rect painter.setOpacity(0.08); QPainterPath framePath; QStyleOption opt; opt.init(this); m_bgColor = (QColor("#131414")); framePath.addRoundedRect(rect(), 4, 4); painter.fillPath(framePath, this->m_bgColor);//painter.drawPath(framePath); painter.restore(); //draw separate lines painter.save(); painter.setOpacity(0.5); int distance = this->rect().height()/4; painter.setPen(this->palette().color(QPalette::Base)); painter.setBrush(Qt::NoBrush); painter.drawLine(rect().x(), rect().y() + distance, rect().right(), rect().y() + distance); painter.drawLine(rect().x(), rect().y() + distance * 2, rect().right(), rect().y() + distance * 2); painter.drawLine(rect().x(), rect().y() + distance * 3, rect().right(), rect().y() + distance * 3); painter.restore(); //draw Cpu history line painter.save(); painter.translate(rect().right(),rect().bottom()); painter.scale(-1, -1);//将横坐标扩大1倍,将纵坐标缩小1倍 // painter.translate((rect().width() - m_pointsCount * POINTSPACE - 2) / 2 + 6, 89);//将坐标的原点移动到该点 QPen pen(this->m_cpuHistoryColor,2); painter.setPen(pen); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawPath(m_cpuHistoryPath);//绘制前面创建的path:m_downloadPath painter.restore(); update(); QWidget::paintEvent(event); // **********************************现在的折线图写法********************************/ /* QPainter painter(this); painter.setOpacity(0.08); QPainterPath framePath; QStyleOption opt; opt.init(this); m_bgColor = (QColor("#131414")); framePath.addRoundedRect(QRectF(this->rect().x(), this->rect().y(), this->rect().width(), this->rect().height()),4,4); painter.fillPath(framePath, this->m_bgColor);//painter.drawPath(framePath); QPainter p(this); p.save(); p.setRenderHint(QPainter::Antialiasing, true); //设置折线反锯齿 p.scale(1,1); QColor colorCpuHistory = QColor("#F64F61"); QPen pen(colorCpuHistory,1); pen.setWidth(2); p.setPen(pen); for(int j = 2; j cpuHistoryPoints; m_CpuHistoryList->append(cpu); while (m_CpuHistoryList->size() > m_pointsCount) { m_CpuHistoryList->pop_front(); } //计算出Cpu历史占用率的最大的值 double cpuHistoryMaxHeight = 0.0; for (int i = 0; i < m_CpuHistoryList->size(); i++) { if (m_CpuHistoryList->at(i) > cpuHistoryMaxHeight) { cpuHistoryMaxHeight = m_CpuHistoryList->at(i); } } for (int i = 0; i < m_CpuHistoryList->size(); i++) { // qDebug()<<"m_CpuHistoryList.size"<size(); if (cpuHistoryMaxHeight < m_cpuMaxHeight) { cpuHistoryPoints.append(QPointF((m_CpuHistoryList->size() - i -2) * POINTSPACE, m_CpuHistoryList->at(i))); } else { cpuHistoryPoints.append(QPointF((m_CpuHistoryList->size() - i -2) * POINTSPACE, m_CpuHistoryList->at(i) * m_cpuMaxHeight /cpuHistoryMaxHeight)); } } m_cpuHistoryPath = SmoothLineGenerator::generateSmoothCurve(cpuHistoryPoints); // update(); // int x = int(m_pointsCount *i * 0.1 + 0.5); // showValue = int(cpu) + 0.5; // xList<< x; // yDrawList << showValue; // update(); // i++; } void CpuHistoryChart::onUpdateCpuPercent(double value) { this->refreshCpuHistoryData(value); //about the cpurateForm showing } ukui-system-monitor/src/filesystemworker.cpp0000644000175000017500000002356413755732612020420 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemworker.h" #include "util.h" #include #include #include /*For PRIu64*/ #include //extern "C" { //#include //} typedef struct _DISK_INFO { char devname[256]; char mountdir[256]; char type[256]; gint percentage; guint64 btotal; guint64 bfree; guint64 bavail; guint64 bused; gint valid; } DISK_INFO; static void fsusage_stats(const glibtop_fsusage *buf, guint64 *bused, guint64 *bfree, guint64 *bavail, guint64 *btotal, gint *percentage) { guint64 total = buf->blocks * buf->block_size; if (!total) { /* not a real device */ *btotal = *bfree = *bavail = *bused = 0ULL; *percentage = 0; } else { int percent; *btotal = total; *bfree = buf->bfree * buf->block_size; *bavail = buf->bavail * buf->block_size; *bused = *btotal - *bfree; /* percent = 100.0f * *bused / *btotal; */ percent = 100 * *bused / (*bused + *bavail); *percentage = CLAMP(percent, 0, 100); } } DISK_INFO add_disk(const glibtop_mountentry *entry, gboolean show_all_fs) { DISK_INFO disk; memset(&disk, 0, sizeof(disk)); disk.valid = 0; glibtop_fsusage usage; guint64 bused, bfree, bavail, btotal; gint percentage; glibtop_get_fsusage(&usage, entry->mountdir); if (usage.blocks == 0) { return disk; } if(strcmp(entry->devname,"none")==0 || strcmp(entry->devname,"tmpfs")==0){ return disk; } if(strstr(entry->type, "tmpfs")) { return disk; } fsusage_stats(&usage, &bused, &bfree, &bavail, &btotal, &percentage); memcpy(disk.devname, entry->devname, strlen(entry->devname)); memcpy(disk.mountdir, entry->mountdir, strlen(entry->mountdir)); memcpy(disk.type, entry->type, strlen(entry->type)); disk.percentage = percentage; disk.btotal = btotal; disk.bfree = bfree; disk.bavail = bavail; disk.bused = bused; disk.valid = 1; // qDebug() << disk.devname<<"how i can get it ";//设备 // qDebug() << disk.mountdir;//目录 // qDebug() << disk.type;//类型 // qDebug() << disk.percentage; // qDebug() << g_format_size_full(disk.btotal, G_FORMAT_SIZE_DEFAULT);//总数 // qDebug() << g_format_size_full(disk.bavail, G_FORMAT_SIZE_DEFAULT);//可用 // qDebug() << g_format_size_full(disk.bused, G_FORMAT_SIZE_DEFAULT);//已用 return disk; } //void hello(gpointer data) //{ // g_print ("Hello World\n"); //} FileSystemWorker::FileSystemWorker(QObject *parent) : QObject(parent) { // GVolumeMonitor * monitor;//GVolumeMonitor不是 thread-default-context aware,因此不能在除了主线程中的其他地方使用???? // monitor = g_volume_monitor_get(); // g_signal_connect(monitor, "mount-added", G_CALLBACK(hello), NULL); // GVolumeMonitor* monitor = g_volume_monitor_get(); // GList* mountDeviceList = g_volume_monitor_get_mounts(monitor); // GList* it = NULL; // for(it = mountDeviceList; it; it = it->next) { // qDebug() << "mount device list:" << it->data; // } // GList* mountVolumeList = g_volume_monitor_get_volumes(monitor); // for(it = mountVolumeList; it; it = it->next) { // qDebug() << "mount volume list:" << it->data; // } } FileSystemWorker::~FileSystemWorker() { m_diskInfoList.clear(); } void FileSystemWorker::onFileSystemListChanged() { QStringList newDiskList; glibtop_mountentry *entries; glibtop_mountlist mountlist; guint i; gboolean show_all_fs = TRUE; entries = glibtop_get_mountlist(&mountlist, show_all_fs); for (i = 0; i < mountlist.number; i++) { DISK_INFO disk = add_disk(&entries[i], show_all_fs); if (disk.valid == 1) { std::string formatted_dev = make_string(g_strdup(disk.devname)); QString dev_name = QString::fromStdString(formatted_dev); //QString dev_name = QString(QLatin1String(disk.devname)); newDiskList.append(dev_name); if (!this->isDeviceContains(dev_name)) { FileSystemData *info = new FileSystemData(this); info->setDevName(dev_name); std::string formatted_mountdir(make_string(g_strdup(disk.mountdir))); std::string formatted_type(make_string(g_strdup(disk.type))); char *totalSize = g_format_size_full(disk.btotal, G_FORMAT_SIZE_DEFAULT); char *freeSize = g_format_size_full(disk.bfree, G_FORMAT_SIZE_DEFAULT); char *availSize = g_format_size_full(disk.bavail, G_FORMAT_SIZE_DEFAULT); char *usedSize = g_format_size_full(disk.bused, G_FORMAT_SIZE_DEFAULT); std::string formatted_btotal(make_string(g_strdup(totalSize))); std::string formatted_bfree(make_string(g_strdup(freeSize))); std::string formatted_bavail(make_string(g_strdup(availSize))); std::string formatted_bused(make_string(g_strdup(usedSize))); info->updateDiskInfo(QString::fromStdString(formatted_mountdir), QString::fromStdString(formatted_type), QString::fromStdString(formatted_btotal), QString::fromStdString(formatted_bfree), QString::fromStdString(formatted_bavail), QString::fromStdString(formatted_bused), disk.percentage/*QString::number(disk.percentage).append("%")*/); // info->updateDiskInfo(QString(QLatin1String(disk.mountdir)), QString(QLatin1String(disk.type)), QString(QLatin1String(g_format_size_full(disk.btotal, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bfree, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bavail, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bused, G_FORMAT_SIZE_DEFAULT))), disk.percentage/*QString::number(disk.percentage).append("%")*/); this->addDiskInfo(dev_name, info); g_free(totalSize); g_free(freeSize); g_free(availSize); g_free(usedSize); } else {//update info which had exists FileSystemData *info = this->getDiskInfo(dev_name); if (info) { char *totalSize = g_format_size_full(disk.btotal, G_FORMAT_SIZE_DEFAULT); char *freeSize = g_format_size_full(disk.bfree, G_FORMAT_SIZE_DEFAULT); char *availSize = g_format_size_full(disk.bavail, G_FORMAT_SIZE_DEFAULT); char *usedSize = g_format_size_full(disk.bused, G_FORMAT_SIZE_DEFAULT); std::string formatted_mountdir(make_string(g_strdup(disk.mountdir))); std::string formatted_type(make_string(g_strdup(disk.type))); std::string formatted_btotal(make_string(g_strdup(totalSize))); std::string formatted_bfree(make_string(g_strdup(freeSize))); std::string formatted_bavail(make_string(g_strdup(availSize))); std::string formatted_bused(make_string(g_strdup(usedSize))); info->updateDiskInfo(QString::fromStdString(formatted_mountdir), QString::fromStdString(formatted_type), QString::fromStdString(formatted_btotal), QString::fromStdString(formatted_bfree), QString::fromStdString(formatted_bavail), QString::fromStdString(formatted_bused), disk.percentage/*QString::number(disk.percentage).append("%")*/); g_free(totalSize); g_free(freeSize); g_free(availSize); g_free(usedSize); // info->updateDiskInfo(QString(QLatin1String(disk.mountdir)), QString(QLatin1String(disk.type)), QString(QLatin1String(g_format_size_full(disk.btotal, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bfree, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bavail, G_FORMAT_SIZE_DEFAULT))), QString(QLatin1String(g_format_size_full(disk.bused, G_FORMAT_SIZE_DEFAULT))), disk.percentage/*QString::number(disk.percentage).append("%")*/); } } } } //remove the device whice not exists anymore for (auto device : m_diskInfoList.keys()) { bool foundDevice = false; for (auto devName : newDiskList) { if (devName == device) { foundDevice = true; break; } } if (!foundDevice) { m_diskInfoList.remove(device);//or erase??? } } g_free(entries); } FileSystemData *FileSystemWorker::getDiskInfo(const QString &devname) { return m_diskInfoList.value(devname, nullptr); } QList FileSystemWorker::diskInfoList() const { return m_diskInfoList.values(); } void FileSystemWorker::addDiskInfo(const QString &devname, FileSystemData *info) { if (!m_diskInfoList.contains(devname)) { m_diskInfoList[devname] = info; } } void FileSystemWorker::removeDiskItem(const QString &devname) { // FileSystemData *info = getDiskInfo(devname); // m_diskInfoList.remove(devname); } bool FileSystemWorker::isDeviceContains(const QString &devname) { return m_diskInfoList.keys().contains(devname); } ukui-system-monitor/src/filesystemdata.cpp0000644000175000017500000000445413746753504020020 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemdata.h" #include FileSystemData::FileSystemData(QObject *parent) : QObject(parent) { } const QString FileSystemData::deviceName() const { return m_devName; } void FileSystemData::setDevName(const QString &name) { if (name != m_devName) m_devName = name; } const QString FileSystemData::mountDir() const { return m_mountDir; } const QString FileSystemData::diskType() const { return m_diskType; } const QString FileSystemData::totalCapacity() const { return m_totalCapacity; } const QString FileSystemData::freeCapacity() const { return m_freeCapacity; } const QString FileSystemData::availCapacity() const { return m_availCapacity; } const QString FileSystemData::usedCapactiy() const { return m_usedCapactiy; } const int FileSystemData::usedPercentage() { return m_percentage; } void FileSystemData::updateDiskInfo(QString mountDir, QString diskType, QString totalCapacity, QString freeCapacity, QString availCapacity, QString usedCapactiy, int percentage) { if (mountDir != m_mountDir) m_mountDir = mountDir; if (diskType != m_diskType) m_diskType = diskType; if (totalCapacity != m_totalCapacity) m_totalCapacity = totalCapacity; if (freeCapacity != m_freeCapacity) m_freeCapacity = freeCapacity; if (availCapacity != m_availCapacity) m_availCapacity = availCapacity; if (usedCapactiy != m_usedCapactiy) m_usedCapactiy = usedCapactiy; if (percentage != m_percentage) m_percentage = percentage; } ukui-system-monitor/src/singleProcessNet/0000755000175000017500000000000013764070001017536 5ustar fengfengukui-system-monitor/src/singleProcessNet/devices.h0000644000175000017500000000224413746753570021356 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __DEVICES_H #define __DEVICES_H #include // NULL class device { public: device (const char * m_name, device * m_next = NULL) { name = m_name; next = m_next; } const char * name; device * next; }; /** * This function can return null, if no good interface is found * The function avoids loopback interface and down/not running interfaces */ device * get_default_devices(); #endif ukui-system-monitor/src/singleProcessNet/process.cpp0000644000175000017500000001421313746753570021744 0ustar fengfeng/* * process.cpp * * Copyright (c) 2004,2005,2008,2011 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include "process.h" #include "kylinsystemnethogs.h" #include "inode2prog.h" #include "conninode.h" extern local_addr * local_addrs; /* * connection-inode table. takes information from /proc/net/tcp. * key contains source ip, source port, destination ip, destination * port in format: '1.2.3.4:5-1.2.3.4:5' */ extern std::map conninode; /* this file includes: * - calls to inodeproc to get the pid that belongs to that inode */ /* * Initialise the global process-list with some special processes: * * unknown TCP traffic * * UDP traffic * * unknown IP traffic * We must take care these never get removed from the list. */ Process * unknowntcp; Process * unknownudp; Process * unknownip; ProcList * processes; /* We're migrating to having several `unknown' processes that are added as * normal processes, instead of hard-wired unknown processes. * This mapping maps from unknown processes descriptions to processes */ std::map unknownprocs; void process_init () { unknowntcp = new Process (0, "", "unknown TCP"); processes = new ProcList (unknowntcp, NULL); } int Process::getLastPacket() { int lastpacket=0; ConnList * curconn=connections; while (curconn != NULL) { assert (curconn != NULL); assert (curconn->getVal() != NULL); if (curconn->getVal()->getLastPacket() > lastpacket) lastpacket = curconn->getVal()->getLastPacket(); curconn = curconn->getNext(); } return lastpacket; } Process * findProcess (struct prg_node * node) //final { ProcList * current = processes; while (current != NULL) { Process * currentproc = current->getVal(); assert (currentproc != NULL); if (node->pid == currentproc->pid) return current->getVal(); current = current->next; } return NULL; } /* finds process based on inode, if any */ /* should be done quickly after arrival of the packet, * otherwise findPID will be outdated */ Process * findProcess (unsigned long inode) // init { struct prg_node * node = findPID(inode); if (node == NULL) return NULL; return findProcess (node); } int ProcList::size () { int i=1; if (next != NULL) i += next->size(); return i; } void check_all_procs () { ProcList * curproc = processes; while (curproc != NULL) { curproc->getVal()->check(); curproc = curproc->getNext(); } } /* * returns the process from proclist with matching pid * if the inode is not associated with any PID, return NULL * if the process is not yet in the proclist, add it */ Process * getProcess (unsigned long inode, const char * devicename) { struct prg_node * node = findPID(inode); if (node == NULL) { if (DEBUG) std::cout << "No PID information for inode " << inode << std::endl; return NULL; } Process * proc = findProcess (node); if (proc != NULL) return proc; Process * newproc = new Process (inode, devicename, node->name.c_str()); newproc->pid = node->pid; char procdir [100]; sprintf(procdir , "/proc/%d", node->pid); struct stat stats; int retval = stat(procdir, &stats); if (retval != 0) newproc->setUid(0); else newproc->setUid(stats.st_uid); processes = new ProcList (newproc, processes); return newproc; } /* * Used when a new connection is encountered. Finds corresponding * process and adds the connection. If the connection doesn't belong * to any known process, the process list is updated and a new process * is made. If no process can be found even then, it's added to the * 'unknown' process. */ Process * getProcess (Connection * connection, const char * devicename) { unsigned long inode = conninode[connection->refpacket->gethashstring()]; if (inode == 0) { // no? refresh and check conn/inode table // refresh the inode->pid table first. Presumably processing the renewed connection->inode table // is slow, making this worthwhile. // We take the fact for granted that we might already know the inode->pid (unlikely anyway if we // haven't seen the connection->inode yet though). reread_mapping(); refreshconninode(); inode = conninode[connection->refpacket->gethashstring()]; #if REVERSEHACK if (inode == 0) { /* HACK: the following is a hack for cases where the * 'local' addresses aren't properly recognised, as is * currently the case for IPv6 */ /* we reverse the direction of the stream if * successful. */ Packet * reversepacket = connection->refpacket->newInverted(); inode = conninode[reversepacket->gethashstring()]; if (inode == 0) { delete reversepacket; if (bughuntmode || DEBUG) std::cout << "LOC: " << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n"; unknowntcp->connections = new ConnList (connection, unknowntcp->connections); return unknowntcp; } delete connection->refpacket; connection->refpacket = reversepacket; } #endif } Process * proc = NULL; if (inode != 0) proc = getProcess(inode, devicename); if (proc == NULL) { proc = new Process (inode, "", connection->refpacket->gethashstring()); processes = new ProcList (proc, processes); } proc->connections = new ConnList (connection, proc->connections); return proc; } ukui-system-monitor/src/singleProcessNet/packet.cpp0000644000175000017500000002064113746753570021537 0ustar fengfeng/* * packet.cpp * * Copyright (c) 2004-2006,2008 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "kylinsystemnethogs.h" #include #include "packet.h" #include #include #include #include #include #include #include #include #include #include local_addr * local_addrs = NULL; bool local_addr::contains (const in_addr_t & n_addr) { if ((sa_family == AF_INET) && (n_addr == addr)) return true; if (next == NULL) return false; return next->contains(n_addr); } bool local_addr::contains(const struct in6_addr & n_addr) { if (sa_family == AF_INET6) { if (memcmp (&addr6, &n_addr, sizeof(struct in6_addr)) == 0) { if (DEBUG) std::cerr << "Match!" << std::endl; return true; } } if (next == NULL) return false; return next->contains(n_addr); } /* moves the pointer right until a non-space is seen */ char * stripspaces (char * input) { char * retval = input; while (*retval == ' ') retval++; return retval; } /* * getLocal * device: This should be device explicit (e.g. eth0:1) * * uses ioctl to get address of this device, and adds it to the * local_addrs-list. */ void getLocal (const char *device) { /* get local IPv4 addresses */ int sock; struct ifreq iFreq; struct sockaddr_in *saddr; if((sock=socket(AF_INET, SOCK_DGRAM, 0))<0) { // forceExit(false, "creating socket failed while establishing local IP - are you root?"); } strcpy(iFreq.ifr_name, device); if(ioctl(sock, SIOCGIFADDR, &iFreq)<0) { // forceExit(false, "ioctl failed while establishing local IP for selected device %s. You may specify the device on the command line.", device); } saddr=(struct sockaddr_in*)&iFreq.ifr_addr; local_addrs = new local_addr (saddr->sin_addr.s_addr, local_addrs); /* also get local IPv6 addresses */ FILE * ifinfo = fopen ("/proc/net/if_inet6", "r"); char buffer [500]; if (ifinfo) { do { if (fgets(buffer, sizeof(buffer), ifinfo)) { char address [33]; char ifname [9]; int n_results = sscanf (buffer, "%32[0-9a-f] %*d %*d %*d %*d %8[0-9a-zA-Z]", address, ifname); assert (n_results = 2); if (strcmp (stripspaces(ifname), device) == 0) { local_addrs = new local_addr (address, local_addrs); } } } while (!feof(ifinfo)); fclose(ifinfo); } } typedef u_int32_t tcp_seq; /* ppp header, i hope ;) */ /* glanced from ethereal, it's 16 bytes, and the payload packet type is * in the last 2 bytes... */ struct ppp_header { u_int16_t dummy1; u_int16_t dummy2; u_int16_t dummy3; u_int16_t dummy4; u_int16_t dummy5; u_int16_t dummy6; u_int16_t dummy7; u_int16_t packettype; }; /* TCP header */ // TODO take from elsewhere. struct tcp_hdr { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #if BYTE_ORDER == LITTLE_ENDIAN u_int th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif #if BYTE_ORDER == BIG_ENDIAN u_int th_off:4, /* data offset */ th_x2:4; /* (unused) */ #endif u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; Packet::Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction m_dir) { sip = m_sip; sport = m_sport; dip = m_dip; dport = m_dport; len = m_len; time = m_time; dir = m_dir; sa_family = AF_INET; hashstring = NULL; } Packet::Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction m_dir) { sip6 = m_sip; sport = m_sport; dip6 = m_dip; dport = m_dport; len = m_len; time = m_time; dir = m_dir; sa_family = AF_INET6; hashstring = NULL; } direction invert(direction dir) { if (dir == dir_incoming) return dir_outgoing; else if (dir == dir_outgoing) return dir_incoming; else return dir_unknown; } Packet * Packet::newInverted () { direction new_direction = invert(dir); if (sa_family == AF_INET) return new Packet (dip, dport, sip, sport, len, time, new_direction); else return new Packet (dip6, dport, sip6, sport, len, time, new_direction); } /* constructs returns a new Packet() structure with the same contents as this one */ Packet::Packet (const Packet &old_packet) { sip = old_packet.sip; sport = old_packet.sport; sip6 = old_packet.sip6; dip6 = old_packet.dip6; dip = old_packet.dip; dport = old_packet.dport; len = old_packet.len; time = old_packet.time; sa_family = old_packet.sa_family; if (old_packet.hashstring == NULL) hashstring = NULL; else hashstring = strdup(old_packet.hashstring); dir = old_packet.dir; } bool sameinaddr(in_addr one, in_addr other) { return one.s_addr == other.s_addr; } bool Packet::isOlderThan (timeval t) { std::cout << "Comparing " << time.tv_sec << " <= " << t.tv_sec << std::endl; return (time.tv_sec <= t.tv_sec); } bool Packet::Outgoing () { /* must be initialised with getLocal("eth0:1");) */ assert (local_addrs != NULL); switch (dir) { case dir_outgoing: return true; case dir_incoming: return false; case dir_unknown: bool islocal; if (sa_family == AF_INET) islocal = local_addrs->contains(sip.s_addr); else islocal = local_addrs->contains(sip6); if (islocal) { dir = dir_outgoing; return true; } else { if (DEBUG) { if (sa_family == AF_INET) islocal = local_addrs->contains(dip.s_addr); else islocal = local_addrs->contains(dip6); if (!islocal) { std::cerr << "Neither dip nor sip are local: "; char addy [50]; inet_ntop (AF_INET6, &sip6, addy, 49); std::cerr << addy << std::endl; inet_ntop (AF_INET6, &dip6, addy, 49); std::cerr << addy << std::endl; return false; } } dir = dir_incoming; return false; } } return false; } /* returns the packet in '1.2.3.4:5-1.2.3.4:5'-form, for use in the 'conninode' table */ /* '1.2.3.4' should be the local address. */ /* the calling code should take care of deletion of the hash string */ char * Packet::gethashstring () { if (hashstring != NULL) { return hashstring; } hashstring = (char *) malloc (HASHKEYSIZE * sizeof(char)); char * local_string = (char *) malloc (50); char * remote_string = (char *) malloc (50); if (sa_family == AF_INET) { inet_ntop(sa_family, &sip, local_string, 49); inet_ntop(sa_family, &dip, remote_string, 49); } else { inet_ntop(sa_family, &sip6, local_string, 49); inet_ntop(sa_family, &dip6, remote_string, 49); } if (Outgoing()) { snprintf(hashstring, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, sport, remote_string, dport); } else { snprintf(hashstring, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", remote_string, dport, local_string, sport); } free (local_string); free (remote_string); //if (DEBUG) // std::cout << "Returning newly created hash string: " << hashstring << std::endl; return hashstring; } /* 2 packets match if they have the same * source and destination ports and IP's. */ bool Packet::match (Packet * other) { return (sport == other->sport) && (dport == other->dport) && (sameinaddr(sip, other->sip)) && (sameinaddr(dip, other->dip)); } bool Packet::matchSource (Packet * other) { return (sport == other->sport) && (sameinaddr(sip, other->sip)); } ukui-system-monitor/src/singleProcessNet/kylinsystemnethogs.h0000644000175000017500000000735713746753570023731 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __NETHOGS_H #define __NETHOGS_H #include #include #include #include #include #include #include #include #define _BSD_SOURCE 1 /* take the average speed over the last 5 seconds */ #define PERIOD 5 /* the amount of time after the last packet was recieved * after which a process is removed */ #define PROCESSTIMEOUT 150 /* the amount of time after the last packet was recieved * after which a connection is removed */ #define CONNTIMEOUT 50 #define DEBUG 0 #define REVERSEHACK 0 // 2 times: 32 characters, 7 ':''s, a ':12345'. // 1 '-' // -> 2*45+1=91. we make it 92, for the null. #define HASHKEYSIZE 92 #define PROGNAME_WIDTH 512 // viewMode: how to represent numbers #define VIEWMODE_KBPS 0 #define VIEWMODE_TOTAL_KB 1 #define VIEWMODE_TOTAL_B 2 #define VIEWMODE_TOTAL_MB 3 #define VIEWMODE_COUNT 4 #define NORETURN __attribute__ ((__noreturn__)) void forceExit(bool success, const char *msg, ...) NORETURN; class local_addr { public: /* ipv4 constructor takes an in_addr_t */ local_addr (in_addr_t m_addr, local_addr * m_next = NULL) { addr = m_addr; next = m_next; sa_family = AF_INET; string = (char*) malloc (16); inet_ntop (AF_INET, &m_addr, string, 15); } /* this constructor takes an char address[33] */ local_addr (char m_address [33], local_addr * m_next = NULL) { next = m_next; char address [40]; address[0] = m_address[0]; address[1] = m_address[1]; address[2] = m_address[2]; address[3] = m_address[3]; address[4] = ':'; address[5] = m_address[4]; address[6] = m_address[5]; address[7] = m_address[6]; address[8] = m_address[7]; address[9] = ':'; address[10] = m_address[8]; address[11] = m_address[9]; address[12] = m_address[10]; address[13] = m_address[11]; address[14] = ':'; address[15] = m_address[12]; address[16] = m_address[13]; address[17] = m_address[14]; address[18] = m_address[15]; address[19] = ':'; address[20] = m_address[16]; address[21] = m_address[17]; address[22] = m_address[18]; address[23] = m_address[19]; address[24] = ':'; address[25] = m_address[20]; address[26] = m_address[21]; address[27] = m_address[22]; address[28] = m_address[23]; address[29] = ':'; address[30] = m_address[24]; address[31] = m_address[25]; address[32] = m_address[26]; address[33] = m_address[27]; address[34] = ':'; address[35] = m_address[28]; address[36] = m_address[29]; address[37] = m_address[30]; address[38] = m_address[31]; address[39] = 0; string = strdup(address); //if (DEBUG) // std::cout << "Converting address " << address << std::endl; int result = inet_pton (AF_INET6, address, &addr6); assert (result > 0); sa_family = AF_INET6; } bool contains (const in_addr_t & n_addr); bool contains (const struct in6_addr & n_addr); char * string; local_addr * next; private: in_addr_t addr; struct in6_addr addr6; short int sa_family; }; void quit_cb (int i); const char* getVersion(); #endif ukui-system-monitor/src/singleProcessNet/conninode.cpp0000644000175000017500000001353613746753570022251 0ustar fengfeng/* * conninode.cpp * * Copyright (c) 2008,2009 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include "kylinsystemnethogs.h" #include "conninode.h" extern local_addr * local_addrs; /* * connection-inode table. takes information from /proc/net/tcp. * key contains source ip, source port, destination ip, destination * port in format: '1.2.3.4:5-1.2.3.4:5' */ std::map conninode; /* * parses a /proc/net/tcp-line of the form: * sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode * 10: 020310AC:1770 9DD8A9C3:A525 01 00000000:00000000 00:00000000 00000000 0 0 2119 1 c0f4f0c0 206 40 10 3 -1 * 11: 020310AC:0404 936B2ECF:0747 01 00000000:00000000 00:00000000 00000000 1000 0 2109 1 c0f4fc00 368 40 20 2 -1 * * and of the form: * 2: 0000000000000000FFFF0000020310AC:0016 0000000000000000FFFF00009DD8A9C3:A526 01 00000000:00000000 02:000A7214 00000000 0 0 2525 2 c732eca0 201 40 1 2 -1 * */ void addtoconninode (char * buffer) { short int sa_family; struct in6_addr result_addr_local; struct in6_addr result_addr_remote; char rem_addr[128], local_addr[128]; int local_port, rem_port; struct in6_addr in6_local; struct in6_addr in6_remote; // this leaked memory //unsigned long * inode = (unsigned long *) malloc (sizeof(unsigned long)); unsigned long inode; int matches = sscanf(buffer, "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n", local_addr, &local_port, rem_addr, &rem_port, &inode); if (matches != 5) { fprintf(stderr,"Unexpected buffer: '%s'\n",buffer); exit(0); } if (inode == 0) { /* connection is in TIME_WAIT state. We rely on * the old data still in the table. */ return; } if (strlen(local_addr) > 8) { /* this is an IPv6-style row */ /* Demangle what the kernel gives us */ sscanf(local_addr, "%08X%08X%08X%08X", &in6_local.s6_addr32[0], &in6_local.s6_addr32[1], &in6_local.s6_addr32[2], &in6_local.s6_addr32[3]); sscanf(rem_addr, "%08X%08X%08X%08X", &in6_remote.s6_addr32[0], &in6_remote.s6_addr32[1], &in6_remote.s6_addr32[2], &in6_remote.s6_addr32[3]); if ((in6_local.s6_addr32[0] == 0x0) && (in6_local.s6_addr32[1] == 0x0) && (in6_local.s6_addr32[2] == 0xFFFF0000)) { /* IPv4-compatible address */ result_addr_local = *((struct in6_addr*) &(in6_local.s6_addr32[3])); result_addr_remote = *((struct in6_addr*) &(in6_remote.s6_addr32[3])); sa_family = AF_INET; } else { /* real IPv6 address */ //inet_ntop(AF_INET6, &in6_local, addr6, sizeof(addr6)); //INET6_getsock(addr6, (struct sockaddr *) &localaddr); //inet_ntop(AF_INET6, &in6_remote, addr6, sizeof(addr6)); //INET6_getsock(addr6, (struct sockaddr *) &remaddr); //localaddr.sin6_family = AF_INET6; //remaddr.sin6_family = AF_INET6; result_addr_local = in6_local; result_addr_remote = in6_remote; sa_family = AF_INET6; } } else { /* this is an IPv4-style row */ sscanf(local_addr, "%X", (unsigned int *) &result_addr_local); sscanf(rem_addr, "%X", (unsigned int *) &result_addr_remote); sa_family = AF_INET; } char * hashkey = (char *) malloc (HASHKEYSIZE * sizeof(char)); char * local_string = (char*) malloc (50); char * remote_string = (char*) malloc (50); inet_ntop(sa_family, &result_addr_local, local_string, 49); inet_ntop(sa_family, &result_addr_remote, remote_string, 49); snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", local_string, local_port, remote_string, rem_port); free (local_string); //if (DEBUG) // fprintf (stderr, "Hashkey: %s\n", hashkey); //std::cout << "Adding to conninode\n" << std::endl; conninode[hashkey] = inode; /* workaround: sometimes, when a connection is actually from 172.16.3.1 to * 172.16.3.3, packages arrive from 195.169.216.157 to 172.16.3.3, where * 172.16.3.1 and 195.169.216.157 are the local addresses of different * interfaces */ struct local_addr * current_local_addr = local_addrs; while (current_local_addr != NULL) { /* TODO maybe only add the ones with the same sa_family */ snprintf(hashkey, HASHKEYSIZE * sizeof(char), "%s:%d-%s:%d", current_local_addr->string, local_port, remote_string, rem_port); conninode[hashkey] = inode; current_local_addr = current_local_addr->next; } free (hashkey); free (remote_string); } /* opens /proc/net/tcp[6] and adds its contents line by line */ int addprocinfo (const char * filename) { FILE * procinfo = fopen (filename, "r"); char buffer[8192]; if (procinfo == NULL) return 0; fgets(buffer, sizeof(buffer), procinfo); do { if (fgets(buffer, sizeof(buffer), procinfo)) addtoconninode(buffer); } while (!feof(procinfo)); fclose(procinfo); return 1; } void refreshconninode () { /* we don't forget old mappings, just overwrite */ //delete conninode; //conninode = new HashTable (256); if (! addprocinfo ("/proc/net/tcp")) { std::cout << "Error: couldn't open /proc/net/tcp\n"; exit(0); } addprocinfo ("/proc/net/tcp6"); //if (DEBUG) // reviewUnknown(); } ukui-system-monitor/src/singleProcessNet/connection.cpp0000644000175000017500000001251713746753570022432 0ustar fengfeng/* * connection.cpp * * Copyright (c) 2004-2006,2008 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include "kylinsystemnethogs.h" #include "connection.h" #include "process.h" ConnList * connections = NULL; void PackList::add (Packet * p) { if (content == NULL) { content = new PackListNode (new Packet (*p)); return; } if (content->val->time.tv_sec == p->time.tv_sec) { content->val->len += p->len; return; } /* store copy of packet, so that original may be freed */ content = new PackListNode(new Packet (*p), content); } /* sums up the total bytes used and removes 'old' packets */ u_int32_t PackList::sumanddel (timeval t) { u_int32_t retval = 0; PackListNode * current = content; PackListNode * previous = NULL; while (current != NULL) { //std::cout << "Comparing " << current->val->time.tv_sec << " <= " << t.tv_sec - PERIOD << endl; if (current->val->time.tv_sec <= t.tv_sec - PERIOD) { if (current == content) content = NULL; else if (previous != NULL) previous->next = NULL; delete current; return retval; } retval += current->val->len; previous = current; current = current->next; } return retval; } /* packet may be deleted by caller */ Connection::Connection (Packet * packet) { assert (packet != NULL); connections = new ConnList (this, connections); sent_packets = new PackList (); recv_packets = new PackList (); sumSent = 0; sumRecv = 0; if (DEBUG) { std::cout << "New connection, with package len " << packet->len << std::endl; } if (packet->Outgoing()) { sumSent += packet->len; sent_packets->add(packet); refpacket = new Packet (*packet); } else { sumRecv += packet->len; recv_packets->add(packet); refpacket = packet->newInverted(); } lastpacket = packet->time.tv_sec; if (DEBUG) std::cout << "New reference packet created at " << refpacket << std::endl; } Connection::~Connection () { if (DEBUG) std::cout << "Deleting connection" << std::endl; /* refpacket is not a pointer to one of the packets in the lists * so deleted */ delete (refpacket); if (sent_packets != NULL) delete sent_packets; if (recv_packets != NULL) delete recv_packets; ConnList * curr_conn = connections; ConnList * prev_conn = NULL; while (curr_conn != NULL) { if (curr_conn->getVal() == this) { ConnList * todelete = curr_conn; curr_conn = curr_conn->getNext(); if (prev_conn == NULL) { connections = curr_conn; } else { prev_conn->setNext(curr_conn); } delete (todelete); } else { prev_conn = curr_conn; curr_conn = curr_conn->getNext(); } } } /* the packet will be freed by the calling code */ void Connection::add (Packet * packet) { lastpacket = packet->time.tv_sec; if (packet->Outgoing()) { if (DEBUG) { std::cout << "Outgoing: " << packet->len << std::endl; } sumSent += packet->len; sent_packets->add (packet); } else { if (DEBUG) { std::cout << "Incoming: " << packet->len << std::endl; } sumRecv += packet->len; if (DEBUG) { std::cout << "sumRecv now: " << sumRecv << std::endl; } recv_packets->add (packet); } } Connection * findConnectionWithMatchingSource(Packet * packet) { assert(packet->Outgoing()); ConnList * current = connections; while (current != NULL) { /* the reference packet is always outgoing */ if (packet->matchSource(current->getVal()->refpacket)) { return current->getVal(); } current = current->getNext(); } return NULL; } Connection * findConnectionWithMatchingRefpacketOrSource(Packet * packet) { ConnList * current = connections; while (current != NULL) { /* the reference packet is always *outgoing* */ if (packet->match(current->getVal()->refpacket)) { return current->getVal(); } current = current->getNext(); } return findConnectionWithMatchingSource(packet); } /* * finds connection to which this packet belongs. * a packet belongs to a connection if it matches * to its reference packet */ Connection * findConnection (Packet * packet) { if (packet->Outgoing()) return findConnectionWithMatchingRefpacketOrSource(packet); else { Packet * invertedPacket = packet->newInverted(); Connection * result = findConnectionWithMatchingRefpacketOrSource(invertedPacket); delete invertedPacket; return result; } } /* * Connection::sumanddel * * sums up the total bytes used * and removes 'old' packets. * * Returns sum of sent packages (by address) * sum of recieved packages (by address) */ void Connection::sumanddel (timeval t, u_int32_t * recv, u_int32_t * sent) { (*sent)=(*recv)=0; *sent = sent_packets->sumanddel(t); *recv = recv_packets->sumanddel(t); } ukui-system-monitor/src/singleProcessNet/packet.h0000644000175000017500000000426713746753570021212 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __PACKET_H #define __PACKET_H #define _BSD_SOURCE 1 #include #include #include #include #include "kylinsystemnethogs.h" enum direction { dir_unknown, dir_incoming, dir_outgoing }; /* To initialise this module, call getLocal with the currently * monitored device (e.g. "eth0:1") */ void getLocal (const char *device); class Packet { public: in6_addr sip6; in6_addr dip6; in_addr sip; in_addr dip; unsigned short sport; unsigned short dport; u_int32_t len; timeval time; Packet (in_addr m_sip, unsigned short m_sport, in_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction dir = dir_unknown); Packet (in6_addr m_sip, unsigned short m_sport, in6_addr m_dip, unsigned short m_dport, u_int32_t m_len, timeval m_time, direction dir = dir_unknown); /* copy constructor */ Packet (const Packet &old); ~Packet () { if (hashstring != NULL) { free (hashstring); hashstring = NULL; } } /* Packet (const Packet &old_packet); */ /* copy constructor that turns the packet around */ Packet * newInverted (); bool isOlderThan(timeval t); /* is this packet coming from the local host? */ bool Outgoing (); bool match (Packet * other); bool matchSource (Packet * other); /* returns '1.2.3.4:5-1.2.3.4:6'-style string */ char * gethashstring(); private: direction dir; short int sa_family; char * hashstring; }; #endif ukui-system-monitor/src/singleProcessNet/decpcap.c0000644000175000017500000002077113746753570021333 0ustar fengfeng/* * decpcap.c * * Copyright (c) 2004-2006,2011 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include // for memcpy #include #include "decpcap.h" #define DP_DEBUG 0 /* functions to set up a handle (which is basically just a pcap handle) */ struct dp_handle * dp_fillhandle(pcap_t * phandle) { struct dp_handle * retval = (struct dp_handle *) malloc (sizeof (struct dp_handle)); int i; retval->pcap_handle = phandle; for (i = 0; i < dp_n_packet_types; i++) { retval->callback[i] = NULL; } retval->linktype = pcap_datalink(retval->pcap_handle); switch (retval->linktype) { case (DLT_EN10MB): fprintf(stdout, "Ethernet link detected\n"); break; case (DLT_PPP): fprintf(stdout, "PPP link detected\n"); break; case (DLT_LINUX_SLL): fprintf(stdout, "Linux Cooked Socket link detected\n"); break; default: fprintf(stdout, "No PPP or Ethernet link: %d\n", retval->linktype); // TODO maybe error? or 'other' callback? break; } return retval; } struct dp_handle * dp_open_offline(char * fname, char * ebuf) { pcap_t * temp = pcap_open_offline(fname, ebuf); if (temp == NULL) { return NULL; } return dp_fillhandle(temp); } struct dp_handle * dp_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf) { pcap_t * temp = pcap_open_live(device, snaplen, promisc, to_ms, errbuf); if (temp == NULL) { return NULL; } return dp_fillhandle(temp); } /* functions to add callbacks */ void dp_addcb (struct dp_handle * handle, enum dp_packet_type type, dp_callback callback) { handle->callback[type] = callback; } /* functions for parsing the payloads */ void dp_parse_tcp (struct dp_handle * handle, const dp_header * header, const u_char * packet) { //const struct tcphdr * tcp = (struct tcphdr *) packet; //u_char * payload = (u_char *) packet + sizeof (struct tcphdr); if (handle->callback[dp_packet_tcp] != NULL) { int done = (handle->callback[dp_packet_tcp]) (handle->userdata, header, packet); if (done) return; } // TODO: maybe `pass on' payload to lower-level protocol parsing } void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct ip * ip = (struct ip *) packet; if (DP_DEBUG) { fprintf(stdout, "Looking at packet with length %ud\n", header->len); } u_char * payload = (u_char *) packet + sizeof (struct ip); if (handle->callback[dp_packet_ip] != NULL) { int done = (handle->callback[dp_packet_ip]) (handle->userdata, header, packet); if (done) return; } switch (ip->ip_p) { case IPPROTO_TCP: dp_parse_tcp (handle, header, payload); break; default: // TODO: maybe support for non-tcp IP packets break; } } void dp_parse_ip6 (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct ip6_hdr * ip6 = (struct ip6_hdr *) packet; u_char * payload = (u_char *) packet + sizeof (struct ip6_hdr); if (handle->callback[dp_packet_ip6] != NULL) { int done = (handle->callback[dp_packet_ip6]) (handle->userdata, header, packet); if (done) return; } switch ((ip6->ip6_ctlun).ip6_un1.ip6_un1_nxt) { case IPPROTO_TCP: dp_parse_tcp (handle, header, payload); break; default: // TODO: maybe support for non-tcp ipv6 packets break; } } void dp_parse_ethernet (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct ether_header * ethernet = (struct ether_header *)packet; u_char * payload = (u_char *) packet + sizeof (struct ether_header); u_int16_t protocol = 0; /* call handle if it exists */ if (handle->callback[dp_packet_ethernet] != NULL) { int done = (handle->callback[dp_packet_ethernet]) (handle->userdata, header, packet); /* return if handle decides we're done */ if (done) return; } /* parse payload */ protocol = ntohs(ethernet->ether_type); switch (protocol) { case ETHERTYPE_IP: dp_parse_ip (handle, header, payload); break; case ETHERTYPE_IPV6: dp_parse_ip6 (handle, header, payload); break; default: // TODO: maybe support for other protocols apart from IPv4 and IPv6 break; } } /* ppp header, i hope ;) */ /* glanced from ethereal, it's 16 bytes, and the payload packet type is * in the last 2 bytes... */ struct ppp_header { u_int16_t dummy1; u_int16_t dummy2; u_int16_t dummy3; u_int16_t dummy4; u_int16_t dummy5; u_int16_t dummy6; u_int16_t dummy7; u_int16_t packettype; }; void dp_parse_ppp (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct ppp_header * ppp = (struct ppp_header *) packet; u_char * payload = (u_char *) packet + sizeof (struct ppp_header); u_int16_t protocol = 0; /* call handle if it exists */ if (handle->callback[dp_packet_ppp] != NULL) { int done = (handle->callback[dp_packet_ppp]) (handle->userdata, header, packet); /* return if handle decides we're done */ if (done) return; } /* parse payload */ protocol = ntohs(ppp->packettype); switch (protocol) { case ETHERTYPE_IP: dp_parse_ip (handle, header, payload); break; case ETHERTYPE_IPV6: dp_parse_ip6 (handle, header, payload); break; default: // TODO: support for other than IPv4 and IPv6 break; } } /* linux cooked header, i hope ;) */ /* glanced from libpcap/ssl.h */ #define SLL_ADDRLEN 8 /* length of address field */ struct sll_header { u_int16_t sll_pkttype; /* packet type */ u_int16_t sll_hatype; /* link-layer address type */ u_int16_t sll_halen; /* link-layer address length */ u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ u_int16_t sll_protocol; /* protocol */ }; void dp_parse_linux_cooked (struct dp_handle * handle, const dp_header * header, const u_char * packet) { const struct sll_header * sll = (struct sll_header *) packet; u_char * payload = (u_char *) packet + sizeof (struct sll_header); u_int16_t protocol = 0; /* call handle if it exists */ if (handle->callback[dp_packet_sll] != NULL) { int done = (handle->callback[dp_packet_sll]) (handle->userdata, header, packet); /* return if handle decides we're done */ if (done) return; } /* parse payload */ protocol = ntohs(sll->sll_protocol); switch (protocol) { case ETHERTYPE_IP: dp_parse_ip (handle, header, payload); break; case ETHERTYPE_IPV6: dp_parse_ip6 (handle, header, payload); break; default: // TODO: support for other than IPv4 / IPv6 break; } } /* functions to do the monitoring */ void dp_pcap_callback (u_char * u_handle, const struct pcap_pkthdr * header, const u_char * packet) { struct dp_handle * handle = (struct dp_handle *) u_handle; struct dp_header; /* make a copy of the userdata for every packet */ u_char * userdata_copy = (u_char *) malloc (handle->userdata_size); memcpy (userdata_copy, handle->userdata, handle->userdata_size); switch (handle->linktype) { case (DLT_EN10MB): dp_parse_ethernet (handle, header, packet); break; case (DLT_PPP): dp_parse_ppp (handle, header, packet); break; case (DLT_LINUX_SLL): dp_parse_linux_cooked (handle, header, packet); break; case (DLT_RAW): case (DLT_NULL): // hope for the best dp_parse_ip (handle, header, packet); break; default: fprintf(stdout, "Unknown linktype %d", handle->linktype); break; } free (userdata_copy); } int dp_dispatch (struct dp_handle * handle, int count, u_char *user, int size) { handle->userdata = user; handle->userdata_size = size; return pcap_dispatch (handle->pcap_handle, count, dp_pcap_callback, (u_char *)handle); } int dp_setnonblock (struct dp_handle * handle, int i, char * errbuf) { return pcap_setnonblock (handle->pcap_handle, i, errbuf); } char * dp_geterr (struct dp_handle * handle) { return pcap_geterr (handle->pcap_handle); } ukui-system-monitor/src/singleProcessNet/devices.cpp0000644000175000017500000000354013746753570021711 0ustar fengfeng/* * devices.cpp * * Copyright (c) 2011 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "devices.h" #include #include #include #include #include device * get_default_devices() { struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == -1) { std::cerr << "Fail to get interface addresses" << std::endl; // perror("getifaddrs"); return NULL; } device* devices = NULL; for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; // The interface is up, not a loopback and running ? if ( !(ifa->ifa_flags & IFF_LOOPBACK) && (ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING) ) { // Check if the interface is already known by going through all the devices bool found = false; device* pIter = devices; while(pIter != NULL) { if ( strcmp(ifa->ifa_name,pIter->name) == 0 ) { found = true; } pIter = pIter->next; } // We found a new interface, let's add it if ( found == false ) { devices = new device(strdup(ifa->ifa_name),devices); } } } freeifaddrs(ifaddr); return devices; } ukui-system-monitor/src/singleProcessNet/scanthread.cpp0000644000175000017500000001272713746753570022412 0ustar fengfeng/* * scanthread.cpp * * Copyright (c) 2016 Stephane List * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "scanthread.h" #include #include "process.h" #include "devices.h" #include "kylinsystemnethogs.h" extern Process * unknownudp; timeval curtime; int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) { struct dpargs * args = (struct dpargs *) userdata; struct tcphdr * tcp = (struct tcphdr *) m_packet; curtime = header->ts; /* get info from userdata, then call getPacket */ Packet * packet=NULL; switch (args->sa_family) { case (AF_INET): packet = new Packet (args->ip_src, ntohs(tcp->source), args->ip_dst, ntohs(tcp->dest), header->len, header->ts); break; case (AF_INET6): packet = new Packet (args->ip6_src, ntohs(tcp->source), args->ip6_dst, ntohs(tcp->dest), header->len, header->ts); break; } Connection * connection = findConnection(packet); if (connection != NULL) { connection->add(packet); } else { connection = new Connection (packet); getProcess(connection, args->device); } delete packet; return true; } int process_udp (u_char * userdata, const dp_header * header, const u_char * m_packet) { struct dpargs * args = (struct dpargs *) userdata; struct udphdr * udp = (struct udphdr *) m_packet; curtime = header->ts; Packet * packet=NULL; switch (args->sa_family) { case (AF_INET): packet = new Packet (args->ip_src, ntohs(udp->source), args->ip_dst, ntohs(udp->dest), header->len, header->ts); break; case (AF_INET6): packet = new Packet (args->ip6_src, ntohs(udp->source), args->ip6_dst, ntohs(udp->dest), header->len, header->ts); break; } Connection * connection = findConnection(packet); if (connection != NULL) { connection->add(packet); } else { connection = new Connection (packet); getProcess(connection, args->device); } delete packet; return true; } int process_ip (u_char * userdata, const dp_header * /* header */, const u_char * m_packet) { struct dpargs * args = (struct dpargs *) userdata; struct ip * ip = (struct ip *) m_packet; args->sa_family = AF_INET; args->ip_src = ip->ip_src; args->ip_dst = ip->ip_dst; return false; } int process_ip6 (u_char * userdata, const dp_header * /* header */, const u_char * m_packet) { struct dpargs * args = (struct dpargs *) userdata; const struct ip6_hdr * ip6 = (struct ip6_hdr *) m_packet; args->sa_family = AF_INET6; args->ip6_src = ip6->ip6_src; args->ip6_dst = ip6->ip6_dst; return false; } ScanThread::ScanThread(QObject *parent) : QThread(parent) { } void ScanThread::run() { process_init(); device * devices = NULL; int promisc = 0; devices = get_default_devices(); if ( devices == NULL ) { qCritical("Not devices to monitor"); return; } char errbuf[PCAP_ERRBUF_SIZE]; handle * handles = NULL; device * current_dev = devices; while (current_dev != NULL) { getLocal(current_dev->name); dp_handle * newhandle = dp_open_live(current_dev->name, BUFSIZ, promisc, 100, errbuf); if (newhandle != NULL) { dp_addcb (newhandle, dp_packet_ip, process_ip); dp_addcb (newhandle, dp_packet_ip6, process_ip6); dp_addcb (newhandle, dp_packet_tcp, process_tcp); dp_addcb (newhandle, dp_packet_udp, process_udp); if (dp_setnonblock (newhandle, 1, errbuf) == -1) { qCritical() << "Error putting libpcap in nonblocking mode"; } handles = new handle (newhandle, current_dev->name, handles); } else { qCritical() << "Error opening handler for device " << current_dev->name; } current_dev = current_dev->next; } struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); while (1) // main loop { bool packets_read = false; handle * current_handle = handles; while (current_handle != NULL) { userdata->device = current_handle->devicename; userdata->sa_family = AF_UNSPEC; int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); if (retval < 0) { qCritical() << "Error dispatching: " << retval; } else if (retval != 0) { packets_read = true; } current_handle = current_handle->next; } // If no packets were read at all this iteration, pause to prevent 100% CPU utilisation if (!packets_read) { usleep(100); } } } ukui-system-monitor/src/singleProcessNet/refreshthread.h0000644000175000017500000000320013746753570022553 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef REFRESHTHREAD_H #define REFRESHTHREAD_H #include #include #include "conninode.h" #include "process.h" class RefreshThread : public QThread { Q_OBJECT private: void gettotalb(Process * curproc, quint64 * recvd, quint64 * sent); void gettotal(Process * curproc, u_int32_t * recvd, u_int32_t * sent); void refresh_process_list(); void refresh_cnx_list(); int pid_cnx; public: explicit RefreshThread(QObject *parent = 0); void run(); signals: void procDetected(const QString& procname, quint64 rcv, quint64 sent, int pid, unsigned int uid, const QString& devname); void procDeleted(int pid); void refresh_finished(); void cnxDetected(const QHostAddress& sourceip, quint16 sport, const QHostAddress& destip, quint16 dport); public slots: void update_cnx_list(int pid); }; #endif // REFRESHTHREAD_H ukui-system-monitor/src/singleProcessNet/inode2prog.h0000644000175000017500000000227113746753570022004 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __INODE2PROG_h #define __INODE2PROG_h /* this should be called quickly after the packet * arrived, since the inode may disappear from the table * quickly, too :) */ #include "kylinsystemnethogs.h" struct prg_node { long inode; pid_t pid; std::string name; }; struct prg_node * findPID (unsigned long inode); void prg_cache_clear(); // reread the inode-to-prg_node-mapping void reread_mapping (); #endif ukui-system-monitor/src/singleProcessNet/decpcap.h0000644000175000017500000000421013746753570021326 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __DECPCAP_H #define __DECPCAP_H #include #include #include #define DP_ERRBUF_SIZE PCAP_ERRBUF_SIZE /* definitions */ enum dp_packet_type { dp_packet_ethernet, dp_packet_ppp, dp_packet_sll, dp_packet_ip, dp_packet_ip6, dp_packet_tcp, dp_packet_udp, dp_n_packet_types }; /*struct dp_header { * pcap };*/ typedef struct pcap_pkthdr dp_header; typedef int (*dp_callback)(u_char *, const dp_header *, const u_char *); struct dp_handle { pcap_t * pcap_handle; dp_callback callback [dp_n_packet_types]; int linktype; u_char * userdata; int userdata_size; }; /* functions to set up a handle (which is basically just a pcap handle) */ struct dp_handle * dp_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf); struct dp_handle * dp_open_offline(char * fname, char * ebuf); /* functions to add callbacks */ void dp_addcb (struct dp_handle * handle, enum dp_packet_type type, dp_callback callback); /* functions to parse payloads */ void dp_parse (enum dp_packet_type type, void * packet); /* functions to start monitoring */ int dp_dispatch (struct dp_handle * handler, int count, u_char *user, int size); /* functions that simply call libpcap */ int dp_datalink(struct dp_handle * handle); int dp_setnonblock (struct dp_handle * handle, int i, char * errbuf); char * dp_geterr (struct dp_handle * handle); #endif ukui-system-monitor/src/singleProcessNet/mainwindow.cpp0000644000175000017500000002746013746753570022452 0ustar fengfeng/* * mainwindow.cpp * * Copyright (c) 2016 Stephane List * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include //#include #include // for geteuid #include #include #include #include "scanthread.h" #include "linebandwith.h" #include "smallchart.h" // Table 1 enum { COLUMN_PID = 0, COLUMN_USER_NAME, COLUMN_PROC_NAME, COLUMN_PROC_STATUS, COLUMN_RCV, COLUMN_SENT, COLUMN_RCV_PER_S, COLUMN_SENT_PER_S, COLUMN_DEV_NAME, COLUMN_MORE, COLUMN_LAST }; // Table 2 enum { COLUMN_CNX_SIP = 0, COLUMN_CNX_SPORT, COLUMN_CNX_DIP, COLUMN_CNX_DPORT, COLUMN_CNX_LOOKUP, COLUMN_CNX_LAST }; Q_DECLARE_METATYPE(QHostAddress) MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->tableWidget_2->hide(); ui->pushButton_back->hide(); total_speed_recv = 0; total_speed_sent = 0; ui->centralWidget->layout()->removeWidget(ui->lineEdit); SmallChart * s = new SmallChart(this); ui->centralWidget->layout()->addWidget(s); ui->centralWidget->layout()->addWidget(ui->lineEdit); // if (geteuid() != 0) { // ui->lineEdit->setText("You need to be root to run qNetHogs!"); // return; // } scanThread = new ScanThread(this); scanThread->start(QThread::TimeCriticalPriority); refreshThread = new RefreshThread(this); refreshThread->start(QThread::HighPriority); connect(refreshThread, SIGNAL(procDetected(const QString &, quint64 , quint64 , int , unsigned int , const QString&)), this, SLOT(refreshLine(const QString &, quint64 , quint64 , int, unsigned int , const QString&))); connect(refreshThread, SIGNAL(procDeleted(int)), this, SLOT(deleteLine(int))); connect(refreshThread, SIGNAL(refresh_finished()), this, SLOT(updateGraph())); connect(refreshThread, SIGNAL(cnxDetected(const QHostAddress&, quint16, const QHostAddress&, quint16)), this, SLOT(cnxDetected(const QHostAddress&,quint16,const QHostAddress&,quint16))); connect(this, SIGNAL(new_speed(quint64,quint64)), s, SLOT(add_points(quint64,quint64))); connect(this, SIGNAL(reset_graph()), s, SLOT(reset())); ui->lineEdit->setText("正在运行!"); qRegisterMetaType(); // int id = qRegisterMetaType(); } MainWindow::~MainWindow() { delete ui; } int MainWindow::searchRow(int pid) { for (int i=0; i< ui->tableWidget->rowCount();i++) { if (ui->tableWidget->item(i, COLUMN_PID) && (ui->tableWidget->item(i, COLUMN_PID)->text().toInt() == pid)) { return i; } } return -1; } QString MainWindow::searchIcon(const QString & procname) { int i; QString s,filename; if (procname.startsWith("/usr/lib/apt/methods/")) { if (QFile::exists("/usr/share/icons/hicolor/48x48/status/aptdaemon-download.png")) { return "/usr/share/icons/hicolor/48x48/status/aptdaemon-download.png"; } } if (procname =="ssh") { if (QFile::exists("/usr/share/seahorse/icons/hicolor/48x48/apps/seahorse-key-ssh.png")) { return "/usr/share/seahorse/icons/hicolor/48x48/apps/seahorse-key-ssh.png"; } } // remove path i= procname.lastIndexOf("/"); if (i>0) { filename = procname.mid(i+1); } else { filename = procname; } s = filename; if (s == "gnome-software") { if (QFile::exists("/usr/share/icons/hicolor/48x48/apps/org.gnome.Software.png")) { return "/usr/share/icons/hicolor/48x48/apps/org.gnome.Software.png"; } } if (s == "snapd") { if (QFile::exists("/usr/share/app-install/icons/snappy.png")) { return "/usr/share/app-install/icons/snappy.png"; } } // remove end of prog after a '-' for example transmission-gtk gnome-software ... i= s.lastIndexOf("-"); if (i>0) { filename = s.left(i); } else { filename = s; } s = filename; s.prepend("/usr/share/pixmaps/"); s.append(".png"); if (QFile::exists(s)) { return s; } s = filename; s.prepend("/usr/share/pixmaps/"); s.append(".xpm"); if (QFile::exists(s)) { return s; } s = filename; s.prepend("/usr/share/icons/hicolor/48x48/apps/"); s.append(".png"); if (QFile::exists(s)) { return s; } return NULL; } QString MainWindow::uid2username(uid_t uid) { struct passwd * pwd = NULL; pwd = getpwuid(uid); if (pwd == NULL) { return "No name"; } return QString(pwd->pw_name); } void MainWindow::updateGraph() { emit new_speed(total_speed_recv,total_speed_sent); total_speed_recv = 0; total_speed_sent = 0; } void MainWindow::deleteLine(int pid) { int row = searchRow(pid); QTableWidgetItem *p = new QTableWidgetItem("finished"); p->setIcon(QIcon(":/red.ico")); ui->tableWidget->setItem(row, COLUMN_PROC_STATUS, p); } void MainWindow::refreshLine(const QString& procname, quint64 recv, quint64 sent, int pid, unsigned int uid, const QString& devname) { int row; QString s, iconfile; bool new_row = false; if (pid == 0) return; row = searchRow(pid); if (row == -1) { ui->tableWidget->insertRow(0); row = 0; new_row = true; } if (new_row) { QTableWidgetItem *pname = new QTableWidgetItem(procname); iconfile = searchIcon(procname); if (iconfile != NULL) { pname->setIcon(QIcon(iconfile)); } pname->setTextAlignment(Qt::AlignVCenter); ui->tableWidget->setItem(row, COLUMN_PROC_NAME, pname); s.setNum(recv); QTableWidgetItem *prcv = new QTableWidgetItem(s); prcv->setTextAlignment(Qt::AlignVCenter|Qt::AlignRight); ui->tableWidget->setItem(row, COLUMN_RCV_PER_S, prcv ); s.setNum(sent); QTableWidgetItem *psent = new QTableWidgetItem(s); psent->setTextAlignment(Qt::AlignVCenter|Qt::AlignRight); ui->tableWidget->setItem(row, COLUMN_SENT_PER_S, psent); s.setNum(pid); QTableWidgetItem *ppid = new QTableWidgetItem(s); ppid->setTextAlignment(Qt::AlignVCenter|Qt::AlignHCenter); ui->tableWidget->setItem(row, COLUMN_PID, ppid); QTableWidgetItem *pdevname = new QTableWidgetItem(devname); pdevname->setTextAlignment(Qt::AlignVCenter|Qt::AlignHCenter); ui->tableWidget->setItem(row, COLUMN_DEV_NAME, pdevname); QTableWidgetItem *pusername = new QTableWidgetItem(uid2username(uid)); pusername->setTextAlignment(Qt::AlignVCenter|Qt::AlignHCenter); ui->tableWidget->setItem(row, COLUMN_USER_NAME, pusername); QTableWidgetItem *p = new QTableWidgetItem("正在运行"); p->setIcon(QIcon(":/green.ico")); ui->tableWidget->setItem(row, COLUMN_PROC_STATUS, p); lineBandwith* br = new lineBandwith(this); ui->tableWidget->setCellWidget(row,COLUMN_RCV_PER_S,br); total_speed_recv +=br->new_count(recv); lineBandwith* bs = new lineBandwith(this); ui->tableWidget->setCellWidget(row,COLUMN_SENT_PER_S,bs); total_speed_sent += bs->new_count(sent); QPushButtonArrow* b = new QPushButtonArrow(this); b->pid = pid; ui->tableWidget->setCellWidget(row, COLUMN_MORE, b); connect(b, SIGNAL(display_cnx(int)), this, SLOT(update_cnx_list(int))); connect(b, SIGNAL(display_cnx(int)), refreshThread, SLOT(update_cnx_list(int))); } else { lineBandwith *br = qobject_cast(ui->tableWidget->cellWidget(row, COLUMN_RCV_PER_S)); total_speed_recv +=br->new_count(recv); lineBandwith *bs = qobject_cast(ui->tableWidget->cellWidget(row, COLUMN_SENT_PER_S)); total_speed_sent += bs->new_count(sent); } s.setNum(recv); QTableWidgetItem *prcv = new QTableWidgetItem(s); prcv->setTextAlignment(Qt::AlignVCenter|Qt::AlignRight); ui->tableWidget->setItem(row, COLUMN_RCV, prcv); s.setNum(sent); QTableWidgetItem *psent = new QTableWidgetItem(s); psent->setTextAlignment(Qt::AlignVCenter|Qt::AlignRight); ui->tableWidget->setItem(row, COLUMN_SENT, psent); for (int i=0; itableWidget-> resizeColumnToContents(i); } } void MainWindow::on_actionAbout_Qt_triggered() { QMessageBox::aboutQt(this, "About Qt"); } void MainWindow::on_actionAbout_triggered() { QMessageBox::about(this, "关于进程网络监控工具", "进程网络监控工具\n在GPL v3下是一款免费的软件!"); } void MainWindow::on_actionExit_triggered() { QApplication::quit(); } void MainWindow::on_actionReset_triggered() { emit reset_graph(); } void MainWindow::update_cnx_list(int pid) { ui->tableWidget_2->clearContents(); ui->tableWidget_2->setRowCount(0); ui->tableWidget_2->show(); ui->pushButton_back->show(); } void MainWindow::cnxDetected(const QHostAddress& sourceip, quint16 sport, const QHostAddress& destip, quint16 dport) { for (int i=0; i< ui->tableWidget_2->rowCount();i++) { if ((ui->tableWidget_2->item(i, COLUMN_CNX_SPORT)->text().toInt() == sport) && (ui->tableWidget_2->item(i, COLUMN_CNX_DPORT)->text().toInt() == dport)) return; // cnx already in table } // if not found add line ui->tableWidget_2->insertRow(0); QTableWidgetItem *psip = new QTableWidgetItem(sourceip.toString()); ui->tableWidget_2->setItem(0, COLUMN_CNX_SIP, psip); QTableWidgetItem *pdip = new QTableWidgetItem(destip.toString()); ui->tableWidget_2->setItem(0, COLUMN_CNX_DIP, pdip); QTableWidgetItem *psport = new QTableWidgetItem(QString::number(sport)); ui->tableWidget_2->setItem(0, COLUMN_CNX_SPORT, psport); QTableWidgetItem *pdport = new QTableWidgetItem(QString::number(dport)); ui->tableWidget_2->setItem(0, COLUMN_CNX_DPORT, pdport); for (int i=0; itableWidget_2-> resizeColumnToContents(i); } QHostInfo::lookupHost(destip.toString(), this, SLOT(lookedUp(QHostInfo))); } void MainWindow::lookedUp(const QHostInfo &host) { if (host.error() != QHostInfo::NoError) { qDebug() << "Lookup failed:" << host.errorString(); return; } // qDebug() << "host:" << host.hostName(); foreach (const QHostAddress &address, host.addresses()) { // qDebug() << "Found address:" << address.toString(); for (int row=0; row< ui->tableWidget_2->rowCount();row++) { if ((ui->tableWidget_2->item(row, COLUMN_CNX_DIP)->text() == address.toString())) { QTableWidgetItem *pname = new QTableWidgetItem(host.hostName()); ui->tableWidget_2->setItem(row, COLUMN_CNX_LOOKUP, pname); //return; } } } ui->tableWidget_2-> resizeColumnToContents(COLUMN_CNX_LOOKUP); } void MainWindow::on_pushButton_back_clicked() { ui->tableWidget_2->hide(); ui->pushButton_back->hide(); } ukui-system-monitor/src/singleProcessNet/process.h0000644000175000017500000000643313746753570021416 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __PROCESS_H #define __PROCESS_H #include #include #include "kylinsystemnethogs.h" #include "connection.h" void check_all_procs (); class ConnList { public: ConnList (Connection * m_val, ConnList * m_next) { assert (m_val != NULL); val = m_val; next = m_next; } ~ConnList () { /* does not delete its value, to allow a connection to * remove itself from the global connlist in its destructor */ } Connection * getVal () { return val; } void setNext (ConnList * m_next) { next = m_next; } ConnList * getNext () { return next; } private: Connection * val; ConnList * next; }; class Process { public: /* the process makes a copy of the name. the device name needs to be stable. */ Process (const unsigned long m_inode, const char * m_devicename, const char * m_name = NULL) : inode (m_inode) { //std::cout << "ARN: Process created with dev " << m_devicename << std::endl; if (DEBUG) std::cout << "PROC: Process created at " << this << std::endl; if (m_name == NULL) name = NULL; else name = strdup(m_name); devicename = m_devicename; connections = NULL; pid = 0; uid = 0; } void check () { assert (pid >= 0); } ~Process () { free (name); if (DEBUG) std::cout << "PROC: Process deleted at " << this << std::endl; // if(unknowntcp) // { // delete unknowntcp; // } } int getLastPacket (); char * name; const char * devicename; int pid; ConnList * connections; uid_t getUid() { return uid; } void setUid(uid_t m_uid) { uid = m_uid; } unsigned long getInode() { return inode; } private: const unsigned long inode; uid_t uid; }; class ProcList { public: ProcList (Process * m_val, ProcList * m_next) { assert (m_val != NULL); val = m_val; next = m_next; } int size (); Process * getVal () { return val; } ProcList * getNext () { return next; } ProcList * next; ~ProcList() {/* if(processes) { delete processes; }*/ } private: Process * val; }; Process * getProcess (Connection * connection, const char * devicename = NULL); void process_init (); void process_delete(); void refreshconninode (); void procclean (); #endif ukui-system-monitor/src/singleProcessNet/refreshthread.cpp0000644000175000017500000001174713764070001023102 0ustar fengfeng/* * refreshthread.cpp * * Copyright (c) 2016 Stephane List * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "refreshthread.h" #include #include extern ProcList * processes; extern timeval curtime; extern Process * unknowntcp; extern Process * unknownudp; extern Process * unknownip; RefreshThread::RefreshThread(QObject *parent) : QThread(parent) { pid_cnx = -1; } /** get total values for this process */ void RefreshThread::gettotal(Process * curproc, u_int32_t * recvd, u_int32_t * sent) { u_int32_t sum_sent = 0, sum_recv = 0; ConnList * curconn = curproc->connections; while (curconn != NULL) { Connection * conn = curconn->getVal(); sum_sent += conn->sumSent; sum_recv += conn->sumRecv; curconn = curconn->getNext(); } *recvd = sum_recv; *sent = sum_sent; } void RefreshThread::gettotalb(Process * curproc, quint64 * recvd, quint64 * sent) { u_int32_t sum_sent = 0, sum_recv = 0; gettotal(curproc, &sum_recv, &sum_sent); *sent = sum_sent; *recvd = sum_recv; } void RefreshThread::refresh_process_list() { ProcList * curproc = processes; ProcList * previousproc = NULL; int nproc = processes->size(); while (curproc != NULL) { // walk though its connections, summing up their data, and // throwing away connections that haven't received a package // in the last PROCESSTIMEOUT seconds. assert (curproc != NULL); assert (curproc->getVal() != NULL); assert (nproc == processes->size()); /* remove timed-out processes (unless it's one of the the unknown process) */ if ((curproc->getVal()->getLastPacket() + PROCESSTIMEOUT <= curtime.tv_sec) && (curproc->getVal() != unknowntcp) && (curproc->getVal() != unknownudp) && (curproc->getVal() != unknownip)) { //qDebug() << "PROC: Deleting process" << curproc->getVal()->name; ProcList * todelete = curproc; Process * p_todelete = curproc->getVal(); emit procDeleted(curproc->getVal()->pid); if (previousproc) { previousproc->next = curproc->next; curproc = curproc->next; } else { processes = curproc->getNext(); curproc = processes; } delete todelete; delete p_todelete; nproc--; } else { // add a non-timed-out process to the list of stuff to show quint64 value_sent = 0, value_recv = 0; gettotalb(curproc->getVal(), &value_recv, &value_sent); uid_t uid = curproc->getVal()->getUid(); emit procDetected(curproc->getVal()->name, value_recv, value_sent, curproc->getVal()->pid, uid , curproc->getVal()->devicename);; previousproc = curproc; curproc = curproc->next; } } } void RefreshThread::update_cnx_list(int pid) { pid_cnx = pid; } void RefreshThread::refresh_cnx_list() { // qDebug() << "refresh cnx for pid :" << pid_cnx; ProcList * curproc = processes; while (curproc != NULL) { if (curproc->getVal()->pid == pid_cnx) { //qDebug() << "TODO IPv6"; ConnList * curconn = curproc->getVal()->connections; while (curconn != NULL) { Connection * conn = curconn->getVal(); /* qDebug() << "sip" << QHostAddress(ntohl(conn->refpacket->sip.s_addr)); qDebug() << "dip" << QHostAddress(ntohl(conn->refpacket->dip.s_addr)); qDebug() << "sport" << conn->refpacket->sport; qDebug() << "dport" << conn->refpacket->dport; */ emit cnxDetected(QHostAddress(ntohl(conn->refpacket->sip.s_addr)), conn->refpacket->sport, QHostAddress(ntohl(conn->refpacket->dip.s_addr)), conn->refpacket->dport); curconn = curconn->getNext(); } } curproc = curproc->next; } } void RefreshThread::run() { while (1) { sleep(5); refreshconninode(); refresh_process_list(); refresh_cnx_list(); emit refresh_finished(); } } ukui-system-monitor/src/singleProcessNet/scanthread.h0000644000175000017500000000305613746753570022052 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SCANTHREAD_H #define SCANTHREAD_H #include #include #include #include #include extern "C" { #include "decpcap.h" } class ScanThread : public QThread { Q_OBJECT public: explicit ScanThread(QObject *parent = 0); void run(); signals: public slots: }; struct dpargs { const char * device; int sa_family; in_addr ip_src; in_addr ip_dst; in6_addr ip6_src; in6_addr ip6_dst; }; class handle { public: handle (dp_handle * m_handle, const char * m_devicename = NULL, handle * m_next = NULL) { content = m_handle; next = m_next; devicename = m_devicename; } dp_handle * content; const char * devicename; handle * next; }; #endif // SCANTHREAD_H ukui-system-monitor/src/singleProcessNet/conninode.h0000644000175000017500000000151513746753570021710 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // handling the connection->inode mapping void refreshconninode (); ukui-system-monitor/src/singleProcessNet/connection.h0000644000175000017500000000502013746753570022066 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __CONNECTION_H #define __CONNECTION_H #include #include "packet.h" class PackListNode { public: PackListNode (Packet * m_val, PackListNode * m_next = NULL) { val = m_val; next = m_next; } ~PackListNode () { delete val; if (next != NULL) delete next; } PackListNode * next; Packet * val; }; class PackList { public: PackList () { content = NULL; } PackList (Packet * m_val) { assert (m_val != NULL); content = new PackListNode(m_val); } ~PackList () { if (content != NULL) delete content; } /* sums up the total bytes used and removes 'old' packets */ u_int32_t sumanddel (timeval t); /* calling code may delete packet */ void add (Packet * p); private: PackListNode * content; }; class Connection { public: /* constructs a connection, makes a copy of * the packet as 'refpacket', and adds the * packet to the packlist */ /* packet may be deleted by caller */ Connection (Packet * packet); ~Connection(); /* add a packet to the packlist * will delete the packet structure * when it is 'merged with' (added to) another * packet */ void add (Packet * packet); int getLastPacket () { return lastpacket; } /* sums up the total bytes used * and removes 'old' packets. */ void sumanddel(timeval curtime, u_int32_t * recv, u_int32_t * sent); /* for checking if a packet is part of this connection */ /* the reference packet is always *outgoing*. */ Packet * refpacket; /* total sum or sent/received bytes */ u_int32_t sumSent; u_int32_t sumRecv; private: PackList * sent_packets; PackList * recv_packets; int lastpacket; }; /* Find the connection this packet belongs to */ /* (the calling code may free the packet afterwards) */ Connection * findConnection (Packet * packet); #endif ukui-system-monitor/src/singleProcessNet/inode2prog.cpp0000644000175000017500000001221613754661732022334 0ustar fengfeng/* * inode2prog.cpp * * Copyright (c) 2005,2006,2008,2009 Arnout Engelen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "inode2prog.h" extern bool bughuntmode; // Not sure, but assuming there's no more PID's than go into 64 unsigned bits.. const int MAX_PID_LENGTH = 20; // Max length of filenames in /proc//fd/*. These are numeric, so 10 digits seems like a safe assumption. const int MAX_FDLINK = 10; /* maps from inode to program-struct */ std::map inodeproc; bool is_number (const char * string) { while (*string) { if (!isdigit (*string)) return false; string++; } return true; } unsigned long str2ulong (const char * ptr) { unsigned long retval = 0; while ((*ptr >= '0') && (*ptr <= '9')) { retval *= 10; retval += *ptr - '0'; ptr++; } return retval; } int str2int (const char * ptr) { int retval = 0; while ((*ptr >= '0') && (*ptr <= '9')) { retval *= 10; retval += *ptr - '0'; ptr++; } return retval; } static std::string read_file (int fd) { char buf[255]; std::string content; for (int length; (length = read(fd, buf, sizeof(buf))) > 0;) { if (length < 0) { std::fprintf(stderr, "Error reading file: %s\n", std::strerror(errno)); std::exit(34); } content.append(buf, length); } return content; } static std::string read_file (const char* filepath) { int fd = open(filepath, O_RDONLY); if (fd < 0) { std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno)); std::exit(3); return NULL; } std::string contents = read_file(fd); if (close(fd)) { std::fprintf(stderr, "Error opening %s: %s\n", filepath, std::strerror(errno)); std::exit(34); } return contents; } std::string getprogname (pid_t pid) { const int maxfilenamelen = 14 + MAX_PID_LENGTH + 1; char filename[maxfilenamelen]; std::snprintf(filename, maxfilenamelen, "/proc/%d/cmdline", pid); return read_file(filename); } void setnode (unsigned long inode, pid_t pid) { prg_node * current_value = inodeproc[inode]; if (current_value == NULL || current_value->pid != pid) { prg_node * newnode = new prg_node; newnode->inode = inode; newnode->pid = pid; newnode->name = getprogname(pid); inodeproc[inode] = newnode; delete current_value; } } void get_info_by_linkname (const char * pid, const char * linkname) { if (strncmp(linkname, "socket:[", 8) == 0) { setnode(str2ulong(linkname + 8), str2int(pid)); } } /* updates the `inodeproc' inode-to-prg_node * for all inodes belonging to this PID * (/proc/pid/fd/42) * */ void get_info_for_pid(const char * pid) { char dirname[10 + MAX_PID_LENGTH]; size_t dirlen = 10 + strlen(pid); snprintf(dirname, dirlen, "/proc/%s/fd", pid); DIR * dir = opendir(dirname); if (!dir) { std::cout << "Couldn't open dir " << dirname << ": " << strerror(errno) << "\n"; return; } /* walk through /proc/%s/fd/... */ dirent * entry; while ((entry = readdir(dir))) { if (entry->d_type != DT_LNK) continue; //std::cout << "Looking at: " << entry->d_name << std::endl; size_t fromlen = dirlen + strlen(entry->d_name) + 1; char fromname[10 + MAX_PID_LENGTH + 1 + MAX_FDLINK]; snprintf (fromname, fromlen, "%s/%s", dirname, entry->d_name); //std::cout << "Linking from: " << fromname << std::endl; int linklen = 80; char linkname [linklen]; int usedlen = readlink(fromname, linkname, linklen-1); if (usedlen == -1) { continue; } assert (usedlen < linklen); linkname[usedlen] = '\0'; get_info_by_linkname (pid, linkname); } closedir(dir); } /* updates the `inodeproc' inode-to-prg_node mapping * for all processes in /proc */ void reread_mapping () { DIR * proc = opendir ("/proc"); if (proc == 0) { std::cerr << "Error reading /proc, needed to get inode-to-pid-maping\n"; exit(1); } dirent * entry; while ((entry = readdir(proc))) { if (entry->d_type != DT_DIR) continue; if (! is_number (entry->d_name)) continue; get_info_for_pid(entry->d_name); } closedir(proc); } struct prg_node * findPID (unsigned long inode) { /* we first look in inodeproc */ struct prg_node * node = inodeproc[inode]; if (node != NULL) { return node; } reread_mapping(); struct prg_node * retval = inodeproc[inode]; return retval; } //void prg_cache_clear() {}; ukui-system-monitor/src/processcategory.h0000644000175000017500000000253713755705142017656 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCESSCATEGORY_H #define PROCESSCATEGORY_H #include #include class MyHoverButton; class ProcessCategory : public QWidget { Q_OBJECT public: explicit ProcessCategory(int tabIndex, QWidget *parent = 0); ~ProcessCategory(); signals: void activeWhoseProcessList(int index); private: int width; int height; int activeIndex; QHBoxLayout *layout = nullptr; MyHoverButton *activeProcessButton = nullptr; MyHoverButton *userProcessButton = nullptr; MyHoverButton *allProcessButton = nullptr; }; #endif // PROCESSCATEGORY_H ukui-system-monitor/src/filesystemwatcher.h0000644000175000017500000000276313746753504020212 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FILESYSTEMWATCHER_H #define FILESYSTEMWATCHER_H #include #include #include class FileSystemWatcher : public QObject { Q_OBJECT public: static FileSystemWatcher *instance(); FileSystemWatcher(QObject *parent = 0); ~FileSystemWatcher(); bool watcherInitSuccess(); signals: void deviceAdded(const QString &addDevice); void deviceRemoved(const QString &removeDevice); public slots: bool initWatcher(); bool clearWatcher(); private slots: void onMountDeviceFileContentsChanged(); private: int m_fd; QSocketNotifier *m_socketNotifier = nullptr; QSet m_origFileSet; static FileSystemWatcher *m_watcher; }; #endif // FILESYSTEMWATCHER_H ukui-system-monitor/src/main.cpp0000644000175000017500000000543213764070001015703 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "framelessExtended/framelesshandle.h" #include "systemmonitor.h" #include "shell/customstyle.h" //#include "maincontroller.h" #include // should be put in the last int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QString id = QString("ukui-system-monitor"+QLatin1String(getenv("DISPLAY"))); QtSingleApplication app(id,argc,argv); if(app.isRunning()) { app.sendMessage(QApplication::arguments().length() > 1 ? QApplication::arguments().at(1) : app.applicationFilePath()); qDebug() << QObject::tr("ukui-system-monitor is already running!"); return EXIT_SUCCESS; } else { QApplication::setApplicationName("Kylin System Monitor"); QApplication::setApplicationVersion("0.0.0.0001"); QString locale = QLocale::system().name(); QTranslator translator; if(locale == "zh_CN" || locale == "es" || locale == "fr" || locale == "de" || locale == "ru") {//中文 西班牙语 法语 德语 俄语 if(!translator.load("ukui-system-monitor_" + locale + ".qm", ":/translation/")) qDebug() << "Load translation file:"<< "ukui-system-monitor_" + locale + ".qm" << " failed!"; else app.installTranslator(&translator); } SystemMonitor *monitor=new SystemMonitor(); monitor->setAttribute(Qt::WA_DeleteOnClose); app.setActivationWindow(monitor); QObject::connect(&app, SIGNAL(messageReceived(const QString&)),monitor, SLOT(sltMessageReceived(const QString&))); monitor->show(); // qDebug()<activateOn(monitor); app.exec(); return 0; } } ukui-system-monitor/src/smoothlinegenerator.h0000644000175000017500000000506613764070001020517 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SMOOTHLINEGENERATOR_H #define SMOOTHLINEGENERATOR_H #include #include #include class SmoothLineGenerator { public: /** * 传入曲线上的点的 list,创建平滑曲线 * * @param points - 曲线上的点 * @return - 返回使用给定的点创建的 QPainterPath 表示的平滑曲线 * 生成的平滑曲线,会发现平滑曲线段之间会有很多小段的抖动 */ static QPainterPath generateSmoothCurve1(const QList &points); /** * 传入曲线上的点的 list,创建平滑曲线 * @param points - 曲线上的点 * @return - 返回使用给定的点创建的 QPainterPath 表示的平滑曲线 * 可以解决平滑曲线段之间的抖动问题,但是曲线段在比较陡时,曲线上的值可能会超出曲线原来值的范围 */ static QPainterPath generateSmoothCurve(const QList &points); private: /** * Solves a tridiagonal system for one of coordinates (x or y) * of first Bezier control points. * @param result - Solution vector. * @param rhs - Right hand side vector. * @param n - Size of rhs. */ static void calculateFirstControlPoints(double * &result, const double *rhs, int n); /** * Calculate control points of the smooth curve using the given knots. * @param knots - Points of the given curve. * @param firstControlPoints - Store the generated first control points. * @param secondControlPoints - Store the generated second control points. */ static void calculateControlPoints(const QList &knots, QList *firstControlPoints, QList *secondControlPoints); }; #endif // SMOOTHLINEGENERATOR_H ukui-system-monitor/src/res.qrc0000644000175000017500000000255613746753504015577 0ustar fengfeng img/close.png img/fullscreen.png img/minimize.png img/processmanager.png translation/ukui-system-monitor_bo.ts translation/ukui-system-monitor_de.qm translation/ukui-system-monitor_de.ts translation/ukui-system-monitor_es.qm translation/ukui-system-monitor_es.ts translation/ukui-system-monitor_fr.qm translation/ukui-system-monitor_fr.ts translation/ukui-system-monitor_ru.qm translation/ukui-system-monitor_ru.ts translation/ukui-system-monitor_tr.qm translation/ukui-system-monitor_tr.ts translation/ukui-system-monitor_zh_CN.qm translation/ukui-system-monitor_zh_CN.ts img/user_proc.png img/all_proc.png img/active_proc.png img/search.png img/down_arrow.png img/up_arrow.png img/button-close-default-add-background-three.svg img/drive-harddisk-system.png img/ukui-system-monitor.png ukui-system-monitor/src/smoothlinegenerator.cpp0000644000175000017500000001234113764347670021067 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "smoothlinegenerator.h" #include #include QPainterPath SmoothLineGenerator::generateSmoothCurve1(const QList &points) { if (points.size() == 0) { return QPainterPath(); } QPainterPath path(points[0]); for (int i = 0; i < points.size() - 1; ++i) { // 控制点的 x 坐标为 sp 与 ep 的 x 坐标和的一半 // 第一个控制点 c1 的 y 坐标为起始点 sp 的 y 坐标 // 第二个控制点 c2 的 y 坐标为结束点 ep 的 y 坐标 QPointF sp = points[i]; QPointF ep = points[i+1]; QPointF c1 = QPointF((sp.x() + ep.x()) / 2, sp.y()); QPointF c2 = QPointF((sp.x() + ep.x()) / 2, ep.y()); path.cubicTo(c1, c2, ep); } return path; } //使用QPainterPath画贝塞尔曲线 QPainterPath SmoothLineGenerator::generateSmoothCurve(const QList &points) { QPainterPath path; int len = points.size(); if (len < 2) { return path; } QList firstControlPoints; QList secondControlPoints; calculateControlPoints(points, &firstControlPoints, &secondControlPoints); path.moveTo(points[0].x(), points[0].y());//默认是从原点(0,0)开始绘图,使用moveTo()改变绘图的开始位置 // Using bezier curve to generate a smooth curve. for (int i = 0; i < len - 1; ++i) { // path.cubicTo(firstControlPoints[i], secondControlPoints[i], points[i+1]);//三阶贝赛尔曲线函数cubicto()绘图,传入点1 firstControlPoints[i],点2 secondControlPoints[i],endPoint(points[i+1]) path.lineTo(firstControlPoints[i]); // path.moveTo(firstControlPoints[i]); // QLinearGradient lineGradient(firstControlPoints[i],secondControlPoints[i]); // lineGradient } return path; } void SmoothLineGenerator::calculateFirstControlPoints(double *&result, const double *rhs, int n) { double *tmp = new double[n]; double b = 2.0; result[0] = rhs[0] / b; // Decomposition and forward substitution. for (int i = 1; i < n; i++) { tmp[i] = 1 / b; b = (i < n - 1 ? 4.0 : 3.5) - tmp[i]; result[i] = (rhs[i] - result[i - 1]) / b; } for (int i = 1; i < n; i++) { result[n - i - 1] -= tmp[n - i] * result[n - i]; // Backsubstitution. } delete[] tmp; } void SmoothLineGenerator::calculateControlPoints(const QList &knots, QList *firstControlPoints, QList *secondControlPoints) { int n = knots.size() - 1; for (int i = 0; i < n; ++i) { firstControlPoints->append(QPointF()); secondControlPoints->append(QPointF()); } if (n == 1) { // Special case: Bezier curve should be a straight line. // P1 = (2P0 + P3) / 3 (*firstControlPoints)[0].rx() = (2 * knots[0].x() + knots[1].x()) / 3; (*firstControlPoints)[0].ry() = (2 * knots[0].y() + knots[1].y()) / 3; // P2 = 2P1 – P0 (*secondControlPoints)[0].rx() = 2 * (*firstControlPoints)[0].x() - knots[0].x(); (*secondControlPoints)[0].ry() = 2 * (*firstControlPoints)[0].y() - knots[0].y(); return; } // Calculate first Bezier control points double *xs = new double[n]; double *ys = new double[n]; double *rhsx = new double[n]; // Right hand side vector double *rhsy = new double[n]; // Right hand side vector // Set right hand side values for (int i = 1; i < n - 1; ++i) { rhsx[i] = 4 * knots[i].x() + 2 * knots[i + 1].x(); rhsy[i] = 4 * knots[i].y() + 2 * knots[i + 1].y(); } rhsx[0] = knots[0].x() + 2 * knots[1].x(); rhsx[n - 1] = (8 * knots[n - 1].x() + knots[n].x()) / 2.0; rhsy[0] = knots[0].y() + 2 * knots[1].y(); rhsy[n - 1] = (8 * knots[n - 1].y() + knots[n].y()) / 2.0; // Calculate first control points coordinates calculateFirstControlPoints(xs, rhsx, n); calculateFirstControlPoints(ys, rhsy, n); // Fill output control points. for (int i = 0; i < n; ++i) { (*firstControlPoints)[i].rx() = xs[i]; (*firstControlPoints)[i].ry() = ys[i]; if (i < n - 1) { (*secondControlPoints)[i].rx() = 2 * knots[i + 1].x() - xs[i + 1]; (*secondControlPoints)[i].ry() = 2 * knots[i + 1].y() - ys[i + 1]; } else { (*secondControlPoints)[i].rx() = (knots[n].x() + xs[n - 1]) / 2; (*secondControlPoints)[i].ry() = (knots[n].y() + ys[n - 1]) / 2; } } delete[] xs; delete[] ys; delete[] rhsx; delete[] rhsy; } ukui-system-monitor/src/util.cpp0000644000175000017500000002451313764070001015735 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "util.h" #include #include #include #include #include #include #include #include const QPixmap loadSvg(const QString &fileName, const int size) { QPixmap pixmap(size, size); QSvgRenderer renderer(fileName); pixmap.fill(Qt::transparent); QPainter painter; painter.begin(&pixmap); renderer.render(&painter); painter.end(); return pixmap; } QPixmap drawSymbolicColoredPixmap(const QPixmap &source) { QColor gray(128,128,128); QColor standard (31,32,34); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else if(qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else { img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } QPixmap drawSymbolicBlackColoredPixmap(const QPixmap &source) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red())>=200 && qAbs(color.green())>=200 && qAbs(color.blue())>=200) { color.setRed(56); color.setGreen(56); color.setBlue(56); img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } std::string make_string(char *c_str) { if (!c_str) { return string(); } string s(c_str); g_free(c_str); return s; } static inline unsigned divide(unsigned *q, unsigned *r, unsigned d) { *q = *r / d; *r = *r % d; return *q != 0; } QString formatDurationForDisplay(unsigned centiseconds) { unsigned weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0; (void)(divide(&seconds, ¢iseconds, 100) && divide(&minutes, &seconds, 60) && divide(&hours, &minutes, 60) && divide(&days, &hours, 24) && divide(&weeks, &days, 7)); QString formatTime; gchar *duration = NULL; if (weeks) { duration = g_strdup_printf("%uw%ud", weeks, days); formatTime = QString(QLatin1String(duration)); if (duration) { g_free(duration); duration = NULL; } return formatTime; } if (days) { duration = g_strdup_printf("%ud%02uh", days, hours); formatTime = QString(QLatin1String(duration)); if (duration) { g_free(duration); duration = NULL; } return formatTime; } if (hours) { duration = g_strdup_printf("%u:%02u:%02u", hours, minutes, seconds); formatTime = QString(QLatin1String(duration)); if (duration) { g_free(duration); duration = NULL; } return formatTime; } duration = g_strdup_printf("%u:%02u.%02u", minutes, seconds, centiseconds); formatTime = QString(QLatin1String(duration)); if (duration) { g_free(duration); duration = NULL; } return formatTime; } std::string getDesktopFileAccordProcName(QString procName, QString cmdline) { QDirIterator dir("/usr/share/applications", QDirIterator::Subdirectories); std::string desktopFile; QString procname = procName.toLower(); procname.replace("_", "-"); QString processFilename = procname + ".desktop"; while(dir.hasNext()) { if (dir.fileInfo().suffix() == "desktop") { if (dir.fileName().toLower().contains(processFilename)) { desktopFile = dir.filePath().toStdString(); break; } } dir.next(); } return desktopFile; } QPixmap getAppIconFromDesktopFile(std::string desktopFile, int iconSize) { std::ifstream in; in.open(desktopFile); QIcon defaultExecutableIcon = QIcon::fromTheme("application-x-executable");//gnome-mine-application-x-executable if (defaultExecutableIcon.isNull()) { defaultExecutableIcon = QIcon("/usr/share/icons/ukui-icon-theme-default/48x48/mimetypes/application-x-executable.png"); if (defaultExecutableIcon.isNull()) defaultExecutableIcon = QIcon(":/res/autostart-default.png"); } QIcon icon; QString iconName; while(!in.eof()) { std::string line; std::getline(in,line); iconName = QString::fromStdString(line); if (iconName.startsWith("Icon=")) { iconName.remove(0,5); } else { continue; } if (iconName.contains("/")) { icon = QIcon(iconName); } else { icon = QIcon::fromTheme(iconName, defaultExecutableIcon); break; } } in.close(); qreal devicePixelRatio = qApp->devicePixelRatio(); QPixmap pixmap = icon.pixmap(iconSize * devicePixelRatio, iconSize * devicePixelRatio); pixmap.setDevicePixelRatio(devicePixelRatio); return pixmap; } QString getDisplayNameAccordProcName(QString procName, std::string desktopFile) { if (desktopFile.size() == 0) { return procName; } std::ifstream in; in.open(desktopFile); QString displayName = procName; while(!in.eof()) { std::string line; std::getline(in,line); QString lineContent = QString::fromStdString(line); QString localNameFlag = QString("Name[%1]=").arg(QLocale::system().name()); QString nameFlag = "Name="; QString genericNameFlag = QString("GenericName[%1]=").arg(QLocale::system().name()); if (lineContent.startsWith(localNameFlag)) { displayName = lineContent.remove(0, localNameFlag.size()); break; } else if (lineContent.startsWith(genericNameFlag)) { displayName = lineContent.remove(0, genericNameFlag.size()); break; } else if (lineContent.startsWith(nameFlag)) { displayName = lineContent.remove(0, nameFlag.size()); continue; } else { continue; } } in.close(); return displayName; } QString formatProcessState(guint state) { QString status; switch (state) { case GLIBTOP_PROCESS_RUNNING: status = QString(QObject::tr("Running"));//运行中 break; case GLIBTOP_PROCESS_STOPPED: status = QString(QObject::tr("Stopped"));//已停止 break; case GLIBTOP_PROCESS_ZOMBIE: status = QString(QObject::tr("Zombie"));//僵死 break; case GLIBTOP_PROCESS_UNINTERRUPTIBLE: status = QString(QObject::tr("Uninterruptible"));//不可中断 break; default: status = QString(QObject::tr("Sleeping"));//睡眠中 break; } return status; } QString getNiceLevel(int nice) { if (nice < -7) return QObject::tr("Very High"); else if (nice < -2) return QObject::tr("High"); else if (nice < 3) return QObject::tr("Normal"); else if (nice < 7) return QObject::tr("Low"); else return QObject::tr("Very Low"); } QString getNiceLevelWithPriority(int nice) { if (nice < -7) return QObject::tr("Very High Priority"); else if (nice < -2) return QObject::tr("High Priority"); else if (nice < 3) return QObject::tr("Normal Priority"); else if (nice < 7) return QObject::tr("Low Priority"); else return QObject::tr("Very Low Priority"); } void setFontSize(QPainter &painter, int textSize) { QFont font = painter.font() ; font.setPixelSize(textSize); // font.setPointSize(textSize); painter.setFont(font); } QString formatUnitSize(double v, const char** orders, int nb_orders) { int order = 0; while (v >= 1024 && order + 1 < nb_orders) { order++; v = v/1024; } char buffer1[30]; snprintf(buffer1, sizeof(buffer1), "%.1lf %s", v, orders[order]); return QString(buffer1); } QString formatByteCount(double v) { static const char* orders[] = { "B", "KB", "MB", "GB", "TB" }; return formatUnitSize(v, orders, sizeof(orders)/sizeof(orders[0])); } QString getDeviceMountedPointPath(const QString &line) { const QStringList items = line.split(" "); if (items.length() > 4) { return items.at(1); } else { return ""; } } QString getFileContent(const QString &filePath) { QFile fd(filePath); QString fileContent = ""; if (fd.open(QFile::ReadOnly)) { fileContent = QLatin1String(fd.readAll()); fd.close(); } return fileContent; } QSet getFileContentsLineByLine(const QString &filePath) { QString fileContent = getFileContent(filePath); return QSet::fromList(fileContent.split("\n")); } ukui-system-monitor/src/renicedialog.h0000644000175000017500000000402613763560717017070 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SELECTWIDGET_H #define SELECTWIDGET_H #include #include #include class QLabel; class QSlider; class QPushButton; #include "../component/mytitlebar.h" class ReniceDialog : public QDialog { Q_OBJECT public: ReniceDialog(const QString &title = "", QWidget *parent = 0); ~ReniceDialog(); void loadData(int nice); void moveCenter(); public slots: void onClose(); signals: void resetReniceValue(int value); protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); private: QVBoxLayout *m_mainLayout = nullptr; MyTitleBar *m_titleBar = nullptr; QHBoxLayout *h_layout = nullptr; QHBoxLayout *tip_layout = nullptr; QHBoxLayout *btn_layout = nullptr; QLabel *m_titleLabel = nullptr; QSlider *m_slider = nullptr; QLabel *m_valueLabel = nullptr; QLabel *m_valueStrLabel = nullptr; QLabel *m_tipTitle = nullptr; QLabel *m_tipLabel = nullptr; QPushButton *m_cancelbtn = nullptr; QPushButton *m_changeBtn = nullptr; QPoint m_dragPosition; //移动的距离 bool m_mousePressed; //按下鼠标左键 }; #endif // SELECTWIDGET_H ukui-system-monitor/src/filesystemlistwidget.h0000644000175000017500000000577713755705142020737 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FILESYSTEMLISTWIDGET_H #define FILESYSTEMLISTWIDGET_H #include "filesystemlistitem.h" //#include "shell/customstyle.h" #include "../shell/macro.h" #include #include #include #include #include class FileSystemListWidget : public QWidget { Q_OBJECT public: FileSystemListWidget(QList toBeDisplayedColumns, QWidget *parent = 0); ~FileSystemListWidget(); void readyToHideScrollbar(); void clearItems(); void addSelectedItems(QList items, bool recordLastItem=true); void clearSelectedItems(bool clearLast=true); void refreshFileSystemItems(QList items); int getItemsTotalHeight(); int getBottomOffset(); int getScrollbarY(); int getScrollbarHeight(); int getTheScrollAreaHeight(); QList getTitleItemsWidths(); int setOffset(int offset); bool mouseAtScrollArea(int x); bool mouseAtTitleArea(int y); void initThemeMode(); void initFontSize(); signals: void rightMouseClickedItem(QPoint pos); void changeColumnVisible(int index, bool visible, QList columnVisible); public slots: void hideScrollbar(); protected: virtual void leaveEvent(QEvent *event); void mouseMoveEvent(QMouseEvent *mouseEvent); void mousePressEvent(QMouseEvent *mouseEvent); void mouseReleaseEvent(QMouseEvent *mouseEvent); void paintEvent(QPaintEvent *); void wheelEvent(QWheelEvent *event); void paintScrollbar(QPainter *painter); void mouseDoubleClickEvent(QMouseEvent *event) override; private: QTimer *m_hideScrollbarTimer = nullptr; FileSystemListItem *m_lastItem = nullptr; QList *m_listItems; QList *m_selectedItems; QList columnTitles; QList m_columnWidths; QList m_columnVisibles; bool m_mouseAtScrollArea; bool m_mouseDragScrollbar; int m_origOffset; int m_offSet; int m_rowHeight; int m_scrollbarWidth; int m_titleHeight; int m_titleHoverColumn; int m_titlePadding; int m_titlePressColumn; float fontSize; QGSettings * qtSettings; QGSettings *fontSettings; QString currentThemeMode; }; #endif // PROCESSLISTWIDGET_H ukui-system-monitor/src/linebandwith.h0000644000175000017500000000226013746753570017113 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LINEBANDWITH_H #define LINEBANDWITH_H #include "QLineEdit" #include "QDateTime" class lineBandwith : public QLineEdit { Q_OBJECT public: explicit lineBandwith(int pid,QWidget *parent = 0); QString new_count(qint64 count ,int pid); private: qint64 count_prev; QDateTime time_prev; QString speedPerSec; QMap countMap; signals: public slots: }; #endif // LINEBANDWITH_H ukui-system-monitor/src/processlistwidget.cpp0000644000175000017500000011703013763560717020554 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processlistwidget.h" #include #include #include #include #include #include #include #include #include #include #include static int number = 0; /** * QT主题 */ #define THEME_QT_SCHEMA "org.ukui.style" #define MODE_QT_KEY "style-name" /* QT图标主题 */ #define ICON_QT_KEY "icon-theme-name" ProcessListWidget::ProcessListWidget(QList toBeDisplayedColumns, QWidget *parent) : QWidget(parent) ,m_titlePadding(10) ,m_titleHeight(40) ,m_rowHeight(29) ,m_offSet(0) ,m_origOffset(0) ,m_scrollbarWidth(10) ,m_titleHoverColumn(-1) ,m_titlePressColumn(-1) ,m_mouseAtScrollArea(false) ,m_mouseDragScrollbar(false) ,fontSettings(nullptr) ,qtSettings(nullptr) { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } initFontSize(); this->m_searchFunc = NULL; this->m_searchText = ""; this->m_lastItem = NULL; this->m_listItems = new QList(); this->m_searchedItems = new QList(); this->m_selectedItems = new QList(); this->m_sortFuncList = new QList(); this->m_isSortList = new QList(); this->m_downArrowPixmap = QPixmap(":/img/down_arrow.png"); this->m_upArrowPixmap = QPixmap(":/img/up_arrow.png"); this->columnTitles << tr("Process Name") << tr("User") << tr("Disk") << tr("CPU") << tr("ID") << tr("Flownet Persec") << tr("Memory") << tr("Priority"); QList widths; widths << 170 << 90 << 80 << 70 << 80 << -1 << 80 << 80;//-1时让该行填充所有剩余空间 QFont font; font.setPixelSize(14);//需要和填充所有剩余空间的那个的文字字体大小一致 font.setPointSize(9) QFontMetrics fm(font); this->m_columnWidths.clear(); for (int i = 0; i < widths.length(); i++) { if (widths[i] == -1) { this->m_columnWidths << widths[i]; } else {//-1时让改行填充所有剩余空间 int maxWidth = fm.width(this->columnTitles[i]) + this->m_titlePadding + m_upArrowPixmap.width() / m_upArrowPixmap.devicePixelRatio() + 2 * 2; this->m_columnWidths << std::max(widths[i], maxWidth); } } this->m_columnVisibles.clear(); for (int i = 0; i < toBeDisplayedColumns.count(); i++) { this->m_columnVisibles.append(toBeDisplayedColumns[i]); } //this->setStyleSheet("border:none;background:rgba(00,00,00,1);"); this->setStyleSheet("{background-color:#000000;}"); //this->setStyleSheet("widget{border:10px solid red;}"); this->setFocus(); initThemeMode(); } void ProcessListWidget::initThemeMode() { if (!qtSettings) { // qWarning() << "Failed to load the gsettings: " << THEME_QT_SCHEMA; return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); repaint(); } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); } void ProcessListWidget::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toInt(); } }); fontSize = fontSettings->get(FONT_SIZE).toInt(); } ProcessListWidget::~ProcessListWidget() { if (this->m_hideScrollbarTimer != NULL) { disconnect(this->m_hideScrollbarTimer,SIGNAL(timeout()),this,SLOT(hideScrollbar())); if(this->m_hideScrollbarTimer->isActive()) { this->m_hideScrollbarTimer->stop(); } delete this->m_hideScrollbarTimer; this->m_hideScrollbarTimer = nullptr; } if(fontSettings) { delete fontSettings; } if(qtSettings) { delete qtSettings; } delete this->m_lastItem; delete this->m_listItems; delete this->m_searchedItems; delete this->m_selectedItems; delete this->m_sortFuncList; delete this->m_isSortList; } void ProcessListWidget::setProcessSortFunctions(QList *list, int currentSortIndex, bool isSort) { this->m_sortFuncList = list; for (int i = 0; i < this->m_sortFuncList->count(); i++) { this->m_isSortList->append(false); } this->m_currentSortIndex = currentSortIndex; this->m_isSort = isSort; } void ProcessListWidget::setSearchFunction(SearchFunction func) { this->m_searchFunc = func; } void ProcessListWidget::addItems(QList items) //每一行进行手动绘制,添加新的进程信息 { this->m_listItems->append(items); QList s_items = this->getSearchedItems(items); this->m_searchedItems->append(s_items); if (this->m_currentSortIndex != -1) { this->sortItemsByColumn(this->m_currentSortIndex, this->m_isSort); } } void ProcessListWidget::clearItems() { qDeleteAll(this->m_listItems->begin(), this->m_listItems->end()); this->m_listItems->clear(); this->m_searchedItems->clear(); } void ProcessListWidget::addSelectedItems(QList items, bool recordLastItem) { this->m_selectedItems->append(items); if (recordLastItem && this->m_selectedItems->count() > 0) { this->m_lastItem = this->m_selectedItems->last(); } } void ProcessListWidget::clearSelectedItems(bool clearLast) { this->m_selectedItems->clear(); if (clearLast) { this->m_lastItem = NULL; } } void ProcessListWidget::refreshItems(QList items) { QList *allItems = new QList(); ProcessListItem *newLastItem = NULL; for (ProcessListItem *item:items) { for (ProcessListItem *selectionItem:*this->m_selectedItems) { if (item->isSameItem(selectionItem)) { allItems->append(item); break; } } } if (this->m_lastItem != NULL) { for (ProcessListItem *item:items) { if (item->isSameItem(this->m_lastItem)) { newLastItem = item; break; } } } clearItems(); this->m_listItems->append(items); QList s_items = this->getSearchedItems(items); this->m_searchedItems->append(s_items); if (this->m_currentSortIndex != -1) { this->sortItemsByColumn(this->m_currentSortIndex, this->m_isSort); } clearSelectedItems(); addSelectedItems(*allItems, false); this->m_lastItem = newLastItem; this->m_offSet = setOffset(this->m_offSet); repaint(); delete allItems; } void ProcessListWidget::doSearch(QString text) { if (text == "" && this->m_searchText != text) { this->m_searchText = text; this->m_searchedItems->clear(); this->m_searchedItems->append(*this->m_listItems); } else { this->m_searchText = text; QList s_items = this->getSearchedItems(*this->m_listItems); this->m_searchedItems->clear(); this->m_searchedItems->append(s_items); } repaint(); } void ProcessListWidget::selectTheFirstItem() { this->m_origOffset = this->m_offSet; clearSelectedItems(); QList items = QList(); items << this->m_searchedItems->first(); addSelectedItems(items); this->m_offSet = 0; repaint(); } void ProcessListWidget::selectTheLastItem() { this->m_origOffset = this->m_offSet; clearSelectedItems(); QList items = QList(); items << this->m_searchedItems->last(); addSelectedItems(items); this->m_offSet = getBottomOffset(); repaint(); } void ProcessListWidget::selectThePrevItem(int offset) { this->m_origOffset = this->m_offSet; if (this->m_selectedItems->empty()) { selectTheFirstItem(); } else { int firstIndex = this->m_searchedItems->count(); for (ProcessListItem *item:*this->m_selectedItems) { int index = this->m_searchedItems->indexOf(item); if (index < firstIndex) { firstIndex = index; } } if (firstIndex != -1) { firstIndex = std::max(0, firstIndex - offset); clearSelectedItems(); QList items = QList(); items << (*this->m_searchedItems)[firstIndex]; addSelectedItems(items); int itemIndex = firstIndex - 1; int itemOffset = setOffset(itemIndex * this->m_rowHeight + this->m_titleHeight); if ((this->m_offSet / this->m_rowHeight) > itemIndex) { this->m_offSet = itemOffset; } repaint(); } } } void ProcessListWidget::selectTheNextItem(int offset) { this->m_origOffset = this->m_offSet; if (this->m_selectedItems->empty()) { selectTheFirstItem(); } else { int lastIndex = 0; for (ProcessListItem *item:*this->m_selectedItems) { int index = this->m_searchedItems->indexOf(item); if (index > lastIndex) { lastIndex = index; } } if (lastIndex != -1) { lastIndex = std::min(this->m_searchedItems->count() - 1, lastIndex + offset); clearSelectedItems(false); QList items = QList(); items << (*this->m_searchedItems)[lastIndex]; addSelectedItems(items); int itemIndex = lastIndex + 1; int itemOffset = setOffset(itemIndex * this->m_rowHeight - rect().height() + this->m_titleHeight); if (((this->m_offSet + getTheScrollAreaHeight()) / this->m_rowHeight) < itemIndex) { this->m_offSet = itemOffset; } repaint(); } } } void ProcessListWidget::shiftToHomeItem() { if (this->m_selectedItems->empty()) { selectTheFirstItem(); } else { int lastSelectionIndex = this->m_searchedItems->indexOf(this->m_lastItem); shiftToSelectedItems(0, lastSelectionIndex); this->m_offSet = 0; repaint(); } } void ProcessListWidget::shiftToEndItem() { if (this->m_selectedItems->empty()) { selectTheLastItem(); } else { shiftToSelectedItems(this->m_searchedItems->indexOf(this->m_lastItem), this->m_searchedItems->count() - 1); this->m_offSet = getBottomOffset(); repaint(); } } void ProcessListWidget::shiftToPrevItem(int offset) { this->m_origOffset = this->m_offSet; if (this->m_selectedItems->empty()) { selectTheFirstItem(); } else { int firstIndex = this->m_searchedItems->count(); int lastIndex = 0; for (ProcessListItem *item : *this->m_selectedItems) { int index = this->m_searchedItems->indexOf(item); if (index < firstIndex) { firstIndex = index; } if (index > lastIndex) { lastIndex = index; } } if (firstIndex != -1) { int lastSelectionIndex = this->m_searchedItems->indexOf(this->m_lastItem); int selectionStartIndex, selectionEndIndex; if (lastIndex == lastSelectionIndex) { selectionStartIndex = std::max(0, firstIndex - offset); selectionEndIndex = lastSelectionIndex; } else { selectionStartIndex = firstIndex; selectionEndIndex = std::max(0, lastIndex - offset); } shiftToSelectedItems(selectionStartIndex, selectionEndIndex); if (this->m_offSet / this->m_rowHeight >= selectionStartIndex) { this->m_offSet = setOffset((selectionStartIndex - 1) * this->m_rowHeight + this->m_titleHeight); } repaint(); } } } void ProcessListWidget::shiftToNextItem(int offset) { this->m_origOffset = this->m_offSet; if (this->m_selectedItems->empty()) { selectTheFirstItem(); } else { int firstIndex = this->m_searchedItems->count(); int lastIndex = 0; for (ProcessListItem *item:*this->m_selectedItems) { int index = this->m_searchedItems->indexOf(item); if (index < firstIndex) { firstIndex = index; } if (index > lastIndex) { lastIndex = index; } } if (firstIndex != -1) { int lastSelectionIndex = this->m_searchedItems->indexOf(this->m_lastItem); int selectionStartIndex, selectionEndIndex; if (firstIndex == lastSelectionIndex) { selectionStartIndex = firstIndex; selectionEndIndex = std::min(this->m_searchedItems->count() - 1, lastIndex + offset); } else { selectionStartIndex = std::min(this->m_searchedItems->count() - 1, firstIndex + offset); selectionEndIndex = lastIndex; } shiftToSelectedItems(selectionStartIndex, selectionEndIndex); if ((this->m_offSet + rect().height()) / this->m_rowHeight <= selectionEndIndex + 1) { this->m_offSet = setOffset((selectionEndIndex + 1) * this->m_rowHeight + this->m_titleHeight - rect().height()); } repaint(); } } } void ProcessListWidget::shiftToSelectedItems(int start, int end) { clearSelectedItems(false); QList items = QList(); int index = 0; for (ProcessListItem *item:*this->m_searchedItems) { if (index >= start && index <= end) { items << item; } index++; } addSelectedItems(items, false); } void ProcessListWidget::leaveEvent(QEvent * event) { hideScrollbar(); QWidget::leaveEvent(event); } void ProcessListWidget::hideScrollbar() { this->m_mouseAtScrollArea = false; this->m_origOffset = this->m_offSet; repaint(); } void ProcessListWidget::keyPressEvent(QKeyEvent *keyEvent) { if (keyEvent->key() == Qt::Key_Up) { if (keyEvent->modifiers() == Qt::ShiftModifier) shiftToPrevItem(1); else selectThePrevItem(1); } else if (keyEvent->key() == Qt::Key_Down) { if (keyEvent->modifiers() == Qt::ShiftModifier) shiftToNextItem(1); else selectTheNextItem(1); } else if (keyEvent->key() == Qt::Key_Home) { if (keyEvent->modifiers() == Qt::ControlModifier) { this->m_offSet = 0; repaint(); } else if (keyEvent->modifiers() == Qt::ShiftModifier) { shiftToHomeItem(); } else { selectTheFirstItem(); } } else if (keyEvent->key() == Qt::Key_End) { if (keyEvent->modifiers() == Qt::ControlModifier) { this->m_offSet = getBottomOffset(); repaint(); } else if (keyEvent->modifiers() == Qt::ShiftModifier) { shiftToEndItem(); } else { selectTheLastItem(); } } else if (keyEvent->key() == Qt::Key_PageUp) { if (keyEvent->modifiers() == Qt::ControlModifier) { this->m_offSet = setOffset(this->m_offSet - getTheScrollAreaHeight()); repaint(); } else if (keyEvent->modifiers() == Qt::ShiftModifier) { shiftToPrevItem(getTheScrollAreaHeight() / this->m_rowHeight); } else { selectThePrevItem(getTheScrollAreaHeight() / this->m_rowHeight); } } else if (keyEvent->key() == Qt::Key_PageDown) { if (keyEvent->modifiers() == Qt::ControlModifier) { this->m_offSet = setOffset(this->m_offSet + getTheScrollAreaHeight()); repaint(); } else if (keyEvent->modifiers() == Qt::ShiftModifier) { shiftToNextItem(getTheScrollAreaHeight() / this->m_rowHeight); } else { selectTheNextItem(getTheScrollAreaHeight() / this->m_rowHeight); } } } void ProcessListWidget::mouseMoveEvent(QMouseEvent *mouseEvent) { if (this->m_mouseDragScrollbar) { this->m_offSet = setOffset((mouseEvent->y() - getScrollbarHeight() / 2 - this->m_titleHeight) / (getTheScrollAreaHeight() * 1.0) * this->getItemsTotalHeight()); repaint(); } else if (mouseAtScrollArea(mouseEvent->x()) != this->m_mouseAtScrollArea) { this->m_mouseAtScrollArea = mouseAtScrollArea(mouseEvent->x()); repaint(); } else { bool isTitleArea = mouseAtTitleArea(mouseEvent->y()); if (isTitleArea) { int currentHoverIndex = -1; if (this->m_sortFuncList->count() != 0 && this->m_sortFuncList->count() == this->columnTitles.count() && this->m_isSortList->count() == this->columnTitles.count()) { QList titleItemsWidths = getTitleItemsWidths(); int counter = 0; int pos_X = 0; for (int t_width : titleItemsWidths) { if (t_width > 0) { if (mouseEvent->x() > pos_X && mouseEvent->x() < pos_X + t_width) { currentHoverIndex = counter; break; } pos_X += t_width; } counter++; } } if (currentHoverIndex != this->m_titleHoverColumn) { this->m_titleHoverColumn = currentHoverIndex; repaint(); } } } } void ProcessListWidget::mousePressEvent(QMouseEvent *mouseEvent) { setFocus(); bool isTitleArea = mouseAtTitleArea(mouseEvent->y()); bool isScrollArea = mouseAtScrollArea(mouseEvent->x()); if (isTitleArea) {//点击列表的标题栏区域 if (mouseEvent->button() == Qt::LeftButton) { if (this->m_sortFuncList->count() != 0 && this->m_sortFuncList->count() == this->columnTitles.count() && this->m_isSortList->count() == this->columnTitles.count()) { QList titleItemsWidths = getTitleItemsWidths(); int counter = 0; int posX = 0; for (int t_width : titleItemsWidths) { if (t_width > 0) { if (mouseEvent->x() > posX && mouseEvent->x() < posX + t_width) { if (counter != this->m_currentSortIndex) { (*this->m_isSortList)[counter] = true; } else { (*this->m_isSortList)[counter] = !(*this->m_isSortList)[counter]; } this->m_currentSortIndex = counter; this->m_isSort = (*this->m_isSortList)[counter]; emit this->changeSortStatus(this->m_currentSortIndex, this->m_isSort); this->sortItemsByColumn(counter, (*this->m_isSortList)[counter]); if (counter != this->m_titlePressColumn) { this->m_titlePressColumn = counter; } repaint(); break; } posX += t_width; } counter++; } } } else if (mouseEvent->button() == Qt::RightButton) { if (m_columnVisibles.count() == this->columnTitles.count()) { QMenu *menu = new QMenu(); menu->setObjectName("MonitorMenu"); for (int i = 0; i < m_columnVisibles.count(); i++) { if (i != 0) {//让第一行总是显示,不可以设置显示或者不显示,其他行可以设置 QAction *action = new QAction(menu); action->setText(this->columnTitles[i]); action->setCheckable(true); action->setChecked(m_columnVisibles[i]); connect(action, &QAction::triggered, this, [this, action, i] { m_columnVisibles[i] = !m_columnVisibles[i]; emit this->changeColumnVisible(i, m_columnVisibles[i], m_columnVisibles); repaint(); }); menu->addAction(action); } } menu->exec(this->mapToGlobal(mouseEvent->pos())); delete menu; } } } else if (isScrollArea) {//点击滚动条区域 int barHeight = getScrollbarHeight(); int barY = getScrollbarY(); if (mouseEvent->y() > barY && mouseEvent->y() < barY + barHeight) { this->m_mouseDragScrollbar = true; } else { this->m_offSet = setOffset((mouseEvent->y() - barHeight / 2 - this->m_titleHeight) / (getTheScrollAreaHeight() * 1.0) * this->getItemsTotalHeight()); repaint(); } } else { int pressedItemIndex = (this->m_offSet + mouseEvent->y() - this->m_titleHeight) / this->m_rowHeight; if (pressedItemIndex >= this->m_searchedItems->count()) { clearSelectedItems(); repaint(); } else { if (mouseEvent->button() == Qt::LeftButton) { if (pressedItemIndex < this->m_searchedItems->count()) { if (mouseEvent->modifiers() == Qt::ControlModifier) { ProcessListItem *item = (*this->m_searchedItems)[pressedItemIndex]; if (this->m_selectedItems->contains(item)) { this->m_selectedItems->removeOne(item); } else { QList items = QList(); items << item; addSelectedItems(items); } } else if ((mouseEvent->modifiers() == Qt::ShiftModifier) && !this->m_selectedItems->empty()) { int lastSelectionIndex = this->m_searchedItems->indexOf(this->m_lastItem); int selectionStartIndex = std::min(pressedItemIndex, lastSelectionIndex); int selectionEndIndex = std::max(pressedItemIndex, lastSelectionIndex); shiftToSelectedItems(selectionStartIndex, selectionEndIndex); } else { clearSelectedItems(); QList items = QList(); items << (*this->m_searchedItems)[pressedItemIndex]; addSelectedItems(items); } repaint(); } } else if (mouseEvent->button() == Qt::RightButton) { ProcessListItem *pressItem = (*this->m_searchedItems)[pressedItemIndex]; bool pressInSelectionArea = false; for (ProcessListItem *item : *this->m_selectedItems) { if (item == pressItem) { pressInSelectionArea = true; break; } } if (!pressInSelectionArea && pressedItemIndex < this->m_searchedItems->length()) { clearSelectedItems(); QList items = QList(); items << (*this->m_searchedItems)[pressedItemIndex]; addSelectedItems(items); repaint(); } if (this->m_selectedItems->length() > 0) { emit this->rightMouseClickedItems(this->mapToGlobal(mouseEvent->pos()), *this->m_selectedItems); } } } } } void ProcessListWidget::mouseReleaseEvent(QMouseEvent *) { if (this->m_mouseDragScrollbar) { this->m_mouseDragScrollbar = false; repaint(); } else { if (this->m_titlePressColumn != -1) { this->m_titlePressColumn = -1; repaint(); } } } void ProcessListWidget::wheelEvent(QWheelEvent *event) { if (event->orientation() == Qt::Vertical) { this->m_origOffset = this->m_offSet; qreal scrollStep = event->angleDelta().y() / 100.0; this->m_offSet = setOffset(this->m_offSet - scrollStep * this->m_rowHeight); repaint(); } event->accept(); } void ProcessListWidget::paintEvent(QPaintEvent *) { // QPainter painter(this); // painter.setRenderHint(QPainter::Antialiasing, true); // QList titleItemsWidths = getTitleItemsWidths(); // //painter.setOpacity(1); // painter.setPen(Qt::blue); // painter.setBrush(QBrush(QColor(0xff,0xff,0xff,0xFF))); // int penWidth = 1; // QPainterPath framePath; // framePath.addRoundedRect(QRect(rect().x()+5, rect().y()+5, rect().width() /*- penWidth * 2*/, rect().height()/* - penWidth * 2*/), 0, 0);//背景弧度 // painter.setClipPath(framePath); // painter.drawRect(this->rect()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QList titleItemsWidths = getTitleItemsWidths(); int penWidth = 0; QPainterPath framePath; framePath.addRoundedRect(QRect(rect().x() + penWidth, rect().y() + penWidth, rect().width() - penWidth * 2, rect().height() - penWidth * 2), 0, 0);//背景弧度 painter.setClipPath(framePath); // draw border QPainterPath path; path.addRoundedRect(rect().adjusted(2, 2, -2, -2), 0, 0); painter.setClipRect(QRect(), Qt::NoClip); // QPen pen2(QColor(Qt::red)); // pen2.setWidth(1); // painter.setPen(pen2); // painter.drawPath(path); painter.setPen(Qt::NoPen); //painter.fillRect(this->rect(),QColor(0,0,FF,0x20)); painter.setOpacity(0.05); //framePath.setFillRule(Qt::ImhNone); //标题的背景 if (this->m_titleHeight > 0) { QPainterPath titlePath; titlePath.addRect(QRectF(rect().x(), rect().y(), rect().width(), this->m_titleHeight)); //painter.setOpacity(1); painter.fillPath(titlePath, QColor("palette(windowText)")); //painter.fillPath(titlePath, QColor("#CC00FF")); } int title_Y = 0; int title_Height = 0; if (this->m_titleHeight > 0) { int counter = 0; int posX = 0; for (int itemWidth:titleItemsWidths) { if (itemWidth > 0) { //标题文字左上方的排序箭头图标 if (this->m_currentSortIndex == counter) { if(counter == 0 || counter == 5) { painter.setOpacity(1); if (this->m_isSort) { painter.drawPixmap(QPoint(rect().x() + posX + 100, rect().y() + 20), m_downArrowPixmap); } else { painter.drawPixmap(QPoint(rect().x() + posX + 100, rect().y() + 20), m_upArrowPixmap); } } else { painter.setOpacity(1); if (this->m_isSort) { painter.drawPixmap(QPoint(rect().x() + posX + 60, rect().y() + 20), m_downArrowPixmap); } else { painter.drawPixmap(QPoint(rect().x() + posX + 60, rect().y() + 20), m_upArrowPixmap); } } } //标题文字 painter.setOpacity(0.57); QFont font = painter.font(); // font.setPointSize(10); font.setPixelSize(fontSize); painter.setFont(font); if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { painter.setPen(QPen(QColor("#000000"))); } else if (currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { painter.setPen(QPen(QColor("#ffffff"))); } else { painter.setPen(QPen(QColor("#000000"))); } // if (this->columnTitles[counter] == tr("Process Name") || this->columnTitles[counter] == tr("Flownet Persec")) if (this->columnTitles[counter] == tr("Process Name")) painter.drawText(QRect(posX + this->m_titlePadding, 0, itemWidth, this->m_titleHeight), Qt::AlignCenter, this->columnTitles[counter]); else painter.drawText(QRect(posX, 0, itemWidth - this->m_titlePadding, this->m_titleHeight), Qt::AlignCenter, this->columnTitles[counter]); //水平下划线 // painter.setOpacity(0.8); // QPainterPath h_separatorPath; // h_separatorPath.addRect(QRectF(posX, rect().y() + this->m_titleHeight - 1, itemWidth, 1)); // painter.fillPath(h_separatorPath, QColor("#e0e0e0")); if (counter < titleItemsWidths.size()) {//垂直分割线 QPainterPath v_separatorPath; v_separatorPath.addRect(QRectF(rect().x() + posX - 1, rect().y() + 10, 1, this->m_titleHeight - 15)); painter.setOpacity(0.2); painter.fillPath(v_separatorPath, palette().color(QPalette::WindowText)); } posX += itemWidth; } counter++; } title_Y += this->m_titleHeight; title_Height += this->m_titleHeight; } //去掉列表标题栏后的列表显示区域的背景 painter.setOpacity(1); QPainterPath backgroundPath; backgroundPath.addRect(QRectF(rect().x(), rect().y() + this->m_titleHeight, rect().width(), rect().height() - this->m_titleHeight)); // painter.fillPath(backgroundPath, QColor("#CC00FF")); //进程信息 QPainterPath scrollAreaPath; scrollAreaPath.addRect(QRectF(rect().x(), rect().y() + this->m_titleHeight, rect().width(), getTheScrollAreaHeight() - 5)); int rowCounter = 0; for (ProcessListItem *item:*this->m_searchedItems) { if (rowCounter > ((this->m_offSet - this->m_rowHeight) / this->m_rowHeight)) { QPainterPath itemPath; itemPath.addRect(QRect(0, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, rect().width(), this->m_rowHeight)); painter.setClipPath((framePath.intersected(scrollAreaPath)).intersected(itemPath)); bool isSelect = this->m_selectedItems->contains(item); painter.save(); // qDebug()<<"number is ------>"<drawBackground(QRect(0, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, rect().width(), this->m_rowHeight), &painter, rowCounter, isSelect ,currentThemeMode); painter.restore(); int columnCounter = 0; int columnTitleX = 0; for (int titleItemWidth : titleItemsWidths) { if (titleItemWidth > 0) { painter.save(); if (columnCounter < titleItemsWidths.size() - 1) item->drawForeground(QRect(columnTitleX, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, titleItemWidth, this->m_rowHeight), &painter, columnCounter, rowCounter, isSelect, true); else item->drawForeground(QRect(columnTitleX, title_Y + rowCounter * this->m_rowHeight - this->m_offSet, titleItemWidth, this->m_rowHeight), &painter, columnCounter, rowCounter, isSelect, false); painter.restore(); columnTitleX += titleItemWidth; } columnCounter++; } title_Height += this->m_rowHeight; if (title_Height > rect().height()) { break; } } rowCounter++; } painter.setClipPath(framePath); //没有搜索结果时绘制提示文字 if (this->m_searchText != "" && this->m_searchedItems->size() == 0) { painter.setOpacity(1); painter.setPen(QPen(palette().color(QPalette::WindowText))); QFont font = painter.font() ; font.setPointSize(22); painter.setFont(font); painter.drawText(QRect(rect().x(), rect().y() + this->m_titleHeight, rect().width(), rect().height() - this->m_titleHeight), Qt::AlignCenter, tr("No search result")); } //背景 // QPen framePen; // framePen.setColor(QColor("#F5F5F5")); // painter.setPen(framePen); painter.setOpacity(0.2); // painter.drawPath(framePath); //垂直滚动条 if (this->m_mouseAtScrollArea) { paintScrollbar(&painter); } else/* if (this->m_origOffset != this->m_offSet) */{ paintScrollbar(&painter); readyToHideScrollbar(); } } void ProcessListWidget::paintScrollbar(QPainter *painter) { if (this->getItemsTotalHeight() > getTheScrollAreaHeight()) { qreal opacitry = 0; if (this->m_mouseDragScrollbar) { opacitry = 0.8; } else { if (this->m_mouseAtScrollArea) opacitry = 0.7; else opacitry = 0.5; } int barWidth = (this->m_mouseAtScrollArea || this->m_mouseDragScrollbar) ? this->m_scrollbarWidth : 6; int barY = getScrollbarY(); int barHeight = getScrollbarHeight(); painter->setOpacity(opacitry); QPainterPath path; path.addRoundedRect( QRectF(rect().x() + rect().width() - barWidth - 4, barY + 2, barWidth, barHeight - 2 * 2), 2, 2);//2 is radius painter->fillPath(path, QColor("#808080")); QPen pen; pen.setColor(QColor("#808080")); pen.setWidth(1); painter->setOpacity(0); painter->setPen(pen); painter->drawPath(path); } } QList ProcessListWidget::getTitleItemsWidths() { QList titleItemsWidths; if (this->m_columnWidths.length() > 0) { if (this->m_columnWidths.contains(-1)) { for (int i = 0; i < this->m_columnWidths.count(); i++) { if (this->m_columnWidths[i] != -1) { if (m_columnVisibles[i]) { titleItemsWidths << this->m_columnWidths[i]; } else { titleItemsWidths << 0; } } else { if (m_columnVisibles[i]) { int totalWidth = 0; for (int j = 0; j < this->m_columnWidths.count(); j++) { if (this->m_columnWidths[j] != -1 && m_columnVisibles[j]) { totalWidth += this->m_columnWidths[j]; } } titleItemsWidths << rect().width() - totalWidth; } else { titleItemsWidths << 0; } } } } else { for (int i = 0; i < this->m_columnWidths.count(); i++) { if (m_columnVisibles[i]) { titleItemsWidths << this->m_columnWidths[i]; } else { titleItemsWidths << 0; } } } } else { titleItemsWidths << rect().width(); } return titleItemsWidths; } bool ProcessListWidget::mouseAtScrollArea(int x) { return (x > rect().x() + rect().width() - this->m_scrollbarWidth) && (x < rect().x() + rect().width()); } bool ProcessListWidget::mouseAtTitleArea(int y) { return (y > rect().y() && y < rect().y() + this->m_titleHeight); } int ProcessListWidget::setOffset(int offset) { return std::max(0, std::min(offset, getBottomOffset())); } int ProcessListWidget::getItemsTotalHeight() { return m_searchedItems->count() * m_rowHeight; } int ProcessListWidget::getTheScrollAreaHeight() { return this->rect().height() - this->m_titleHeight; } int ProcessListWidget::getScrollbarY() { return static_cast((this->m_offSet / (this->getItemsTotalHeight() * 1.0)) * getTheScrollAreaHeight() + this->m_titleHeight); } int ProcessListWidget::getScrollbarHeight() { return std::max(static_cast(getTheScrollAreaHeight() / (this->getItemsTotalHeight() * 1.0) * rect().height()), 80);//30 is min height } QList ProcessListWidget::getSearchedItems(QList items) { if (m_searchText == "" || m_searchFunc == NULL) { return items; } else { QList *search_items = new QList(); for (ProcessListItem *item : items) { if (m_searchFunc(item, m_searchText)) { search_items->append(item); } } return *search_items; } } int ProcessListWidget::getBottomOffset() { int itemsHeight = this->getItemsTotalHeight(); if (itemsHeight > rect().height() - this->m_titleHeight) { return this->getItemsTotalHeight() - rect().height() + this->m_titleHeight; } else { return 0; } } void ProcessListWidget::sortItemsByColumn(int column, bool isSort) { if (m_sortFuncList->count() != 0 && m_sortFuncList->count() == columnTitles.count() && m_isSortList->count() == columnTitles.count()) { qSort(m_searchedItems->begin(), m_searchedItems->end(), [&](const ProcessListItem *item1, const ProcessListItem *item2) { return (*m_sortFuncList)[column](item1, item2, isSort); }); } } void ProcessListWidget::readyToHideScrollbar() { if (this->m_hideScrollbarTimer) { if (this->m_hideScrollbarTimer->isActive()) this->m_hideScrollbarTimer->stop(); } else { this->m_hideScrollbarTimer = new QTimer(); this->m_hideScrollbarTimer->setSingleShot(true); connect(this->m_hideScrollbarTimer, SIGNAL(timeout()), this, SLOT(hideScrollbar())); } this->m_hideScrollbarTimer->start(2000); } ukui-system-monitor/src/filesystemdata.h0000644000175000017500000000332113746753504017455 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FILESYSTEMDATA_H #define FILESYSTEMDATA_H #include #include class FileSystemData : public QObject { Q_OBJECT public: explicit FileSystemData(QObject *parent = 0); const QString deviceName() const; void setDevName(const QString &name); const QString mountDir() const; const QString diskType() const; const QString totalCapacity() const; const QString freeCapacity() const; const QString availCapacity() const; const QString usedCapactiy() const; const int usedPercentage(); void updateDiskInfo(QString mountDir, QString diskType, QString totalCapacity, QString freeCapacity, QString availCapacity, QString usedCapactiy, int percentage); private: QString m_devName; QString m_mountDir; QString m_diskType; QString m_totalCapacity; QString m_freeCapacity; QString m_availCapacity; QString m_usedCapactiy; int m_percentage; }; #endif // FILESYSTEMDATA_H ukui-system-monitor/src/processworker.cpp0000644000175000017500000002357213764351367017715 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "processworker.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using std::string; ProcessWorker::UserMap ProcessWorker::users; ProcessWorker::List ProcessWorker::all; std::map ProcessWorker::cpu_times; static bool init; static bool is_running; static size_t e_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) { char *c, *ffmt, *ff; size_t ret; ffmt = g_strdup(fmt); ff = ffmt; while ((c = strstr(ff, "%l")) != NULL) { c[1] = 'I'; ff = c; } ff = ffmt; while ((c = strstr(ff, "%k")) != NULL) { c[1] = 'H'; ff = c; } ret = strftime(s, max, ffmt, tm); g_free(ffmt); return ret; } static size_t e_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) { char buf[10]; char *sp; char *ffmt; size_t ret; if (strstr(fmt, "%p")==NULL && strstr(fmt, "%P")==NULL) { /* No AM/PM involved - can use the fmt string directly */ ret=e_strftime(s, max, fmt, tm); } else { /* Get the AM/PM symbol from the locale */ e_strftime (buf, 10, "%p", tm); if (buf[0]) { /** * AM/PM have been defined in the locale * so we can use the fmt string directly **/ ret=e_strftime(s, max, fmt, tm); } else { /** * No AM/PM defined by locale * must change to 24 hour clock **/ ffmt=g_strdup(fmt); for (sp=ffmt; (sp=strstr(sp, "%l")); sp++) { /** * Maybe this should be 'k', but I have never * seen a 24 clock actually use that format **/ sp[1]='H'; } for (sp=ffmt; (sp=strstr(sp, "%I")); sp++) { sp[1]='H'; } ret=e_strftime(s, max, ffmt, tm); g_free(ffmt); } } return(ret); } static size_t e_utf8_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) { size_t sz, ret; char *locale_fmt, *buf; locale_fmt = g_locale_from_utf8(fmt, -1, NULL, &sz, NULL); if (!locale_fmt) return 0; ret = e_strftime_fix_am_pm(s, max, locale_fmt, tm); if (!ret) { g_free (locale_fmt); return 0; } buf = g_locale_to_utf8(s, ret, NULL, &sz, NULL); if (!buf) { g_free (locale_fmt); return 0; } if (sz >= max) { char *tmp = buf + max - 1; tmp = g_utf8_find_prev_char(buf, tmp); if (tmp) sz = tmp - buf; else sz = 0; } memcpy(s, buf, sz); s[sz] = '\0'; g_free(locale_fmt); g_free(buf); return sz; } static char *format_start_datetime_for_display(time_t date) { time_t nowdate = time(NULL); time_t yesdate; struct tm then, now, yesterday; char buf[26]; gboolean done = FALSE; if (date == 0) return g_strdup ("?"); localtime_r (&date, &then); localtime_r (&nowdate, &now); if (then.tm_mday == now.tm_mday && then.tm_mon == now.tm_mon && then.tm_year == now.tm_year) { e_utf8_strftime_fix_am_pm (buf, 26, _("Today %l:%M %p"), &then); done = TRUE; } if (!done) { yesdate = nowdate - 60 * 60 * 24; localtime_r (&yesdate, &yesterday); if (then.tm_mday == yesterday.tm_mday && then.tm_mon == yesterday.tm_mon && then.tm_year == yesterday.tm_year) { e_utf8_strftime_fix_am_pm (buf, 26, _("Yesterday %l:%M %p"), &then); done = TRUE; } } if (!done) { int i; for (i = 2; i < 7; i++) { yesdate = nowdate - 60 * 60 * 24 * i; localtime_r (&yesdate, &yesterday); if (then.tm_mday == yesterday.tm_mday && then.tm_mon == yesterday.tm_mon && then.tm_year == yesterday.tm_year) { e_utf8_strftime_fix_am_pm (buf, 26, _("%a %l:%M %p"), &then); done = TRUE; break; } } } if (!done) { if (then.tm_year == now.tm_year) { e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %l:%M %p"), &then); } else { e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %Y"), &then); } } return g_strdup (buf); } static void get_process_name (ProcessWorker *info, const gchar *cmd, const GStrv args) { if (args) { // look for /usr/bin/very_long_name // and also /usr/bin/interpreter /usr/.../very_long_name // which may have use prctl to alter 'cmd' name for (int i = 0; i != 2 && args[i]; ++i) { char* basename; basename = g_path_get_basename(args[i]); if (g_str_has_prefix(basename, cmd)) { info->name = basename; return; } g_free(basename); } } info->name = g_strdup(cmd); // qDebug()<<"process name: "<name; } static void get_process_systemd_info(ProcessWorker *info) { // uid_t uid; if (!init) { if (access("/run/systemd/seats/", F_OK) >= 0) { is_running = true; } init = true; } if (is_running) { free(info->unit); info->unit = NULL; sd_pid_get_unit(info->pid, &info->unit); free(info->session); info->session = NULL; sd_pid_get_session(info->pid, &info->session); free(info->seat); info->seat = NULL; if (info->session != NULL) sd_session_get_seat(info->session, &info->seat); // if (sd_pid_get_owner_uid(info->pid, &uid) >= 0) // info->owner = info->lookup_user(uid); // else // info->owner = ""; } } ProcessWorker::ProcessWorker(pid_t pid, gint cpus, guint64 cpu_time, QString flownet_persec) : tooltip(NULL), name(NULL), arguments(NULL), // security_context(NULL), // cgroup_name(NULL), unit(NULL), session(NULL), seat(NULL), pid(pid), uid(-1), mem(0UL), status(0U), pcpu(0U), nice(0), num_cpus(cpus), cpu_total_time(cpu_time), frequency(0U), flownet_persec(flownet_persec) { this->setProcData(); } ProcessWorker::~ProcessWorker() { g_free(this->name); g_free(this->tooltip); g_free(this->arguments); // g_free(this->security_context); // g_free(this->cgroup_name); g_free(this->unit); g_free(this->session); g_free(this->seat); } void ProcessWorker::setProcData() { //init ProcessWorker * const info = this; // glibtop_proc_io procio; glibtop_proc_state procstate; glibtop_proc_time proctime; glibtop_proc_args procargs; gchar** args; glibtop_get_proc_state(&procstate, pid); // glibtop_get_proc_io(&procio,pid); glibtop_get_proc_time(&proctime, pid); args = glibtop_get_proc_argv(&procargs, pid, 0); get_process_name(info, procstate.cmd, static_cast(args)); std::string tooltip = make_string(g_strjoinv(" ", args)); if (tooltip.empty()) tooltip = procstate.cmd; info->tooltip = g_markup_escape_text(tooltip.c_str(), -1); info->arguments = g_strescape(tooltip.c_str(), "\\\""); g_strfreev(args); guint64 cpu_time = proctime.rtime; std::map::iterator it(ProcessWorker::cpu_times.find(pid)); if (it != ProcessWorker::cpu_times.end()) { if (proctime.rtime >= it->second) cpu_time = it->second; } info->cpu_time = cpu_time; info->start_time = proctime.start_time; // get_process_selinux_context (info); // info->cgroup_name = NULL; // get_process_cgroup_info(info); info->unit = info->session = info->seat = NULL; get_process_systemd_info(info); } ProcessWorker* ProcessWorker::find(pid_t pid) { Iterator it(ProcessWorker::all.find(pid)); return (it == ProcessWorker::all.end() ? NULL : it->second); } std::string ProcessWorker::lookup_user(guint uid) { typedef std::pair Pair; ProcessWorker::UserMap::value_type hint(uid, ""); Pair p(ProcessWorker::users.insert(hint)); if (p.second) { struct passwd* pwd; pwd = getpwuid(uid); if (pwd && pwd->pw_name) p.first->second = pwd->pw_name; else { char username[16]; g_sprintf(username, "%u", uid); p.first->second = username; } } return p.first->second; } void ProcessWorker::set_user(guint uid) { if (G_LIKELY(this->uid == uid)) return; this->uid = uid; this->user = lookup_user(uid); } ukui-system-monitor/src/framelessExtended/0000755000175000017500000000000013746753504017731 5ustar fengfengukui-system-monitor/src/framelessExtended/framelesshandle.h0000644000175000017500000000266213746753504023245 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FRAMELESSHANDLE_H #define FRAMELESSHANDLE_H #include class QWidget; class FramelessHandlePrivate; class FramelessHandle : public QObject { Q_OBJECT public: explicit FramelessHandle(QObject *parent = 0); ~FramelessHandle(); void activateOn(QWidget * topLevelWidget); void setWidgetResizable(bool resizable); void setWidgetMovable(bool movable); void setBorderWidget(uint width); bool currentWidgetResizable(); bool currentWidgetMovable(); uint currentBorderWidth(); protected: virtual bool eventFilter(QObject *watched, QEvent *event); private: FramelessHandlePrivate * fpri; }; #endif // FRAMELESSHANDLE_H ukui-system-monitor/src/framelessExtended/framelesshandle.cpp0000644000175000017500000000535413746753504023601 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "framelesshandle.h" #include #include "framelesshandleprivate.h" #include "widgethandlerealize.h" FramelessHandle::FramelessHandle(QObject *parent) : QObject(parent), fpri(new FramelessHandlePrivate()) { fpri->widgetResizable = true; fpri->widgetMovable = true; } FramelessHandle::~FramelessHandle() { QList widgets = fpri->widgethandleHash.keys(); for (int i = 0; i < widgets.size(); i++){ delete fpri->widgethandleHash.take(widgets[i]); } delete fpri; } bool FramelessHandle::eventFilter(QObject *watched, QEvent *event){ switch (event->type()){ case QEvent::MouseMove: case QEvent::HoverMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::Leave:{ WidgetHandleRealize * widgethandleobj = fpri->widgethandleHash.value(static_cast(watched)); if (widgethandleobj){ widgethandleobj->handleWidgetEvent(event); return true; } } default: break; } return QObject::eventFilter(watched, event); } void FramelessHandle::activateOn(QWidget *topLevelWidget){ if (!fpri->widgethandleHash.contains(topLevelWidget)){ WidgetHandleRealize * widgethandleobj = new WidgetHandleRealize(fpri, topLevelWidget); fpri->widgethandleHash.insert(topLevelWidget, widgethandleobj); topLevelWidget->installEventFilter(this); } } void FramelessHandle::setWidgetResizable(bool resizable){ fpri->widgetResizable = resizable; } void FramelessHandle::setWidgetMovable(bool movable){ fpri->widgetMovable = movable; } void FramelessHandle::setBorderWidget(uint width){ if (width > 0) CursorPosCalculator::borderWidth = width; } bool FramelessHandle::currentWidgetResizable(){ return fpri->widgetResizable; } bool FramelessHandle::currentWidgetMovable(){ return fpri->widgetMovable; } uint FramelessHandle::currentBorderWidth(){ return CursorPosCalculator::borderWidth; } ukui-system-monitor/src/framelessExtended/widgethandlerealize.cpp0000644000175000017500000001653313746753504024460 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "widgethandlerealize.h" #include #include #include #include WidgetHandleRealize::WidgetHandleRealize(FramelessHandlePrivate *_fpri, QWidget * pTopLevelWidget ) { fpri = _fpri; widgetInAction = pTopLevelWidget; leftBtnPressed = false; cursorShapeChanged = false; currentWindowFlags = widgetInAction->windowFlags(); // widgetInAction->setMouseTracking(true); widgetInAction->setAttribute(Qt::WA_Hover, true); } WidgetHandleRealize::~WidgetHandleRealize() { widgetInAction->setMouseTracking(false); widgetInAction->setWindowFlags(currentWindowFlags); widgetInAction->setAttribute(Qt::WA_Hover, false); } QWidget * WidgetHandleRealize::currentWidget(){ return widgetInAction; } void WidgetHandleRealize::handleWidgetEvent(QEvent *event){ switch (event->type()){ case QEvent::MouseButtonPress: handleMousePressEvent(dynamic_cast(event)); break; case QEvent::MouseButtonRelease: handleMouseReleaseEvent(dynamic_cast(event)); break; case QEvent::MouseMove: handleMouseMoveEvent(dynamic_cast(event)); break; case QEvent::Leave: handleLeaveEvent(dynamic_cast(event)); break; case QEvent::HoverMove: handleHoverMoveEvent(dynamic_cast(event)); break; default: break; } } void WidgetHandleRealize::updateCursorShape(const QPoint &gMousePos){ if (widgetInAction->isFullScreen() || widgetInAction->isMaximized()){ if (cursorShapeChanged) widgetInAction->unsetCursor(); return; } moveMousePos.recalculate(gMousePos, widgetInAction->frameGeometry()); if (moveMousePos.onLeftTopEdges || moveMousePos.onRightBottomEdges){ widgetInAction->setCursor(Qt::SizeFDiagCursor); cursorShapeChanged = true; } else if (moveMousePos.onRightTopEdges || moveMousePos.onLeftBottomEdges){ widgetInAction->setCursor(Qt::SizeBDiagCursor); cursorShapeChanged = true; } else if (moveMousePos.onLeftEdges || moveMousePos.onRightEdges){ widgetInAction->setCursor(Qt::SizeHorCursor); cursorShapeChanged = true; } else if (moveMousePos.onTopEdges || moveMousePos.onBottomEdges){ widgetInAction->setCursor(Qt::SizeVerCursor); cursorShapeChanged = true; } else{ if (cursorShapeChanged){ widgetInAction->unsetCursor(); cursorShapeChanged = false; } } } void WidgetHandleRealize::moveWidget(const QPoint &gMousePos){ widgetInAction->move(gMousePos - dragPos); } void WidgetHandleRealize::resizeWidget(const QPoint &gMousePos){ QRect origRect; origRect = widgetInAction->frameGeometry(); int left = origRect.left(); int top = origRect.top(); int right = origRect.right(); int bottom = origRect.bottom(); origRect.getCoords(&left, &top, &right, &bottom); int minWidth = widgetInAction->minimumWidth(); int minHeight = widgetInAction->minimumHeight(); if (pressedMousePos.onLeftTopEdges){ left = gMousePos.x(); top = gMousePos.y(); } else if (pressedMousePos.onRightTopEdges){ right = gMousePos.x(); top = gMousePos.y(); } else if (pressedMousePos.onRightBottomEdges){ right = gMousePos.x(); bottom = gMousePos.y(); } else if (pressedMousePos.onLeftBottomEdges){ left = gMousePos.x(); bottom = gMousePos.y(); } else if (pressedMousePos.onLeftEdges){ left = gMousePos.x(); } else if (pressedMousePos.onTopEdges){ top = gMousePos.y(); } else if (pressedMousePos.onRightEdges){ right = gMousePos.x(); } else if (pressedMousePos.onBottomEdges){ bottom = gMousePos.y(); } QRect newRect(QPoint(left, top), QPoint(right, bottom)); if (newRect.isValid()){ if (minWidth > newRect.width()){ if (left != origRect.left()) newRect.setLeft(origRect.left()); else newRect.setRight(origRect.right()); } if (minHeight > newRect.height()){ if (top != origRect.top()) newRect.setTop(origRect.top()); else newRect.setBottom(origRect.bottom()); } widgetInAction->setGeometry(newRect); } } void WidgetHandleRealize::handleMousePressEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton){ leftBtnPressed = true; QRect frameRect = widgetInAction->frameGeometry(); pressedMousePos.recalculate(event->globalPos(), frameRect); dragPos = event->globalPos() - frameRect.topLeft(); } } void WidgetHandleRealize::handleMouseReleaseEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton){ leftBtnPressed = false; pressedMousePos.reset(); } } void WidgetHandleRealize::handleMouseMoveEvent(QMouseEvent *event){ if (leftBtnPressed){ if (fpri->widgetResizable && pressedMousePos.onEdges){ resizeWidget(event->globalPos()); } else if (fpri->widgetMovable && leftBtnPressed){ // moveWidget(event->globalPos()); moveMainWindow(); } } else if (fpri->widgetResizable){ updateCursorShape(event->globalPos()); } } void WidgetHandleRealize::moveMainWindow(){ Display *display = QX11Info::display(); Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False); XEvent xEvent; auto pos = QCursor::pos(); pos *= qApp->devicePixelRatio(); memset(&xEvent, 0, sizeof(XEvent)); xEvent.xclient.type = ClientMessage; xEvent.xclient.message_type = netMoveResize; xEvent.xclient.display = display; xEvent.xclient.window = widgetInAction->winId(); xEvent.xclient.format = 32; xEvent.xclient.data.l[0] = pos.x(); xEvent.xclient.data.l[1] = pos.y(); xEvent.xclient.data.l[2] = 8; xEvent.xclient.data.l[3] = Button1; xEvent.xclient.data.l[4] = 0; XUngrabPointer(display, CurrentTime); XSendEvent(display, QX11Info::appRootWindow(QX11Info::appScreen()), False, SubstructureNotifyMask | SubstructureRedirectMask, &xEvent); XFlush(display); } void WidgetHandleRealize::handleLeaveEvent(QEvent *event){ Q_UNUSED(event) if (!leftBtnPressed) widgetInAction->unsetCursor(); } void WidgetHandleRealize::handleHoverMoveEvent(QHoverEvent *event){ if (fpri->widgetResizable){ updateCursorShape(widgetInAction->mapToGlobal(event->pos())); } } ukui-system-monitor/src/framelessExtended/framelesshandleprivate.h0000644000175000017500000000212713746753504024634 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FRAMELESSHANDLEPRIVATE_H #define FRAMELESSHANDLEPRIVATE_H #include class QWidget; class WidgetHandleRealize; class FramelessHandlePrivate { public: QHash widgethandleHash; bool widgetResizable : true; bool widgetMovable : true; }; #endif // FRAMELESSHANDLEPRIVATE_H ukui-system-monitor/src/framelessExtended/widgethandlerealize.h0000644000175000017500000000372313746753504024122 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef WIDGETHANDLEREALIZE_H #define WIDGETHANDLEREALIZE_H #include #include #include #include #include "framelesshandleprivate.h" #include "cursorposcalculator.h" class WidgetHandleRealize : public QWidget { public: explicit WidgetHandleRealize(FramelessHandlePrivate * _fpri, QWidget *pTopLevelWidget); ~WidgetHandleRealize(); public: QWidget * currentWidget(); void handleWidgetEvent(QEvent * event); private: void updateCursorShape(const QPoint &gMousePos); void resizeWidget(const QPoint &gMousePos); void moveWidget(const QPoint &gMousePos); void handleMousePressEvent(QMouseEvent * event); void handleMouseReleaseEvent(QMouseEvent * event); void handleMouseMoveEvent(QMouseEvent * event); void handleLeaveEvent(QEvent * event); void handleHoverMoveEvent(QHoverEvent * event); void moveMainWindow(void); private: FramelessHandlePrivate * fpri; QWidget * widgetInAction; QPoint dragPos; CursorPosCalculator pressedMousePos; CursorPosCalculator moveMousePos; bool leftBtnPressed; bool cursorShapeChanged; Qt::WindowFlags currentWindowFlags; }; #endif // WIDGETHANDLEREALIZE_H ukui-system-monitor/src/framelessExtended/cursorposcalculator.cpp0000644000175000017500000000435313746753504024553 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "cursorposcalculator.h" int CursorPosCalculator::borderWidth = 5; CursorPosCalculator::CursorPosCalculator() { reset(); } void CursorPosCalculator::reset(){ onEdges = false; onLeftEdges = false; onTopEdges = false; onRightEdges = false; onBottomEdges = false; onLeftTopEdges =false; onRightTopEdges = false; onRightBottomEdges = false; onLeftBottomEdges = false; } void CursorPosCalculator::recalculate(const QPoint &globalMousePos, const QRect &frameRect){ int globalMouseX = globalMousePos.x(); int globalMouseY = globalMousePos.y(); int frameX = frameRect.x(); int frameY = frameRect.y(); int frameWidth = frameRect.width(); int frameHeight = frameRect.height(); onLeftEdges = (globalMouseX >= frameX && globalMouseX <= frameX + borderWidth); onRightEdges = (globalMouseX >= frameX + frameWidth - borderWidth && globalMouseX <= frameX + frameWidth); onTopEdges = (globalMouseY >= frameY && globalMouseY <= frameY + borderWidth); onBottomEdges = (globalMouseY >= frameY + frameHeight - borderWidth && globalMouseY <= frameY + frameHeight); onLeftTopEdges = onTopEdges && onLeftEdges; onRightTopEdges = onRightEdges && onTopEdges; onRightBottomEdges = onRightEdges && onBottomEdges; onLeftBottomEdges = onLeftEdges && onBottomEdges; onEdges = onLeftEdges || onRightEdges || onTopEdges || onBottomEdges; } ukui-system-monitor/src/framelessExtended/cursorposcalculator.h0000644000175000017500000000257513746753504024224 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CURSORPOSCALCULATOR_H #define CURSORPOSCALCULATOR_H #include #include class CursorPosCalculator { public: explicit CursorPosCalculator(); public: void reset(); void recalculate(const QPoint &globalMousePos, const QRect &frameRect); public: bool onEdges : true; bool onLeftEdges : true; bool onTopEdges : true; bool onRightEdges : true; bool onBottomEdges : true; bool onLeftTopEdges : true; bool onRightTopEdges : true; bool onRightBottomEdges : true; bool onLeftBottomEdges : true; static int borderWidth; }; #endif // CURSORPOSCALCULATOR_H ukui-system-monitor/src/filesystemlistitem.cpp0000644000175000017500000002663013763560717020742 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "filesystemlistitem.h" #include #include #include #include #include "util.h" #include #include #include FileSystemListItem::FileSystemListItem(FileSystemData *info) :fontSettings(nullptr) ,qtSettings(nullptr) { m_data = info; iconSize = 20; padding = 14; textPadding = 5; const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } initFontSize(); } FileSystemListItem::~FileSystemListItem() { if(qtSettings) { delete qtSettings; } if(fontSettings) { delete fontSettings; } } void FileSystemListItem::initThemeMode() { if (!qtSettings) { // qWarning() << "Failed to load the gsettings: " << THEME_QT_SCHEMA; return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); qDebug() <<" Current theme mode change to: "<get(MODE_QT_KEY).toString(); } void FileSystemListItem::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings, &QGSettings::changed, this, [=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } bool FileSystemListItem::isSameItem(FileSystemListItem *item) { return m_data->deviceName() == ((static_cast(item)))->m_data->deviceName(); } void FileSystemListItem::drawBackground(QRect rect, QPainter *painter, int index, bool isSelect, QString currentTheme) { QPainterPath path; path.addRect(QRectF(rect)); if (isSelect) { painter->setOpacity(0.08); painter->fillPath(path, QColor("palette(windowText)")); } else { painter->setOpacity(0.08); if(currentTheme == "ukui-light" || currentTheme == "ukui-default" || currentTheme == "ukui-white") { painter->fillPath(path, QColor("#ffffff")); } if(currentTheme == "ukui-dark" || currentTheme == "ukui-black") { painter->fillPath(path, QColor("#000000")); } // if (index % 2 == 0) { // painter->fillPath(path, QColor("#ffffff")); // } else { // painter->fillPath(path, QColor("#e9eef0")); // } } } void FileSystemListItem::drawForeground(QRect rect, QPainter *painter, int column, int, bool isSelect, bool isSeparator) { setFontSize(*painter, fontSize); painter->setOpacity(0.85); //painter->setPen(QPen(QColor("#000000"))); if (column == 0) { painter->drawPixmap(QRect(rect.x() + padding, rect.y() + (rect.height() - iconSize) / 2, iconSize, iconSize), QPixmap(":/img/drive-harddisk-system.png")); int nameMaxWidth = rect.width() - iconSize - padding * 3; QFont font = painter->font(); QFontMetrics fm(font); QString deviceName = fm.elidedText(m_data->deviceName(), Qt::ElideRight, nameMaxWidth);//Qt::ElideMiddle painter->drawText(QRect(rect.x() + iconSize + padding * 2, rect.y(), nameMaxWidth, rect.height()), Qt::AlignCenter, deviceName); if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 1) { if (!m_data->mountDir().isEmpty()) { int maxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString mountDir = fm.elidedText(m_data->mountDir(), Qt::ElideMiddle, maxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, mountDir); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 2) { if (!m_data->diskType().isEmpty()) { int maxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString diskType = fm.elidedText(m_data->diskType(), Qt::ElideRight, maxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, diskType); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 3) { if (!m_data->totalCapacity().isEmpty()) { int maxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString tCapacity = fm.elidedText(m_data->totalCapacity(), Qt::ElideRight, maxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, tCapacity); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 4) { if (!m_data->freeCapacity().isEmpty()) { int maxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString fCapacity = fm.elidedText(m_data->freeCapacity(), Qt::ElideRight, maxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, fCapacity); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 5) { if (!m_data->availCapacity().isEmpty()) { int maxWidth = rect.width(); QFont font = painter->font(); QFontMetrics fm(font); QString aCapacity = fm.elidedText(m_data->availCapacity(), Qt::ElideRight, maxWidth); painter->drawText(QRect(rect.x(), rect.y(), rect.width() - textPadding, rect.height()), Qt::AlignCenter, aCapacity); } if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } else if (column == 6) { int maxWidth = rect.width(); int leftPadding = 10; int topPadding = 5; int progressWidth = 100; int progressHeight = rect.height() - 2 * topPadding; int textMaxWidth = rect.width() - progressWidth - 2 * leftPadding; if (!m_data->usedCapactiy().isEmpty()) { QFont font = painter->font(); QFontMetrics fm(font); QString uCapacity = fm.elidedText(m_data->usedCapactiy(), Qt::ElideRight, maxWidth); // painter->drawText(QRect(rect.x() + textPadding, rect.y(), textMaxWidth - textPadding, rect.height()), Qt::AlignCenter, uCapacity); painter->drawText(QRect(rect.x() , rect.y(), rect.width(), rect.height()), Qt::AlignCenter, uCapacity); } //这部分代码为原来绘制未占用区域的灰色部分。////////////// // QPainterPath bgPath; //// bgPath.addRect(QRectF(rect.x() + textMaxWidth + leftPadding, rect.y() + topPadding, progressWidth, progressHeight)); // bgPath.addRect(QRectF(rect.x() + textMaxWidth + leftPadding, rect.y() + topPadding, progressWidth, 2)); // painter->fillPath(bgPath, QColor("#C4BDBD")); //// painter->fillPath(bgPath,QColor("palette(Base)")); ///////////////////////////////////////////////// QPainterPath fillPath; // fillPath.addRect(QRectF(rect.x() + textMaxWidth + leftPadding, rect.y() + topPadding, m_data->usedPercentage(), progressHeight)); fillPath.addRect(QRectF(rect.x() + rect.width() - m_data->usedPercentage(), rect.y() + rect.height() -2, m_data->usedPercentage(), 2)); painter->setOpacity(0.5); if (m_data->usedPercentage() < 75) painter->fillPath(fillPath, QColor("#0288d1")); else painter->fillPath(fillPath, QColor("#f8b551")); // painter->setOpacity(1); // painter->drawText(QRect(rect.x() + textMaxWidth + leftPadding, rect.y() + topPadding, progressWidth, progressHeight), Qt::AlignCenter, nullptr); /* QStyleOptionProgressBar progressBarStyle;//progressBarStyle.initFrom(this); progressBarStyle.rect = QRect(rect.x() + 60, rect.y() + topPadding, pWidth, pHeight); progressBarStyle.minimum = 0; progressBarStyle.maximum = 100; progressBarStyle.textAlignment = Qt::AlignCenter; progressBarStyle.progress = m_data->usedPercentage(); progressBarStyle.text = QString("%1%").arg(m_data->usedPercentage()); progressBarStyle.textVisible = true; QProgressBar progressBar; progressBar.setStyleSheet("QProgressBar{border: none;text-align: center;background:#eeeeee;}QProgressBar::chunk {background:#0288d1;}"); QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarStyle, painter, &progressBar);//绘制进度条 */ if (!isSeparator) { painter->setOpacity(0.8); QPainterPath separatorPath; separatorPath.addRect(QRectF(rect.x() + rect.width() - 1, rect.y(), 1, rect.height())); painter->fillPath(separatorPath, QColor("#e0e0e0")); } } } QString FileSystemListItem::getDeviceName() const { return m_data->deviceName(); } QString FileSystemListItem::getDirectory() const { return m_data->mountDir(); } ukui-system-monitor/widgets/0000755000175000017500000000000013763560717015147 5ustar fengfengukui-system-monitor/widgets/mysearchedit.h0000644000175000017500000000474613755705142020006 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYSEARCHEDIT_H #define MYSEARCHEDIT_H #include #include #include #include #include #include #include #include #include #include #include #include #include "shell/customstyle.h" #include "../shell/macro.h" #include "mytristatebutton.h" class QGsettings; class MySearchEdit : public QFrame { Q_OBJECT public: explicit MySearchEdit(QWidget *parent = 0); ~MySearchEdit(); void setPlaceHolder(const QString &text); const QString searchedText() const; QLineEdit *getLineEdit() const; void initThemeMode(); void initFontSize(); public slots: void clearEdit(); void setEditFocus(); void setText(const QString & text); void clearAndFocusEdit(); private slots: void textChageSlots(const QString &text); signals: void textChanged(); protected: void resizeEvent(QResizeEvent *event); bool event(QEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); bool eventFilter(QObject *object, QEvent *event); // void paintEvent(QEvent *event); private: QPropertyAnimation *m_animation = nullptr; QEasingCurve m_showCurve; QEasingCurve m_hideCurve; QSize m_size; QLineEdit *m_edit = nullptr; QLabel *m_searchBtn = nullptr; QLabel *m_placeHolder = nullptr; MyTristateButton *m_clearBtn = nullptr; QPushButton *m_pClearTextButton =nullptr; QPixmap drawSymbolicColoredPixmap(const QPixmap &source); float fontSize; QGSettings *qtSettings; QGSettings *fontSettings; QString currentThemeMode; }; #endif // MYSEARCHEDIT_H ukui-system-monitor/widgets/mydialog.h0000644000175000017500000000523313746753570017132 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYDIALOG_H #define MYDIALOG_H #include #include #include #include class QAbstractButton; class QButtonGroup; class QLabel; class QCloseEvent; class QVBoxLayout; class MyTristateButton; #include class MyDialog : public QDialog { Q_OBJECT public: explicit MyDialog(const QString &title, const QString& message, QWidget *parent = 0); ~MyDialog(); void updateSize(); int buttonCount() const; QRect getParentGeometry() const; void moveToCenter(); signals: void buttonClicked(int index, const QString &text); public slots: int addButton(const QString &text, bool isDefault = false); void setDefaultButton(QAbstractButton *button); void setTitle(const QString &title); void setMessage(const QString& message); int exec() Q_DECL_OVERRIDE; public slots: void onButtonClicked(); void onDefaultButtonTriggered(); protected: void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; void hideEvent(QHideEvent *event) Q_DECL_OVERRIDE; void childEvent(QChildEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private: QLabel *m_messageLabel = nullptr; QLabel *m_titleLabel = nullptr; QPushButton *closeButton = nullptr; // QVBoxLayout *contentLayout = nullptr; QHBoxLayout *m_buttonLayout = nullptr; QHBoxLayout *m_topLayout = nullptr; QList buttonList; QList contentList; QPointer defaultButton; int clickedButtonIndex; QString m_title; QString m_message; QPoint dragPosition; bool mousePressed; }; #endif // MYDIALOG_H ukui-system-monitor/widgets/mydialog.cpp0000644000175000017500000002403613746753570017467 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mydialog.h" #include "mytristatebutton.h" #include #include #include #include #include #include #include #include #include #include MyDialog::MyDialog(const QString &title, const QString &message, QWidget *parent) : QDialog(parent) , mousePressed(false) { this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint | Qt::WindowCloseButtonHint); // this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);//Attention: Qt::WindowCloseButtonHint make showMinimized() valid this->setAttribute(Qt::WA_TranslucentBackground); // this->setAttribute(Qt::WA_DeleteOnClose, false); this->setAttribute(Qt::WA_Resized, false); m_topLayout = new QHBoxLayout; m_topLayout->setContentsMargins(20, 14, 20, 14); m_topLayout->setSpacing(20); m_titleLabel = new QLabel; m_titleLabel->setStyleSheet("QLabel{padding-top:3px;padding-bottom:3px;font-size:18px;color:#000000;}"); m_titleLabel->hide(); // m_titleLabel->setAttribute(Qt::WA_TransparentForMouseEvents); m_messageLabel = new QLabel; m_messageLabel->setStyleSheet("QLabel{padding-top:3px;padding-bottom:3px;font-size:12px;color:#000000;}"); m_messageLabel->hide(); m_messageLabel->setAttribute(Qt::WA_TransparentForMouseEvents); QVBoxLayout *textLayout = new QVBoxLayout; textLayout->setContentsMargins(0, 0, 0, 0); textLayout->setSpacing(5); textLayout->addWidget(m_titleLabel, 0, Qt::AlignLeft); textLayout->addWidget(m_messageLabel, 0, Qt::AlignLeft); textLayout->addStretch(); m_topLayout->addLayout(textLayout); closeButton = new QPushButton(); closeButton->setObjectName("CloseButton"); // connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); connect(closeButton,&QPushButton::clicked,this,[=](){ this->deleteLater(); this->close(); }); closeButton->setIcon(QIcon::fromTheme("window-close-symbolic")); closeButton->setStyleSheet("QPushButton{background:transparent;}"); // connect(closeButton, &MyTristateButton::clicked, this, [=] { // this->close(); // }); closeButton->setAttribute(Qt::WA_NoMousePropagation); m_buttonLayout = new QHBoxLayout; m_buttonLayout->setMargin(0); m_buttonLayout->setSpacing(0); m_buttonLayout->setContentsMargins(20, 14, 20, 14); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(10); mainLayout->addWidget(closeButton, 0, Qt::AlignTop | Qt::AlignRight); mainLayout->addLayout(m_topLayout); mainLayout->addLayout(m_buttonLayout); QAction *button_action = new QAction(this); button_action->setShortcuts(QKeySequence::InsertParagraphSeparator); button_action->setAutoRepeat(false); connect(button_action, SIGNAL(triggered(bool)), this, SLOT(onDefaultButtonTriggered())); this->setLayout(mainLayout); this->addAction(button_action); this->setFocusPolicy(Qt::ClickFocus); this->setFocus(); setTitle(title); setMessage(message); //this->moveToCenter(); } MyDialog::~MyDialog() { delete m_messageLabel; delete m_titleLabel; delete closeButton; QLayoutItem *child; while ((child = m_topLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } this->buttonList.clear(); while ((child = m_buttonLayout->takeAt(0)) != 0) { if (child->widget()) child->widget()->deleteLater(); delete child; } // while(this->m_buttonLayout->count()) { // QLayoutItem *item = this->m_buttonLayout->takeAt(0); // item->widget()->deleteLater(); // delete item; // } } void MyDialog::updateSize() { if (!this->testAttribute(Qt::WA_Resized)) { QSize size = this->sizeHint(); size.setWidth(qMax(size.width(), 234)); size.setHeight(qMax(size.height(), 196)); this->resize(size); this->setAttribute(Qt::WA_Resized, false); } } void MyDialog::onButtonClicked() { QAbstractButton *button = qobject_cast(this->sender()); if(button) { clickedButtonIndex = buttonList.indexOf(button); emit this->buttonClicked(clickedButtonIndex, button->text()); this->done(clickedButtonIndex);//cancel:0 ok:1 } } void MyDialog::onDefaultButtonTriggered() { QAbstractButton *button = qobject_cast(this->focusWidget()); if (button) button->click(); else if (defaultButton) defaultButton->click(); } int MyDialog::buttonCount() const { return this->buttonList.count(); } int MyDialog::addButton(const QString &text, bool isDefault) { int index = buttonCount(); QAbstractButton *button = new QPushButton(text); button->setFocusPolicy(Qt::NoFocus); button->setStyleSheet("QPushButton{font-size:12px;background-color:transparent;border:1px solid #bebebe;color:#000000;}QPushButton:hover{background-color:#ffffff;border:1px solid #3f96e4;color:#000000;}QPushButton:pressed{background-color:#ffffff;border:1px solid #3f96e4;color:#000000;}"); button->setAttribute(Qt::WA_NoMousePropagation); button->setFixedSize(91, 25); this->m_buttonLayout->insertWidget(index+1, button); this->buttonList << button; connect(button, SIGNAL(clicked(bool)), this, SLOT(onButtonClicked())); if(isDefault) { setDefaultButton(button); } return index; } void MyDialog::setDefaultButton(QAbstractButton *button) { this->defaultButton = button; } void MyDialog::setTitle(const QString &title) { if (this->m_title == title) return; this->m_title = title; this->m_titleLabel->setText(title); this->m_titleLabel->setHidden(title.isEmpty()); } void MyDialog::setMessage(const QString &message) { if (this->m_message == message) return; this->m_message = message; this->m_messageLabel->setText(message); this->m_messageLabel->setHidden(message.isEmpty()); } int MyDialog::exec() { this->clickedButtonIndex = -1; int ret = QDialog::exec(); return this->clickedButtonIndex >= 0 ? this->clickedButtonIndex : ret; } void MyDialog::showEvent(QShowEvent *event) { QDialog::showEvent(event); setAttribute(Qt::WA_Resized, false); this->updateSize(); } void MyDialog::hideEvent(QHideEvent *event) { QDialog::hideEvent(event); done(-1); } void MyDialog::childEvent(QChildEvent *event) { QDialog::childEvent(event); if (event->added()) { if (this->closeButton) { this->closeButton->raise(); } } } QRect MyDialog::getParentGeometry() const { if (this->parentWidget()) { return this->parentWidget()->window()->geometry(); } else { QPoint pos = QCursor::pos(); for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { return screen->geometry(); } } } return qApp->primaryScreen()->geometry(); } void MyDialog::moveToCenter() { QRect qr = geometry(); qr.moveCenter(this->getParentGeometry().center()); move(qr.topLeft()); } void MyDialog::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->dragPosition = event->globalPos() - frameGeometry().topLeft(); this->mousePressed = true; } QDialog::mousePressEvent(event); } void MyDialog::mouseReleaseEvent(QMouseEvent *event) { this->mousePressed = false; QDialog::mouseReleaseEvent(event); } void MyDialog::mouseMoveEvent(QMouseEvent *event) { if (this->mousePressed) { move(event->globalPos() - this->dragPosition); } QDialog::mouseMoveEvent(event); } void MyDialog::paintEvent(QPaintEvent *event) { QPainter painter(this); //绘制圆角矩形 painter.setPen(QPen(QColor("#808080"), 0));//边框颜色 // painter.setBrush(QColor("#e9eef0"));//背景色 #0d87ca painter.setBrush(this->palette().base()); painter.setRenderHint(QPainter::Antialiasing, true); painter.setOpacity(1); QRectF r(0 / 2.0, 0 / 2.0, width() - 0, height() - 0);//左边 上边 右边 下边 painter.drawRoundedRect(r, 4, 4); //绘制背景色 // QPainterPath path; // path.addRect(QRectF(rect())); // painter.setOpacity(1); // painter.fillPath(path, QColor("#ffffff")); QDialog::paintEvent(event); } void MyDialog::resizeEvent(QResizeEvent *event) { QDialog::resizeEvent(event); this->m_titleLabel->setWordWrap(false); int labelMaxWidth = maximumWidth() - this->closeButton->width() - this->m_titleLabel->x(); if (this->m_titleLabel->sizeHint().width() > labelMaxWidth) { this->m_titleLabel->setFixedWidth(labelMaxWidth); this->m_titleLabel->setWordWrap(true); this->m_titleLabel->setFixedHeight(this->m_titleLabel->sizeHint().height()); } this->m_messageLabel->setWordWrap(false); labelMaxWidth = maximumWidth() - this->closeButton->width() - this->m_messageLabel->x(); if (this->m_messageLabel->sizeHint().width() > labelMaxWidth) { this->m_messageLabel->setFixedWidth(labelMaxWidth); this->m_messageLabel->setWordWrap(true); this->m_messageLabel->setFixedHeight(this->m_messageLabel->sizeHint().height()); } } ukui-system-monitor/widgets/myhoverbutton.cpp0000644000175000017500000000623013746753504020600 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "myhoverbutton.h" #include #include MyHoverButton::MyHoverButton(QWidget *parent) : QLabel(parent) ,m_state(Normal) ,m_isChecked(false) { this->setStyleSheet("QLabel{background-color:transparent;}"); } MyHoverButton::~MyHoverButton() { } void MyHoverButton::enterEvent(QEvent *event) { setCursor(Qt::PointingHandCursor); if (!m_isChecked){ setState(Hover); } event->accept(); //QLabel::enterEvent(event); } void MyHoverButton::leaveEvent(QEvent *event) { if (!m_isChecked){ setState(Normal); } event->accept(); //QLabel::leaveEvent(event); } void MyHoverButton::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) return; setState(Press); event->accept(); //QLabel::mousePressEvent(event); } void MyHoverButton::mouseReleaseEvent(QMouseEvent *event) { if (!rect().contains(event->pos())) return; m_isChecked = !m_isChecked; if (m_isChecked){ setState(Checked); } else { setState(Normal); } event->accept(); //QLabel::mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) emit clicked(); } void MyHoverButton::mouseMoveEvent(QMouseEvent *event) { if (!rect().contains(event->pos())) { setState(Normal); } } void MyHoverButton::updateBackgroundColor() { switch (m_state) { case Hover: this->setStyleSheet("QLabel{background-color:#e0f4f9;}"); break; case Press: this->setStyleSheet("QLabel{background-color:#e0f4f9;}"); break; case Checked: this->setStyleSheet("QLabel{background-color:#e0f4f9;}"); break; default: this->setStyleSheet("QLabel{background-color:transparent;}"); break; } setAlignment(Qt::AlignCenter); } void MyHoverButton::setState(MyHoverButton::HoverButtonState state) { if (m_state == state) return; m_state = state; updateBackgroundColor(); } void MyHoverButton::setChecked(bool flag) { m_isChecked = flag; if (m_isChecked){ setState(Checked); } else { setState(Normal); } } bool MyHoverButton::isChecked() { return m_isChecked; } void MyHoverButton::setPicture(const QString &picture) { setPixmap(QPixmap(picture)); } MyHoverButton::HoverButtonState MyHoverButton::getButtonState() const { return m_state; } ukui-system-monitor/widgets/myhoverbutton.h0000644000175000017500000000335113746753504020246 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYHOVERBUTTON_H #define MYHOVERBUTTON_H #include #include #include #include class MyHoverButton : public QLabel { Q_OBJECT enum HoverButtonState {Normal, Hover, Press, Checked}; public: MyHoverButton(QWidget * parent=0); ~MyHoverButton(); void setChecked(bool flag); bool isChecked(); void setPicture(const QString &picture); HoverButtonState getButtonState() const; signals: void clicked(); void stateChanged(); protected: void enterEvent(QEvent * event) Q_DECL_OVERRIDE; void leaveEvent(QEvent * event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent * event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent * event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private: void updateBackgroundColor(); void setState(HoverButtonState state); private: HoverButtonState m_state; bool m_isChecked; }; #endif // MYHOVERBUTTON_H ukui-system-monitor/widgets/myaction.cpp0000644000175000017500000000512713746753504017502 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "myaction.h" #include MyAction::MyAction (QObject * parent, const char * name, bool autoadd) : QAction(parent) { setObjectName(name); if (autoadd) addActionToParent(); } MyAction::MyAction(QObject * parent, bool autoadd) : QAction(parent) { if (autoadd) addActionToParent(); } MyAction::MyAction(const QString & text, QKeySequence accel, QObject * parent, const char * name, bool autoadd ) : QAction(parent) { setObjectName(name); setText(text); setShortcut(accel); if (autoadd) addActionToParent(); } MyAction::MyAction(QKeySequence accel, QObject * parent, const char * name, bool autoadd ) : QAction(parent) { setObjectName(name); setShortcut(accel); if (autoadd) addActionToParent(); } MyAction::~MyAction() { } void MyAction::addShortcut(QKeySequence key) { setShortcuts( shortcuts() << key); } void MyAction::addActionToParent() { if (parent()) { if (parent()->inherits("QWidget")) { QWidget *w = static_cast (parent()); w->addAction(this); } } } void MyAction::change(const QIcon & icon, const QString & text) { setIcon( icon ); change(text); } void MyAction::change(const QString & text ) { setText( text ); QString accel_text = shortcut().toString(); QString s = text; s.replace("&",""); if (!accel_text.isEmpty()) { setToolTip( s + " ("+ accel_text +")"); setIconText( s ); } /* if (text.isEmpty()) { QString s = menuText; s = s.replace("&",""); setText( s ); if (!accel_text.isEmpty()) setToolTip( s + " ("+ accel_text +")"); } else { setText( text ); if (!accel_text.isEmpty()) setToolTip( text + " ("+ accel_text +")"); } */ } ukui-system-monitor/widgets/myactiongroupitem.h0000644000175000017500000000215113746753504021075 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _MYACTIONGROUPITEM_H_ #define _MYACTIONGROUPITEM_H_ #include "myaction.h" #include class MyActionGroup; class MyActionGroupItem : public MyAction { public: MyActionGroupItem( QObject * parent, MyActionGroup *group, const char * name, int data, bool autoadd = true ); }; #endif // _MYACTIONGROUPITEM_H_ ukui-system-monitor/widgets/myaction.h0000644000175000017500000000301413746753504017140 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _MYACTION_H_ #define _MYACTION_H_ #include #include #include #include class MyAction : public QAction { public: MyAction (QObject * parent, const char * name, bool autoadd = true ); MyAction (QObject * parent, bool autoadd = true ); MyAction (const QString & text, QKeySequence accel, QObject * parent, const char * name = "", bool autoadd = true ); MyAction (QKeySequence accel, QObject * parent, const char * name = "", bool autoadd = true ); ~MyAction(); void addShortcut(QKeySequence key); void change(const QIcon & icon, const QString & text ); void change(const QString & text); protected: void addActionToParent(); }; #endif ukui-system-monitor/widgets/mytristatebutton.h0000644000175000017500000000543713746753504020771 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYTRISTATEBUTTON_H #define MYTRISTATEBUTTON_H #include #include #include #include #include #include #include class MyTristateButton : public QLabel { Q_OBJECT Q_PROPERTY(QString normalPic READ getNormalPic WRITE setNormalPic DESIGNABLE true) Q_PROPERTY(QString hoverPic READ getHoverPic WRITE setHoverPic DESIGNABLE true) Q_PROPERTY(QString pressPic READ getPressPic WRITE setPressPic DESIGNABLE true) Q_PROPERTY(QString checkedPic READ getCheckedPic WRITE setCheckedPic DESIGNABLE true) public: MyTristateButton(QWidget * parent=0); ~MyTristateButton(); void setChecked(bool flag); void setCheckable(bool flag); bool isChecked(); bool isCheckable(); void setNormalPic(const QString & normalPic); void setHoverPic(const QString & hoverPic); void setPressPic(const QString & pressPic); void setCheckedPic(const QString & checkedPic); inline const QString getNormalPic() const {return m_normalPic;} inline const QString getHoverPic() const {return m_hoverPic;} inline const QString getPressPic() const {return m_pressPic;} inline const QString getCheckedPic() const {return m_checkedPic;} enum ButtonState {Normal, Hover, Press, Checked}; ButtonState getButtonState() const; signals: //Q_SIGNALS: void clicked(); void stateChanged(); protected: void enterEvent(QEvent * event) Q_DECL_OVERRIDE; void leaveEvent(QEvent * event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent * event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent * event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private: void updateIcon(); void setState(ButtonState state); private: QPushButton *m_pClearTextButton; ButtonState m_state = Normal; bool m_isChecked = false; bool m_isCheckable = false; QString m_normalPic; QString m_hoverPic; QString m_pressPic; QString m_checkedPic; }; #endif // MYTRISTATEBUTTON_H ukui-system-monitor/widgets/myunderlinebutton.h0000644000175000017500000000433013755705142021101 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MYUNDERLINEBUTTON_H #define MYUNDERLINEBUTTON_H #include #include #include #include #include #include #include #include #include "shell/customstyle.h" #include "../shell/macro.h" class QVBoxLayout; class MyUnderLineButton : public QWidget { Q_OBJECT enum ButtonState {Normal, Hover, Press, Checked}; public: MyUnderLineButton(QWidget * parent=0); ~MyUnderLineButton(); void setChecked(bool flag); bool isChecked(); void setName(const QString &name); ButtonState getButtonState() const; void initThemeMode(); void initFontSize(); signals: void clicked(); protected: void enterEvent(QEvent *event) Q_DECL_OVERRIDE; void leaveEvent(QEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) override; private: void updateStyleSheet(); void setState(ButtonState state); private: ButtonState m_state; ButtonState m_button_state; bool m_isChecked; QLabel *m_textLabel = nullptr; //QLabel *m_underlineLabel = nullptr; QVBoxLayout *m_layout = nullptr; float fontSize; QGSettings *qtSettings; QGSettings *fontSettings; QString currentThemeMode; }; #endif // MYUNDERLINEBUTTON_H ukui-system-monitor/widgets/myactiongroupitem.cpp0000644000175000017500000000220313746753504021426 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "myactiongroupitem.h" #include "myactiongroup.h" MyActionGroupItem::MyActionGroupItem(QObject * parent, MyActionGroup *group, const char * name, int data, bool autoadd) : MyAction(parent, name, autoadd) { setData(data); setCheckable(true); if (group) group->addAction(this); } ukui-system-monitor/widgets/mytristatebutton.cpp0000644000175000017500000001057013746753504021316 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mytristatebutton.h" #include #include MyTristateButton::MyTristateButton(QWidget *parent) : QLabel(parent) { setCheckable(false);//setCheckable(true); updateIcon(); this->setStyleSheet("QLabel{background-color:transparent;border:none;}"); m_pClearTextButton = new QPushButton; //QPixmap fileName(":/img/button-close-default-add-background-three.svg"); this->setFixedSize(19, 21); m_pClearTextButton->setIconSize(QSize(9, 9)); m_pClearTextButton->setStyleSheet("QPushButton{border-image:url(:/image/button-close-default-add-background-three.svg)}"); QHBoxLayout *cancel_h_BoxLayout = new QHBoxLayout(this); cancel_h_BoxLayout->addWidget(m_pClearTextButton); } MyTristateButton::~MyTristateButton() { } void MyTristateButton::enterEvent(QEvent *event) { setCursor(Qt::PointingHandCursor); if (!m_isChecked){ setState(Hover); } event->accept(); //QLabel::enterEvent(event); } void MyTristateButton::leaveEvent(QEvent *event) { if (!m_isChecked){ setState(Normal); } event->accept(); //QLabel::leaveEvent(event); } void MyTristateButton::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) return; setState(Press); event->accept(); //QLabel::mousePressEvent(event); } void MyTristateButton::mouseReleaseEvent(QMouseEvent *event) { if (!rect().contains(event->pos())) return; if (m_isCheckable){ m_isChecked = !m_isChecked; if (m_isChecked){ setState(Checked); } else { setState(Normal); } } else { setState(Hover); } event->accept(); //QLabel::mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) emit clicked(); } void MyTristateButton::mouseMoveEvent(QMouseEvent *event) { if (!m_isCheckable && !rect().contains(event->pos())) { setState(Normal); } } void MyTristateButton::updateIcon() { switch (m_state) { case Hover: if (!m_hoverPic.isEmpty()) setPixmap(QPixmap(m_hoverPic)); break; case Press: if (!m_pressPic.isEmpty()) setPixmap(QPixmap(m_pressPic)); break; case Checked: if (!m_checkedPic.isEmpty()) setPixmap(QPixmap(m_checkedPic)); break; default: if (!m_normalPic.isEmpty()) setPixmap(QPixmap(m_normalPic)); break; } setAlignment(Qt::AlignCenter); } void MyTristateButton::setState(MyTristateButton::ButtonState state) { if (m_state == state) return; m_state = state; updateIcon(); } void MyTristateButton::setCheckable(bool flag) { m_isCheckable = flag; if (!m_isCheckable){ setState(Normal); } } void MyTristateButton::setChecked(bool flag) { if (m_isCheckable == false){ return; } m_isChecked = flag; if (m_isChecked){ setState(Checked); } else { setState(Normal); } } bool MyTristateButton::isChecked() { return m_isChecked; } bool MyTristateButton::isCheckable() { return m_isCheckable; } void MyTristateButton::setNormalPic(const QString &normalPicPixmap) { m_normalPic = normalPicPixmap; updateIcon(); } void MyTristateButton::setHoverPic(const QString &hoverPicPixmap) { m_hoverPic = hoverPicPixmap; updateIcon(); } void MyTristateButton::setPressPic(const QString &pressPicPixmap) { m_pressPic = pressPicPixmap; updateIcon(); } void MyTristateButton::setCheckedPic(const QString &checkedPicPixmap) { m_checkedPic = checkedPicPixmap; updateIcon(); } MyTristateButton::ButtonState MyTristateButton::getButtonState() const { return m_state; } ukui-system-monitor/widgets/mysearchedit.cpp0000644000175000017500000003036113763560717020337 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mysearchedit.h" #include #include #include #include #include #include MySearchEdit::MySearchEdit(QWidget *parent) : QFrame(parent) ,m_showCurve(QEasingCurve::OutCubic) ,m_hideCurve(QEasingCurve::InCubic) ,fontSettings(nullptr) ,qtSettings(nullptr) { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } this->setWindowFlags(Qt::FramelessWindowHint); m_searchBtn = new QLabel; m_searchBtn->setStyleSheet("QLabel{background-color:transparent;border:none;background-image:url(:/img/search.png);}"); m_searchBtn->setFixedSize(SEARCHBUTTON, SEARCHBUTTON); m_pClearTextButton = new QPushButton; m_pClearTextButton->setFixedSize(19, 21); m_pClearTextButton->setIconSize(QSize(19, 19)); m_pClearTextButton->setObjectName("ClearTextButton"); m_edit = new QLineEdit; QIcon ClearTextEditIcon; m_pClearTextButton->setCursor(Qt::ArrowCursor); m_edit->setAttribute(Qt::WA_Hover, true); m_edit->setTextMargins(8,0,0,0); connect(m_edit, &QLineEdit::textChanged, this, &MySearchEdit::textChageSlots); initFontSize(); QFont SearchLine; SearchLine = m_edit->font(); SearchLine.setPixelSize(fontSize); SearchLine.setFamily("Noto Sans CJK SC"); m_edit->setFont(SearchLine); m_edit->setStyleSheet("color:palette(windowText)"); QWidgetAction *action = new QWidgetAction(m_edit); action->setDefaultWidget(m_pClearTextButton); m_edit->addAction(action, QLineEdit::TrailingPosition); m_pClearTextButton->setVisible(false); connect(m_pClearTextButton, &QPushButton::clicked, this, [=](){ m_edit->setText(""); }); m_placeHolder = new QLabel; //about the font QFont font; font.setPointSize(fontSize-2); m_placeHolder->setFont(font); initThemeMode(); m_animation = new QPropertyAnimation(m_edit, "minimumWidth"); m_edit->setFixedWidth(0); m_edit->installEventFilter(this); m_pClearTextButton->setStyleSheet( "QPushButton{" "background:transparent;" "border:0px solid;" "}"); QHBoxLayout *layout = new QHBoxLayout(this); layout->addStretch(); layout->addWidget(m_searchBtn); layout->setAlignment(m_searchBtn, Qt::AlignCenter); layout->addWidget(m_placeHolder); layout->setAlignment(m_placeHolder, Qt::AlignCenter); layout->addWidget(m_edit); layout->setAlignment(m_edit, Qt::AlignCenter); layout->addWidget(m_pClearTextButton); layout->setAlignment(m_pClearTextButton,Qt::AlignCenter); layout->addStretch(); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setFocusPolicy(Qt::StrongFocus); connect(m_edit, &QLineEdit::textChanged, this, &MySearchEdit::textChanged, Qt::DirectConnection); } QPixmap MySearchEdit::drawSymbolicColoredPixmap(const QPixmap &source) { if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } } MySearchEdit::~MySearchEdit() { m_animation->deleteLater(); delete m_edit; delete m_searchBtn; delete m_placeHolder; if(fontSettings) { delete fontSettings; } if(qtSettings) { delete qtSettings; } } const QString MySearchEdit::searchedText() const { return m_edit->text(); } void MySearchEdit::clearAndFocusEdit() { this->clearEdit(); this->m_edit->setFocus(); } void MySearchEdit::clearEdit() { m_edit->clear(); this->setStyleSheet("QFrame{background:rgba(77,88,99,0.08);border-radius:4px;}"); } void MySearchEdit::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) return QFrame::mousePressEvent(event); setEditFocus(); event->accept(); } void MySearchEdit::mouseReleaseEvent(QMouseEvent *event) { event->accept(); } bool MySearchEdit::eventFilter(QObject *object, QEvent *event) { if (object == m_edit && event->type() == QEvent::FocusOut && m_edit->text().isEmpty()) { auto focusEvent = dynamic_cast(event); if (focusEvent && focusEvent->reason() != Qt::PopupFocusReason) { // m_placeHolder->show(); m_animation->stop(); m_animation->setStartValue(m_edit->width()); m_animation->setEndValue(0); m_animation->setEasingCurve(m_hideCurve); m_animation->start(); connect(m_animation, &QPropertyAnimation::finished, m_placeHolder, &QLabel::show); } } return QFrame::eventFilter(object, event); } void MySearchEdit::setEditFocus() { if (!m_placeHolder->isVisible()) { return; } disconnect(m_animation, &QPropertyAnimation::finished, m_placeHolder, &QLabel::show); m_animation->stop(); m_animation->setStartValue(0); m_animation->setEndValue(m_size.width() - m_searchBtn->width() - 6); m_animation->setEasingCurve(m_showCurve); m_animation->start(); m_placeHolder->hide(); m_edit->setFocus(); } void MySearchEdit::setPlaceHolder(const QString &text) { m_placeHolder->setText(text); } void MySearchEdit::setText(const QString & text) { if (m_edit) { m_edit->setText(text); } } QLineEdit *MySearchEdit::getLineEdit() const { return m_edit; } void MySearchEdit::resizeEvent(QResizeEvent *event) { m_size = event->size(); m_edit->setFixedHeight(m_size.height()); } bool MySearchEdit::event(QEvent *event) { if (event->type() == QEvent::FocusIn) { const QFocusEvent *ev = static_cast(event); if (ev->reason() == Qt::TabFocusReason || ev->reason() == Qt::BacktabFocusReason || ev->reason() == Qt::OtherFocusReason || ev->reason() == Qt::ShortcutFocusReason) { setEditFocus(); } } return QFrame::event(event); } void MySearchEdit::textChageSlots(const QString &text) { if (text != "") { m_pClearTextButton ->setVisible(true); } else { m_pClearTextButton->setVisible(false); } } void MySearchEdit::initThemeMode() { if (!qtSettings) { // qWarning() << "Failed to load the gsettings: " << THEME_QT_SCHEMA; return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key){ if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); m_pClearTextButton->setIcon(drawSymbolicColoredPixmap(QPixmap::fromImage(QIcon::fromTheme(":/img/button-close-default-add-background-three.svg").pixmap(24,24).toImage()))); if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { m_edit->setStyleSheet("QLineEdit{background:transparent;border-radius:4px;color:#000000;padding-right:12px;padding-bottom: 2px;}"); //#CC00FF transparent m_placeHolder->setStyleSheet("QLabel{background-color:transparent;color:rgba(0,0,0,0.57);margin: 2 0 0 0 px;}"); this->setObjectName("SearchBtn"); this->setStyleSheet("QFrame#SearchBtn{background:rgba(13,14,14,0.08);border-radius:4px;}"); } if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_edit->setStyleSheet("QLineEdit{background:transparent;border-radius:4px;color:#FFFFFF;padding-right:12px;padding-bottom: 2px;}"); //#CC00FF transparent m_placeHolder->setStyleSheet("QLabel{background-color:transparent;color:rgba(255,255,255,0.57);margin: 2 0 0 0 px;}"); this->setObjectName("SearchBtn"); this->setStyleSheet("QFrame#SearchBtn{background:rgba(255,255,255,0.08);border-radius:4px;}"); } } }); //获取当前主题 currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); m_pClearTextButton->setIcon(drawSymbolicColoredPixmap(QPixmap::fromImage(QIcon::fromTheme(":/img/button-close-default-add-background-three.svg").pixmap(24,24).toImage()))); if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { m_edit->setStyleSheet("QLineEdit{background:transparent;border-radius:4px;color:#000000;padding-right:12px;padding-bottom: 2px;}"); //#CC00FF transparent m_placeHolder->setStyleSheet("QLabel{background-color:transparent;color:rgba(0,0,0,0.57);margin: 2 0 0 0 px;}"); this->setObjectName("SearchBtn"); this->setStyleSheet("QFrame#SearchBtn{background:rgba(13,14,14,0.08);border-radius:4px;}"); } if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_edit->setStyleSheet("QLineEdit{background:transparent;border-radius:4px;color:#FFFFFF;padding-right:12px;padding-bottom: 2px;}"); //#CC00FF transparent m_placeHolder->setStyleSheet("QLabel{background-color:transparent;color:rgba(255,255,255,0.57);margin: 2 0 0 0 px;}"); this->setObjectName("SearchBtn"); this->setStyleSheet("QFrame#SearchBtn{background:rgba(255,255,255,0.08);border-radius:4px;}"); } } void MySearchEdit::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } QFont font; font.setPointSize(fontSize - 2); m_placeHolder->setFont(font); QFont searchLineFont; searchLineFont.setPointSize(fontSize); m_edit->setFont(searchLineFont); }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } ukui-system-monitor/widgets/myactiongroup.cpp0000644000175000017500000000442413746753504020556 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "myactiongroup.h" #include #include #include MyActionGroup::MyActionGroup( QObject * parent ) : QActionGroup(parent) { setExclusive(true); connect(this, SIGNAL(triggered(QAction *)), this, SLOT(itemTriggered(QAction *)) ); } void MyActionGroup::setChecked(int ID) { QList l = actions(); for (int n=0; n < l.count(); n++) { if ( (!l[n]->isSeparator()) && (l[n]->data().toInt() == ID) ) { l[n]->setChecked(true); return; } } } int MyActionGroup::checked() { QAction * a = checkedAction(); if (a) return a->data().toInt(); else return -1; } void MyActionGroup::uncheckAll() { QList l = actions(); for (int n=0; n < l.count(); n++) { l[n]->setChecked(false); } } void MyActionGroup::setActionsEnabled(bool b) { QList l = actions(); for (int n=0; n < l.count(); n++) { l[n]->setEnabled(b); } } void MyActionGroup::clear(bool remove) { while (actions().count() > 0) { QAction * a = actions()[0]; if (a) { removeAction(a); if (remove) a->deleteLater(); } } } void MyActionGroup::itemTriggered(QAction *a) { int value = a->data().toInt(); emit activated(value); } void MyActionGroup::addTo(QWidget *w) { w->addActions( actions() ); } void MyActionGroup::removeFrom(QWidget *w) { for (int n=0; n < actions().count(); n++) { w->removeAction( actions()[n] ); } } ukui-system-monitor/widgets/myactiongroup.h0000644000175000017500000000241713746753504020223 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef _MYACTIONGROUP_H_ #define _MYACTIONGROUP_H_ #include #include #include "myaction.h" class MyActionGroup : public QActionGroup { Q_OBJECT public: MyActionGroup ( QObject * parent ); void setChecked(int ID); int checked(); void clear(bool remove); void setActionsEnabled(bool); void addTo(QWidget *); void removeFrom(QWidget *); void uncheckAll(); signals: void activated(int); protected slots: void itemTriggered(QAction *); }; #endif ukui-system-monitor/widgets/myunderlinebutton.cpp0000644000175000017500000002537513763560717021456 0ustar fengfeng/* * Copyright (C) 2020 KylinSoft Co., Ltd. * * Authors: * Kobe Lee xiangli@ubuntukylin.com/kobe24_lixiang@126.com * * 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "myunderlinebutton.h" #include #include #include #include MyUnderLineButton::MyUnderLineButton(QWidget *parent) : QWidget(parent) ,m_state(Normal) ,m_isChecked(false) ,fontSettings(nullptr) ,qtSettings(nullptr) { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } this->setFixedSize(NORMALWIDTH, NORMALHEIGHT+2); m_textLabel = new QLabel; initThemeMode(); initFontSize(); m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->addWidget(m_textLabel, 0, Qt::AlignVCenter| Qt::AlignCenter); } void MyUnderLineButton::initThemeMode() { if (!qtSettings) { // qWarning() << "Failed to load the gsettings: " << THEME_QT_SCHEMA; return; } //监听主题改变 connect(qtSettings, &QGSettings::changed, this, [=](const QString &key) { if (key == "styleName") { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); if (currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(0,0,0,0.57);text-align:center;}"); //ffffff } if (currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(255,255,255,0.57); text-align:center;}"); //ffffff } } }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); if (currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(0,0,0,0.57); text-align:center;}"); //ffffff } if (currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(255,255,255,0.57); font-size:20px;text-align:center;}"); //ffffff } } void MyUnderLineButton::initFontSize() { if (!fontSettings) { fontSize = DEFAULT_FONT_SIZE; return; } connect(fontSettings, &QGSettings::changed, [=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); } // repaint(); QFont font; font.setPointSize(fontSize -2); m_textLabel->setFont(font); }); fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); QFont font; font.setPointSize(fontSize -2); m_textLabel->setFont(font); } MyUnderLineButton::~MyUnderLineButton() { delete m_textLabel; //delete m_underlineLabel; if(fontSettings) { delete fontSettings; } if(qtSettings) { delete qtSettings; } } void MyUnderLineButton::enterEvent(QEvent *event) { setCursor(Qt::PointingHandCursor); if (!m_isChecked){ setState(Normal); } event->accept(); //QWidget::enterEvent(event); } void MyUnderLineButton::leaveEvent(QEvent *event) { if (!m_isChecked){ setState(Normal); } event->accept(); //QWidget::leaveEvent(event); } void MyUnderLineButton::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) return; setState(Press); event->accept(); //QWidget::mousePressEvent(event); } void MyUnderLineButton::mouseReleaseEvent(QMouseEvent *event) { if (!rect().contains(event->pos())) return; m_isChecked = !m_isChecked; if (m_isChecked){ setState(Checked); } else { setState(Normal); } event->accept(); //QWidget::mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) emit clicked(); } void MyUnderLineButton::mouseMoveEvent(QMouseEvent *event) { if (!rect().contains(event->pos())) { setState(Normal); } } void MyUnderLineButton::updateStyleSheet() { QFont font; font.setPointSize(fontSize - 3); m_textLabel->setFont(font); switch (m_state) { // case Hover: // m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:#778899; font-size:14px;text-align:center;font-weight:bold;}"); // //m_underlineLabel->hide(); // break; case Press: this->setObjectName("OnlyBackground"); this->setStyleSheet("onlyBackground#QPushButton{background:#3d6be5;}"); m_textLabel->setStyleSheet("QLabel{background-color:#3d6be5;color:#ffffff; text-align:center;font-weight:bold;}"); //m_underlineLabel->hide(); break; case Normal: if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(0,0,0,0.57); text-align:center;}"); } else { m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:rgba(255,255,255,0.57); text-align:center;}"); } // case Normal: // case Checked: // m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:778899; font-size:14px;text-align:center;font-weight:bold;}"); // //m_underlineLabel->show(); // break; // default: // m_textLabel->setStyleSheet("QLabel{background-color:transparent;color:778899; font-size:14px;text-align:center;}"); // //m_underlineLabel->hide(); // break; } // m_textLabel->setStyleSheet("QLabel{color:white};"); } void MyUnderLineButton::setState(MyUnderLineButton::ButtonState state) { if (m_state == state) return; m_state = state; updateStyleSheet(); } void MyUnderLineButton::setChecked(bool flag) /////////////////face the difficulties,then resolve them { m_isChecked = flag; if (m_isChecked){ setState(Press); } else { setState(Normal); } repaint(); } bool MyUnderLineButton::isChecked() { return m_isChecked; } void MyUnderLineButton::setName(const QString &name) { this->m_textLabel->setText(name); } MyUnderLineButton::ButtonState MyUnderLineButton::getButtonState() const { return m_state; } void MyUnderLineButton::paintEvent(QPaintEvent *event) { #if 0 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //// ////////set the background color // QPainterPath path; // path.addRect(QRectF(0, 0, width(), height())); //// painter.setOpacity(1); //// painter.fillPath(path, QColor("#0d87ca")); ////////Draw fillet QStyleOption opt; opt.init(this);CC00FF painter.setBrush(QBrush(QColor(0x3D,0x6B,0xE5,0xFF))); painter.setPen(Qt::NoPen); opt.rect.adjust(0,0,0,0); // path.addRoundedRect(opt.rect,4,4); painter.drawRoundedRect(opt.rect,4,4); // setProperty("blurRegion",QRegion(path.toFillPolygon().toPolygon())); style()->drawPrimitive(QStyle::PE_Widget,&opt,&painter,this); // painter.setPen(QPen(QColor("#e9eef0"), 0));//边框颜色 // painter.setBrush(QColor("#0d87ca"));//背景色 // //painter.setOpacity(1); // QRectF r(1, 1, width() - 2, height() - 2);//左边 上边 右边 下边 // painter.drawRoundedRect(r, 6, 6); #endif #if 1 QStyleOption opt; opt.init(this); QPainter p(this); switch(getButtonState()) { case Normal: { // p.setOpacity(0.57); if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui-white") { p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x19))); } else { p.setBrush(QBrush(QColor(0xff,0xff,0xff,0x19))); } p.setPen(Qt::NoPen); // QPainterPath path; opt.rect.adjust(0,0,0,0); // path.addRoundedRect(opt.rect,6,6); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); // p.setPen(QPen(QColor("#e9eef0"), 0));//边框颜色 // p.setBrush(QColor("#0d87ca"));//背景色 // QRectF r(1, 1, width() - 2, height() - 2);//左边 上边 右边 下边 p.drawRoundedRect(opt.rect, 6, 6); break; } case Press: { p.setBrush(QBrush(QColor(0x3D,0x6B,0xE5,0xFF))); //0x33,0x42,0x33,0x33 0x3D,0x6B,0xE5,0xFF p.setPen(Qt::NoPen); // p.setPen(QPen(QColor("#CC00FF"))); // QPainterPath path; opt.rect.adjust(0,0,0,0); // path.addRoundedRect(opt.rect,6,6); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); // p.setPen(QPen(QColor("#e9eef0"), 0));//边框颜色 // p.setBrush(QColor("#0d87ca"));//背景色 // QRectF r(1, 1, width() - 2, height() - 2);//左边 上边 右边 下边 p.drawRoundedRect(opt.rect, 6, 6); break; } // case Checked: // { // p.setBrush(QBrush(QColor(0x3D,0x6B,0xE5,0xFF))); //0x33,0x42,0x33,0x33 0x3D,0x6B,0xE5,0xFF //// p.setPen(Qt::NoPen); // // QPainterPath path; // opt.rect.adjust(0,0,0,0); // // path.addRoundedRect(opt.rect,6,6); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // // p.drawRoundedRect(opt.rect,6,6); // style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); // // p.setPen(QPen(QColor("#e9eef0"), 0));//边框颜色 // // p.setBrush(QColor("#0d87ca"));//背景色 // // QRectF r(1, 1, width() - 2, height() - 2);//左边 上边 右边 下边 // p.drawRoundedRect(opt.rect, 6, 6); // p.setPen(QPen(QColor("#CC00FF"))); // break; // } } #endif } ukui-system-monitor/README.md0000644000175000017500000000051313764070001014736 0ustar fengfeng# ukui-system-monitor UKUI System Monitor allows you to graphically view and manipulate the running processes, It also provides an overview of the resources (such as CPU and memory) and File Systems on your system. ## Build mkdir build qmake .. sudo make install ## Bug report https://github.com/ukui/ukui-system-monitor/issues ukui-system-monitor/data/0000755000175000017500000000000013746753570014414 5ustar fengfengukui-system-monitor/data/org.ukui.system-monitor.menu.gschema.xml0000644000175000017500000000056713746753570024272 0ustar fengfeng 0 Control which content to show of all components Control the menu of all components