diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 01:06:58 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 01:06:58 +0000 |
commit | ccceabd36ed168eefd785fb4fb720a577482fec1 (patch) | |
tree | 643927e0ff83170395fa3be8f50c69dae48be1ca /src | |
download | knemo-ccceabd36ed168eefd785fb4fb720a577482fec1.tar.gz knemo-ccceabd36ed168eefd785fb4fb720a577482fec1.zip |
Added KDE3 version of knemo
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/knemo@1091560 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
73 files changed, 10469 insertions, 0 deletions
diff --git a/src/COPYING-DOCS b/src/COPYING-DOCS new file mode 100644 index 0000000..4a0fe1c --- /dev/null +++ b/src/COPYING-DOCS @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/src/INSTALL.Mandrake b/src/INSTALL.Mandrake new file mode 100644 index 0000000..57419d4 --- /dev/null +++ b/src/INSTALL.Mandrake @@ -0,0 +1,40 @@ +These are installation instructions for Mandrake 10.0. + +They have been tested with Mandrake 10.0 Download Edition but should +also work for the Official Edition. + +The simplest way to compile KNemo for Mandrake is: + + 1. `cd' to the directory containing KNemos source code and type + `./configure --prefix=/usr' to configure the package for Mandrake. + + 2. Open the file `knemod\interfaceicon.cpp' and go to line 257. + Change the line from + + process << "kcmshell" << "kcm_knemo"; + + to + + process << "kcmshell" << "/usr/share/applnk/Settings/Network/kcm_knemo"; + + Do the same in line 64 of `knemod\knemodaemon.cpp' + + 3. Save your changes. + + 4. Type `make' to compile the package. + + 5. Type `make install' to install the programs and any data files and + documentation. + +Now you should be able start KNemo as a KDE Service and open its +configuration dialog from the context menu of the tray icon. + +IMPORTANT: If you already installed and started KNemo before doing the +above changes it may be neccessary to open the configuration dialog +manually by running + + kcmshell /usr/share/applnk/Settings/Network/kcm_knemo + +on the console after you have installed KNemo with the above solution, +because KNemo won't display any icons in the system traybar until it +is configured to do so. diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..67a0ea1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = kcm knemod + +#EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README TODO knemo.lsm + +#MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 configure.files + + +#messages: rc.cpp +# $(EXTRACTRC) `find . -name "*.ui"` >> rc.cpp +# $(EXTRACTRC) `find . -name "*.rc"` >> rc.cpp +# LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ +# if test -n "$$LIST"; then \ +# $(XGETTEXT) $$LIST -o $(podir)/knemo.pot; \ +# fi + +#include ../admin/Doxyfile.am + diff --git a/src/NEWS b/src/NEWS new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/NEWS @@ -0,0 +1 @@ + diff --git a/src/VERSION b/src/VERSION new file mode 100644 index 0000000..7e76520 --- /dev/null +++ b/src/VERSION @@ -0,0 +1 @@ +KNemo v0.4.8 diff --git a/src/common/data.h b/src/common/data.h new file mode 100644 index 0000000..e8de9a2 --- /dev/null +++ b/src/common/data.h @@ -0,0 +1,94 @@ +/* This file is part of KNemo + Copyright (C) 2004 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DATA_H +#define DATA_H + +#include <qstring.h> +#include <qvaluevector.h> + +/** + * This file contains data structures used to store information about + * an interface. It is shared between the daemon and the control center + * module. + * + * @short Shared data structures + * @author Percy Leonhardt <percy@eris23.de> + */ + +struct InterfaceCommand +{ + int id; + bool runAsRoot; + QString command; + QString menuText; +}; + +struct InterfaceSettings +{ + InterfaceSettings() + : iconSet( 0 ), + numCommands( 0 ), + trafficThreshold( 0 ), + hideWhenNotExisting( false ), + hideWhenNotAvailable( false ), + activateStatistics( false ), + customCommands( false ) + {} + + int iconSet; + int numCommands; + int trafficThreshold; + bool hideWhenNotExisting; + bool hideWhenNotAvailable; + bool activateStatistics; + bool customCommands; + QString alias; + QValueVector<InterfaceCommand> commands; +}; + +enum ToolTipEnums +{ + INTERFACE = 0x00000001, + ALIAS = 0x00000002, + STATUS = 0x00000004, + UPTIME = 0x00000008, + IP_ADDRESS = 0x00000010, + SUBNET_MASK = 0x00000020, + HW_ADDRESS = 0x00000040, + PTP_ADDRESS = 0x00000080, + RX_PACKETS = 0x00000100, + TX_PACKETS = 0x00000200, + RX_BYTES = 0x00000400, + TX_BYTES = 0x00000800, + ESSID = 0x00001000, + MODE = 0x00002000, + FREQUENCY = 0x00004000, + BIT_RATE = 0x00008000, + ACCESS_POINT = 0x00010000, + LINK_QUALITY = 0x00020000, + BCAST_ADDRESS = 0x00040000, + GATEWAY = 0x00080000, + DOWNLOAD_SPEED = 0x00100000, + UPLOAD_SPEED = 0x00200000, + NICK_NAME = 0x00400000, + ENCRYPTION = 0x00800000 +}; + +#endif // DATA_H diff --git a/src/configure.in.bot b/src/configure.in.bot new file mode 100644 index 0000000..75471e8 --- /dev/null +++ b/src/configure.in.bot @@ -0,0 +1,33 @@ +dnl put here things which have to be done as very last part of configure + +if test -z "$PATH_IFCONFIG"; then + echo "" + echo "You're missing the program 'ifconfig'." + echo "KNemo won't be able to run without it so please install 'ifconfig'" + echo "which is normally part of a package called 'net-tools' or similar" + echo "and run configure again." + echo "" + all_tests=bad +fi + +if test -z "$PATH_IWCONFIG"; then + echo "" + echo "You're missing the program 'iwconfig'." + echo "KNemo works without 'iwconfig' being installed but you won't be able" + echo "to monitor the wireless extensions of wireless interfaces." + echo "If you would like to have these additional features install" + echo "'iwconfig' which can be found in a package called 'wireless-tools'" + echo "or similar and run configure again." + echo "" +fi + +if test -z "$PATH_ROUTE"; then + echo "" + echo "You're missing the program 'route'." + echo "KNemo works without 'route' being installed but KNemo won't be able" + echo "to display the default gateway of an interface." + echo "If you would like to have this additional feature install" + echo "'route' which can be found in a package called 'net-tools'" + echo "or similar and run configure again." + echo "" +fi diff --git a/src/configure.in.in b/src/configure.in.in new file mode 100644 index 0000000..78547c8 --- /dev/null +++ b/src/configure.in.in @@ -0,0 +1,37 @@ + +AM_INIT_AUTOMAKE(knemo, 0.4.8) + +dnl These are common macros that you might or might not want to use + +dnl Image readers/writers +dnl If you want to use this test, you have to define it somewhere +dnl KDE_CHECK_KIMGIO + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_TIME +AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h stdlib.h paths.h) +AC_CHECK_FUNCS(usleep) +AC_CHECK_LIB(iw,iw_sockets_open) + +dnl Check path to ifconfig, iwconfig and route. + +AC_PATH_PROG([PATH_IFCONFIG],[ifconfig],, + [$PATH:/sbin:/usr/sbin:/usr/local/sbin]) +AC_PATH_PROG([PATH_IWCONFIG],[iwconfig],, + [$PATH:/sbin:/usr/sbin:/usr/local/sbin]) +AC_PATH_PROG([PATH_ROUTE],[route],, + [$PATH:/sbin:/usr/sbin:/usr/local/sbin]) +if test -n "${PATH_IFCONFIG}"; then + AC_SUBST([PATH_IFCONFIG]) + AC_DEFINE_UNQUOTED(PATH_IFCONFIG, "${PATH_IFCONFIG}", [Path of ifconfig program]) +fi +if test -n "${PATH_IWCONFIG}"; then + AC_SUBST([PATH_IWCONFIG]) + AC_DEFINE_UNQUOTED(PATH_IWCONFIG, "${PATH_IWCONFIG}", [Path of iwconfig program]) +fi +if test -n "${PATH_ROUTE}"; then + AC_SUBST([PATH_ROUTE]) + AC_DEFINE_UNQUOTED(PATH_ROUTE, "${PATH_ROUTE}", [Path of route program]) +fi diff --git a/src/kcm/Makefile.am b/src/kcm/Makefile.am new file mode 100644 index 0000000..15440a0 --- /dev/null +++ b/src/kcm/Makefile.am @@ -0,0 +1,28 @@ +## Makefile.am for kcm_knemo + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcm_knemo.pot + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kcm_knemo.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../common -I$(srcdir)/../knemod/backends $(all_includes) + +# the library search path. +kcm_knemo_la_LDFLAGS = -module -avoid-version $(all_libraries) + +# the libraries to link against. +kcm_knemo_la_LIBADD = $(LIB_KDEUI) + +# which sources should be compiled for knemo +kcm_knemo_la_SOURCES = configdialog.cpp configdlg.ui + +# these are the headers for your project +noinst_HEADERS = configdialog.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +xdg_apps_DATA = kcm_knemo.desktop diff --git a/src/kcm/configdialog.cpp b/src/kcm/configdialog.cpp new file mode 100644 index 0000000..9c5ca9a --- /dev/null +++ b/src/kcm/configdialog.cpp @@ -0,0 +1,1199 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qfile.h> +#include <qdict.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qcstring.h> +#include <qlistbox.h> +#include <qcheckbox.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qgroupbox.h> +#include <qwhatsthis.h> +#include <qtabwidget.h> +#include <qpushbutton.h> +#include <qstringlist.h> +#include <qdatastream.h> + +#include <kglobal.h> +#include <kconfig.h> +#include <klocale.h> +#include <knuminput.h> +#include <dcopclient.h> +#include <kiconloader.h> +#include <kfiledialog.h> +#include <kdesktopfile.h> +#include <kcolorbutton.h> +#include <kinputdialog.h> +#include <kapplication.h> +#include <knotifydialog.h> +#include <kstandarddirs.h> +#include <kgenericfactory.h> +#include <kdirselectdialog.h> + +#include "configdlg.h" +#include "kcmregistry.h" +#include "configdialog.h" + +const QString ConfigDialog::ICON_DISCONNECTED = "network_disconnected"; +const QString ConfigDialog::ICON_CONNECTED = "network_connected"; +const QString ConfigDialog::ICON_INCOMING = "network_incoming"; +const QString ConfigDialog::ICON_OUTGOING = "network_outgoing"; +const QString ConfigDialog::ICON_TRAFFIC = "network_traffic"; +const QString ConfigDialog::SUFFIX_PPP = "_ppp"; +const QString ConfigDialog::SUFFIX_LAN = "_lan"; +const QString ConfigDialog::SUFFIX_WLAN = "_wlan"; + +typedef KGenericFactory<ConfigDialog, QWidget> KNemoFactory; +K_EXPORT_COMPONENT_FACTORY( kcm_knemo, KNemoFactory("kcm_knemo") ) + +ConfigDialog::ConfigDialog( QWidget *parent, const char *name, const QStringList& ) + : KCModule( KNemoFactory::instance(), parent, name ), + mLock( false ), + mDlg( new ConfigDlg( this ) ), + mColorVLines( 0x04FB1D ), + mColorHLines( 0x04FB1D ), + mColorIncoming( 0x1889FF ), + mColorOutgoing( 0xFF7F08 ), + mColorBackground( 0x313031 ) +{ + KGlobal::locale()->insertCatalogue("kcm_knemo"); + setupToolTipArray(); + + // fill the backends combobox + for ( int i = 0; KCMRegistry[i].name != QString::null; i++ ) + { + mDlg->comboBoxBackends->insertItem( KCMRegistry[i].name ); + } + + load(); + + QVBoxLayout* top = new QVBoxLayout(this); + mDlg->pushButtonNew->setPixmap( SmallIcon( "filenew" ) ); + mDlg->pushButtonDelete->setPixmap( SmallIcon( "editdelete" ) ); + mDlg->pushButtonAddCommand->setPixmap( SmallIcon( "filenew" ) ); + mDlg->pushButtonRemoveCommand->setPixmap( SmallIcon( "editdelete" ) ); + mDlg->pushButtonUp->setPixmap( SmallIcon( "1uparrow" ) ); + mDlg->pushButtonDown->setPixmap( SmallIcon( "1downarrow" ) ); + mDlg->pushButtonAddToolTip->setPixmap( SmallIcon( "1rightarrow" ) ); + mDlg->pushButtonRemoveToolTip->setPixmap( SmallIcon( "1leftarrow" ) ); + mDlg->listViewCommands->setSorting( -1 ); + QWhatsThis::add( mDlg->listViewCommands, + i18n("<p>In this area you can add the custom entries " \ + "for your context menu: <ol><li>check <b>Display " \ + "custom entries in context menu</b>;</li>" \ + "<li>push on the <b>Add</b> button to add a new " \ + "entry in the list;</li><li>edit the entry by " \ + "double clicking in column <b>Menu text</b> and " \ + "<b>Command</b>;</li><li>start from step 2 for " \ + "every new entry</li>.</ol>If you need to execute " \ + "the command as root user check the corresponding " \ + "<b>Root</b> CheckBox.") ); + + mSettingsDict.setAutoDelete( true ); + setButtons( KCModule::Default | KCModule::Apply ); + + connect( mDlg->pushButtonNew, SIGNAL( clicked() ), + this, SLOT( buttonNewSelected() ) ); + connect( mDlg->pushButtonDelete, SIGNAL( clicked() ), + this, SLOT( buttonDeleteSelected() ) ); + connect( mDlg->pushButtonAddCommand, SIGNAL( clicked() ), + this, SLOT( buttonAddCommandSelected() ) ); + connect( mDlg->pushButtonRemoveCommand, SIGNAL( clicked() ), + this, SLOT( buttonRemoveCommandSelected() ) ); + connect( mDlg->pushButtonUp, SIGNAL( clicked() ), + this, SLOT( buttonCommandUpSelected() ) ); + connect( mDlg->pushButtonDown, SIGNAL( clicked() ), + this, SLOT( buttonCommandDownSelected() ) ); + connect( mDlg->pushButtonAddToolTip, SIGNAL( clicked() ), + this, SLOT( buttonAddToolTipSelected() ) ); + connect( mDlg->pushButtonRemoveToolTip, SIGNAL( clicked() ), + this, SLOT( buttonRemoveToolTipSelected() ) ); + connect( mDlg->pushButtonNotifications, SIGNAL( clicked() ), + this, SLOT( buttonNotificationsSelected() ) ); + connect( mDlg->pushButtonStatisticsDir, SIGNAL( clicked() ), + this, SLOT( buttonStatisticsDirSelected() ) ); + connect( mDlg->lineEditAlias, SIGNAL( textChanged( const QString& ) ), + this, SLOT( aliasChanged( const QString& ) ) ); + connect( mDlg->comboBoxIconSet, SIGNAL( activated( int ) ), + this, SLOT( iconSetChanged( int ) ) ); + connect( mDlg->comboBoxBackends, SIGNAL( activated( int ) ), + this, SLOT( backendChanged( int ) ) ); + connect( mDlg->checkBoxNotConnected, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxNotConnectedToggled ( bool ) ) ); + connect( mDlg->checkBoxNotExisting, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxNotExistingToggled ( bool ) ) ); + connect( mDlg->checkBoxStatistics, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxStatisticsToggled ( bool ) ) ); + connect( mDlg->checkBoxStartKNemo, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxStartKNemoToggled( bool ) ) ); + connect( mDlg->spinBoxTrafficThreshold, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxTrafficValueChanged ( int ) ) ); + connect( mDlg->checkBoxCustom, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxCustomToggled ( bool ) ) ); + connect( mDlg->listBoxInterfaces, SIGNAL( highlighted( const QString& ) ), + this, SLOT( interfaceSelected( const QString& ) ) ); + connect( mDlg->listViewCommands, SIGNAL( selectionChanged() ), + this, SLOT( listViewCommandsSelectionChanged() ) ); + connect( mDlg->listViewCommands, SIGNAL( itemRenamed( QListViewItem*, int, const QString& ) ), + this, SLOT( listViewCommandsRenamed( QListViewItem*, int, const QString& ) ) ); + + // connect the plotter widgets + connect( mDlg->checkBoxTopBar, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxLabels, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxVLines, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxHLines, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxIncoming, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxOutgoing, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxVLinesScroll, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->checkBoxAutoDetection, SIGNAL( toggled( bool ) ), + this, SLOT( checkBoxToggled( bool ) ) ); + connect( mDlg->spinBoxCount, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->spinBoxPixel, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->spinBoxDistance, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->spinBoxFontSize, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->spinBoxMinValue, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->spinBoxMaxValue, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->numInputPollInterval, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->numInputSaveInterval, SIGNAL( valueChanged( int ) ), + this, SLOT( spinBoxValueChanged( int ) ) ); + connect( mDlg->kColorButtonVLines, SIGNAL( changed( const QColor& ) ), + this, SLOT( kColorButtonChanged( const QColor& ) ) ); + connect( mDlg->kColorButtonHLines, SIGNAL( changed( const QColor& ) ), + this, SLOT( kColorButtonChanged( const QColor& ) ) ); + connect( mDlg->kColorButtonIncoming, SIGNAL( changed( const QColor& ) ), + this, SLOT( kColorButtonChanged( const QColor& ) ) ); + connect( mDlg->kColorButtonOutgoing, SIGNAL( changed( const QColor& ) ), + this, SLOT( kColorButtonChanged( const QColor& ) ) ); + connect( mDlg->kColorButtonBackground, SIGNAL( changed( const QColor& ) ), + this, SLOT( kColorButtonChanged( const QColor& ) ) ); + + // No dcop call if KNemo is not activated by the user. Otherwise + // load-on-demand will start KNemo. + if ( mDlg->checkBoxStartKNemo->isChecked() ) + { + // In case the user opened the control center via the context menu + // this call to the daemon will deliver the interface the menu + // belongs to. This way we can preselect the appropriate entry in the list. + QCString replyType; + QByteArray replyData, arg; + QString selectedInterface = QString::null; + if ( kapp->dcopClient()->call( "kded", "knemod", "getSelectedInterface()", arg, replyType, replyData ) ) + { + QDataStream reply( replyData, IO_ReadOnly ); + reply >> selectedInterface; + } + + if ( selectedInterface != QString::null ) + { + // Try to preselect the interface. + unsigned int i; + for ( i = 0; i < mDlg->listBoxInterfaces->count(); i++ ) + { + QListBoxItem* item = mDlg->listBoxInterfaces->item( i ); + if ( item->text() == selectedInterface ) + { + // Found it. + mDlg->listBoxInterfaces->setSelected( i, true ); + break; + } + } + if ( i == mDlg->listBoxInterfaces->count() ) + // Not found. Select first entry in list. + mDlg->listBoxInterfaces->setSelected( 0, true ); + } + else + // No interface from daemon. Select first entry in list. + mDlg->listBoxInterfaces->setSelected( 0, true ); + } + else + { + // Started from control center. Select first entry in list. + mDlg->listBoxInterfaces->setSelected( 0, true ); + } + + top->add( mDlg ); +} + +ConfigDialog::~ConfigDialog() +{ + delete mDlg; +} + +void ConfigDialog::load() +{ + mSettingsDict.clear(); + mDlg->listBoxInterfaces->clear(); + KConfig* config = new KConfig( "knemorc", true ); + + config->setGroup( "General" ); + bool startKNemo = config->readBoolEntry( "StartKNemo", false ); + mDlg->checkBoxStartKNemo->setChecked( startKNemo ); + mDlg->tabWidgetConfiguration->setEnabled( startKNemo ); + mDlg->numInputPollInterval->setValue( config->readNumEntry( "PollInterval", 1 ) ); + mDlg->numInputSaveInterval->setValue( config->readNumEntry( "SaveInterval", 60 ) ); + mDlg->lineEditStatisticsDir->setText( config->readEntry( "StatisticsDir", KGlobal::dirs()->saveLocation( "data", "knemo/" ) ) ); + mToolTipContent = config->readNumEntry( "ToolTipContent", 2 ); + + // select the backend from the config file + bool foundBackend = false; + QString backend = config->readEntry( "Backend", "Nettools" ); + int i; + for ( i = 0; KCMRegistry[i].name != QString::null; i++ ) + { + if ( KCMRegistry[i].name == backend ) + { + foundBackend = true; + break; + } + } + + if ( !foundBackend ) + { + i = 0; // use the first backend (Nettools) + } + mDlg->comboBoxBackends->setCurrentItem( i ); + mDlg->textLabelBackendDescription->setText( KCMRegistry[i].description ); + + QStrList list; + int numEntries = config->readListEntry( "Interfaces", list ); + + if ( numEntries == 0 ) + return; + + char* interface; + for ( interface = list.first(); interface; interface = list.next() ) + { + QString group( "Interface_" ); + group += interface; + InterfaceSettings* settings = new InterfaceSettings(); + if ( config->hasGroup( group ) ) + { + config->setGroup( group ); + settings->alias = config->readEntry( "Alias" ); + settings->iconSet = config->readNumEntry( "IconSet", 0 ); + settings->customCommands = config->readBoolEntry( "CustomCommands" ); + settings->hideWhenNotAvailable = config->readBoolEntry( "HideWhenNotAvailable" ); + settings->hideWhenNotExisting = config->readBoolEntry( "HideWhenNotExisting" ); + settings->activateStatistics = config->readBoolEntry( "ActivateStatistics" ); + settings->trafficThreshold = config->readNumEntry( "TrafficThreshold", 0 ); + int numCommands = config->readNumEntry( "NumCommands" ); + for ( int i = 0; i < numCommands; i++ ) + { + QString entry; + InterfaceCommand cmd; + entry = QString( "RunAsRoot%1" ).arg( i + 1 ); + cmd.runAsRoot = config->readBoolEntry( entry ); + entry = QString( "Command%1" ).arg( i + 1 ); + cmd.command = config->readEntry( entry ); + entry = QString( "MenuText%1" ).arg( i + 1 ); + cmd.menuText = config->readEntry( entry ); + settings->commands.append( cmd ); + } + } + mSettingsDict.insert( interface, settings ); + mDlg->listBoxInterfaces->insertItem( interface ); + } + + // enable or disable statistics entries + updateStatisticsEntries(); + + // Set the plotter widgets + config->setGroup( "PlotterSettings" ); + mDlg->spinBoxPixel->setValue( config->readNumEntry( "Pixel", 1 ) ); + mDlg->spinBoxCount->setValue( config->readNumEntry( "Count", 5 ) ); + mDlg->spinBoxDistance->setValue( config->readNumEntry( "Distance", 30 ) ); + mDlg->spinBoxFontSize->setValue( config->readNumEntry( "FontSize", 8 ) ); + mDlg->spinBoxMinValue->setValue( config->readNumEntry( "MinimumValue", 0 ) ); + mDlg->spinBoxMaxValue->setValue( config->readNumEntry( "MaximumValue", 1 ) ); + mDlg->checkBoxLabels->setChecked( config->readBoolEntry( "Labels", true ) ); + mDlg->checkBoxTopBar->setChecked( config->readBoolEntry( "TopBar", false ) ); + mDlg->checkBoxVLines->setChecked( config->readBoolEntry( "VerticalLines", true ) ); + mDlg->checkBoxHLines->setChecked( config->readBoolEntry( "HorizontalLines", true ) ); + mDlg->checkBoxIncoming->setChecked( config->readBoolEntry( "ShowIncoming", true ) ); + mDlg->checkBoxOutgoing->setChecked( config->readBoolEntry( "ShowOutgoing", true ) ); + mDlg->checkBoxAutoDetection->setChecked( config->readBoolEntry( "AutomaticDetection", true ) ); + mDlg->checkBoxVLinesScroll->setChecked( config->readBoolEntry( "VerticalLinesScroll", true ) ); + mDlg->kColorButtonVLines->setColor( config->readColorEntry( "ColorVLines", &mColorVLines ) ); + mDlg->kColorButtonHLines->setColor( config->readColorEntry( "ColorHLines", &mColorHLines ) ); + mDlg->kColorButtonIncoming->setColor( config->readColorEntry( "ColorIncoming", &mColorIncoming ) ); + mDlg->kColorButtonOutgoing->setColor( config->readColorEntry( "ColorOutgoing", &mColorOutgoing ) ); + mDlg->kColorButtonBackground->setColor( config->readColorEntry( "ColorBackground", &mColorBackground ) ); + + delete config; + + // These things need to be here so that 'Reset' from the control + // center is handled correctly. + setupToolTipTab(); +} + +void ConfigDialog::save() +{ + KConfig* config = new KConfig( "knemorc", false ); + + QStringList list; + QDictIterator<InterfaceSettings> it( mSettingsDict ); + for ( ; it.current(); ++it ) + { + list.append( it.currentKey() ); + InterfaceSettings* settings = it.current(); + config->setGroup( "Interface_" + it.currentKey() ); + if ( settings->alias.isEmpty() ) + config->deleteEntry( "Alias" ); + else + config->writeEntry( "Alias", settings->alias ); + config->writeEntry( "IconSet", settings->iconSet ); + config->writeEntry( "CustomCommands", settings->customCommands ); + config->writeEntry( "HideWhenNotAvailable", settings->hideWhenNotAvailable ); + config->writeEntry( "HideWhenNotExisting", settings->hideWhenNotExisting ); + config->writeEntry( "ActivateStatistics", settings->activateStatistics ); + config->writeEntry( "TrafficThreshold", settings->trafficThreshold ); + config->writeEntry( "NumCommands", settings->commands.size() ); + for ( uint i = 0; i < settings->commands.size(); i++ ) + { + QString entry; + entry = QString( "RunAsRoot%1" ).arg( i + 1 ); + config->writeEntry( entry, settings->commands[i].runAsRoot ); + entry = QString( "Command%1" ).arg( i + 1 ); + config->writeEntry( entry, settings->commands[i].command ); + entry = QString( "MenuText%1" ).arg( i + 1 ); + config->writeEntry( entry, settings->commands[i].menuText ); + } + } + + config->setGroup( "General" ); + config->writeEntry( "StartKNemo", mDlg->checkBoxStartKNemo->isChecked() ); + config->writeEntry( "PollInterval", mDlg->numInputPollInterval->value() ); + config->writeEntry( "SaveInterval", mDlg->numInputSaveInterval->value() ); + config->writeEntry( "StatisticsDir", mDlg->lineEditStatisticsDir->text() ); + config->writeEntry( "Backend", mDlg->comboBoxBackends->text( mDlg->comboBoxBackends->currentItem() ) ); + config->writeEntry( "ToolTipContent", mToolTipContent ); + config->writeEntry( "Interfaces", list ); + + config->setGroup( "PlotterSettings" ); + config->writeEntry( "Pixel", mDlg->spinBoxPixel->value() ); + config->writeEntry( "Count", mDlg->spinBoxCount->value() ); + config->writeEntry( "Distance", mDlg->spinBoxDistance->value() ); + config->writeEntry( "FontSize", mDlg->spinBoxFontSize->value() ); + config->writeEntry( "MinimumValue", mDlg->spinBoxMinValue->value() ); + config->writeEntry( "MaximumValue", mDlg->spinBoxMaxValue->value() ); + config->writeEntry( "Labels", mDlg->checkBoxLabels->isChecked() ); + config->writeEntry( "TopBar", mDlg->checkBoxTopBar->isChecked() ); + config->writeEntry( "VerticalLines", mDlg->checkBoxVLines->isChecked() ); + config->writeEntry( "HorizontalLines", mDlg->checkBoxHLines->isChecked() ); + config->writeEntry( "ShowIncoming", mDlg->checkBoxIncoming->isChecked() ); + config->writeEntry( "ShowOutgoing", mDlg->checkBoxOutgoing->isChecked() ); + config->writeEntry( "AutomaticDetection", mDlg->checkBoxAutoDetection->isChecked() ); + config->writeEntry( "VerticalLinesScroll", mDlg->checkBoxVLinesScroll->isChecked() ); + config->writeEntry( "ColorVLines", mDlg->kColorButtonVLines->color() ); + config->writeEntry( "ColorHLines", mDlg->kColorButtonHLines->color() ); + config->writeEntry( "ColorIncoming", mDlg->kColorButtonIncoming->color() ); + config->writeEntry( "ColorOutgoing", mDlg->kColorButtonOutgoing->color() ); + config->writeEntry( "ColorBackground", mDlg->kColorButtonBackground->color() ); + + config->sync(); + delete config; + + KDesktopFile* desktop = new KDesktopFile( "kded/knemod.desktop", false, "services" ); + if ( mDlg->checkBoxStartKNemo->isChecked() ) + { + // This call will implicitly start KNemo if it is not yet running. + kapp->dcopClient()->send( "kded", "knemod", "reparseConfiguration()", "" ); + desktop->writeEntry( "X-KDE-Kded-autoload", true ); + } + else + { + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << "knemod"; + kapp->dcopClient()->send("kded", "kded", "unloadModule(QCString)", data); + desktop->deleteEntry( "X-KDE-Kded-autoload" ); + } + desktop->sync(); + delete desktop; +} + +void ConfigDialog::defaults() +{ + // Default interfaces + QFile proc( "/proc/net/dev" ); + if ( proc.open( IO_ReadOnly ) ) + { + mSettingsDict.clear(); + mDlg->listBoxInterfaces->clear(); + + QString file = proc.readAll(); + QStringList content = QStringList::split( "\n", file ); + if ( content.count() > 2 ) + { + for ( unsigned int i = 2; i < content.count(); i++ ) + { + QString interface = content[i].simplifyWhiteSpace(); + interface = interface.left( interface.find( ':' ) ); + if ( interface == "lo" ) + continue; + + InterfaceSettings* settings = new InterfaceSettings(); + settings->customCommands = false; + settings->hideWhenNotAvailable = false; + settings->hideWhenNotExisting = false; + settings->activateStatistics = false; + mSettingsDict.insert( interface, settings ); + mDlg->listBoxInterfaces->insertItem( interface ); + } + if ( mDlg->listBoxInterfaces->count() > 0 ) + { + mDlg->listBoxInterfaces->setSelected( 0, true ); + } + else + { + mDlg->lineEditAlias->setText( QString::null ); + mDlg->comboBoxIconSet->setCurrentItem( 0 ); + mDlg->checkBoxNotConnected->setChecked( false ); + mDlg->checkBoxNotExisting->setChecked( false ); + mDlg->checkBoxStatistics->setChecked( false ); + mDlg->checkBoxCustom->setChecked( false ); + } + } + proc.close(); + } + + // Default misc settings + mDlg->numInputPollInterval->setValue( 1 ); + mDlg->numInputSaveInterval->setValue( 60 ); + mDlg->lineEditStatisticsDir->setText( KGlobal::dirs()->saveLocation( "data", "knemo/" ) ); + mDlg->comboBoxBackends->setCurrentItem( 0 ); + mDlg->textLabelBackendDescription->setText( KCMRegistry[0].description ); + + // Default tool tips + mToolTipContent = 2; + setupToolTipTab(); + + // Default plotter settings + mDlg->spinBoxPixel->setValue( 1 ); + mDlg->spinBoxCount->setValue( 5 ); + mDlg->spinBoxDistance->setValue( 30 ); + mDlg->spinBoxFontSize->setValue( 8 ); + mDlg->spinBoxMinValue->setValue( 0 ); + mDlg->spinBoxMaxValue->setValue( 1 ); + mDlg->checkBoxLabels->setChecked( true ); + mDlg->checkBoxTopBar->setChecked( false ); + mDlg->checkBoxVLines->setChecked( true ); + mDlg->checkBoxHLines->setChecked( true ); + mDlg->checkBoxIncoming->setChecked( true ); + mDlg->checkBoxOutgoing->setChecked( true ); + mDlg->checkBoxAutoDetection->setChecked( true ); + mDlg->checkBoxVLinesScroll->setChecked( true ); + mDlg->kColorButtonVLines->setColor( mColorVLines ); + mDlg->kColorButtonHLines->setColor( mColorHLines ); + mDlg->kColorButtonIncoming->setColor( mColorIncoming ); + mDlg->kColorButtonOutgoing->setColor( mColorOutgoing ); + mDlg->kColorButtonBackground->setColor( mColorBackground ); + + changed( true ); +} + +void ConfigDialog::buttonNewSelected() +{ + bool ok = false; + QString ifname = KInputDialog::getText( i18n( "Add new interface" ), + i18n( "Please enter the name of the interface to be monitored.\nIt should be something like 'eth1', 'wlan2' or 'ppp0'." ), + QString::null, + &ok ); + + if ( ok ) + { + mDlg->listBoxInterfaces->insertItem( ifname ); + mSettingsDict.insert( ifname, new InterfaceSettings() ); + mDlg->listBoxInterfaces->setSelected( mDlg->listBoxInterfaces->count() - 1, true ); + changed( true ); + } +} + +void ConfigDialog::buttonDeleteSelected() +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + // TODO: find a better way than blocking signals + mSettingsDict.remove( selected->text() ); + mDlg->lineEditAlias->blockSignals( true ); + mDlg->lineEditAlias->setText( QString::null ); + mDlg->lineEditAlias->blockSignals( false ); + mDlg->comboBoxIconSet->blockSignals( true ); + mDlg->comboBoxIconSet->setCurrentItem( 0 ); + mDlg->comboBoxIconSet->blockSignals( false ); + mDlg->checkBoxNotConnected->blockSignals( true ); + mDlg->checkBoxNotConnected->setChecked( false ); + mDlg->checkBoxNotConnected->blockSignals( false ); + mDlg->checkBoxNotExisting->blockSignals( true ); + mDlg->checkBoxNotExisting->setChecked( false ); + mDlg->checkBoxNotExisting->blockSignals( false ); + mDlg->checkBoxStatistics->blockSignals( true ); + mDlg->checkBoxStatistics->setChecked( false ); + mDlg->checkBoxStatistics->blockSignals( false ); + mDlg->checkBoxCustom->blockSignals( true ); + mDlg->checkBoxCustom->setChecked( false ); + mDlg->checkBoxCustom->blockSignals( false ); + mDlg->listBoxInterfaces->removeItem( mDlg->listBoxInterfaces->index( selected ) ); + changed( true ); +} + +void ConfigDialog::buttonAddCommandSelected() +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + KNemoCheckListItem* item = new KNemoCheckListItem( mDlg->listViewCommands ); + item->setRenameEnabled( 1, true ); + item->setRenameEnabled( 2, true ); + connect( item, SIGNAL( stateChanged( KNemoCheckListItem*, bool ) ), + this, SLOT( listViewCommandsCheckListItemChanged( KNemoCheckListItem*, bool ) ) ); + InterfaceSettings* settings = mSettingsDict[selected->text()]; + + QValueVector<InterfaceCommand> cmds; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + InterfaceCommand cmd; + cmd.runAsRoot = static_cast<KNemoCheckListItem*>( i )->isOn(); + cmd.menuText = i->text( 1 ); + cmd.command = i->text( 2 ); + cmds.append( cmd ); + } + + settings->commands = cmds; + if (!mLock) changed( true ); +} + +void ConfigDialog::buttonRemoveCommandSelected() +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + delete mDlg->listViewCommands->selectedItem(); + InterfaceSettings* settings = mSettingsDict[selected->text()]; + + QValueVector<InterfaceCommand> cmds; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + InterfaceCommand cmd; + cmd.runAsRoot = static_cast<KNemoCheckListItem*>( i )->isOn(); + cmd.menuText = i->text( 1 ); + cmd.command = i->text( 2 ); + cmds.append( cmd ); + } + + settings->commands = cmds; + if (!mLock) changed( true ); +} + +void ConfigDialog::buttonCommandUpSelected() +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + QListViewItem* item = mDlg->listViewCommands->selectedItem(); + if ( item ) + { + QListViewItem* previous = item->itemAbove(); + if ( previous ) + { + // We can move one up. + previous = previous->itemAbove(); + if ( previous ) + item->moveItem( previous ); + else + { + mDlg->listViewCommands->takeItem( item ); + mDlg->listViewCommands->insertItem( item ); + mDlg->listViewCommands->setSelected( item, true ); + } + } + } + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + + QValueVector<InterfaceCommand> cmds; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + InterfaceCommand cmd; + cmd.runAsRoot = static_cast<KNemoCheckListItem*>( i )->isOn(); + cmd.menuText = i->text( 1 ); + cmd.command = i->text( 2 ); + cmds.append( cmd ); + } + + settings->commands = cmds; + if (!mLock) changed( true ); +} + +void ConfigDialog::buttonCommandDownSelected() +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + QListViewItem* item = mDlg->listViewCommands->selectedItem(); + if ( item ) + { + QListViewItem* next = item->itemBelow(); + if ( next ) + { + // We can move one down. + item->moveItem( next ); + } + } + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + + QValueVector<InterfaceCommand> cmds; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + InterfaceCommand cmd; + cmd.runAsRoot = static_cast<KNemoCheckListItem*>( i )->isOn(); + cmd.menuText = i->text( 1 ); + cmd.command = i->text( 2 ); + cmds.append( cmd ); + } + + settings->commands = cmds; + if (!mLock) changed( true ); +} + +void ConfigDialog::buttonAddToolTipSelected() +{ + // Support extended selection + for ( int k = mDlg->listBoxAvailable->count() - 1; k >= 0; k-- ) + { + if ( !mDlg->listBoxAvailable->isSelected( k ) ) + continue; + + QListBoxItem* selected = mDlg->listBoxAvailable->item( k ); + + if ( selected == 0 ) + continue; + + // Find the index of the selected item in the tooltip array. + int itemIndex = 0; + for ( int i = 0; mToolTips[i].first != QString::null; i++ ) + { + if ( mToolTips[i].first == selected->text() ) + { + itemIndex = i; + break; + } + } + + // Find the first item in the display list which has a larger + // index in the tooltip array. We have to insert the selected + // item just before this one. + int newIndex = -1; + for ( unsigned int i = 0; i < mDlg->listBoxDisplay->count(); i++ ) + { + // For every item in the display list find its index in + // the tooltip array. + int siblingIndex = 0; + QListBoxItem* item = mDlg->listBoxDisplay->item( i ); + for ( int j = 0; mToolTips[j].first != QString::null; j++ ) + { + if ( mToolTips[j].first == item->text() ) + { + siblingIndex = j; + break; + } + } + + // Check if the index of this item is larger than the index + // of the selected item. + if ( siblingIndex > itemIndex ) + { + // Insert the selected item at position newIndex placing it + // directly in front of the sibling. + newIndex = i; + break; + } + } + + mDlg->listBoxAvailable->setSelected( selected, false ); + mDlg->listBoxAvailable->takeItem( selected ); + mDlg->listBoxDisplay->insertItem( selected, newIndex ); + if ( mDlg->listBoxAvailable->count() == 0 ) + mDlg->pushButtonAddToolTip->setEnabled( false ); + if ( mDlg->listBoxDisplay->count() == 1 ) + mDlg->pushButtonRemoveToolTip->setEnabled( true ); + + mToolTipContent += mToolTips[itemIndex].second; + changed( true ); + } +} + +void ConfigDialog::buttonRemoveToolTipSelected() +{ + // Support extended selection + for ( int k = mDlg->listBoxDisplay->count() - 1; k >= 0; k-- ) + { + if ( !mDlg->listBoxDisplay->isSelected( k ) ) + continue; + + QListBoxItem* selected = mDlg->listBoxDisplay->item( k ); + + if ( selected == 0 ) + continue; + + // Find the index of the selected item in the tooltip array. + int itemIndex = 0; + for ( int i = 0; mToolTips[i].first != QString::null; i++ ) + { + if ( mToolTips[i].first == selected->text() ) + { + itemIndex = i; + break; + } + } + + // Find the first item in the available list which has a larger + // index in the tooltip array. We have to insert the selected + // item just before this one. + int newIndex = -1; + for ( unsigned int i = 0; i < mDlg->listBoxAvailable->count(); i++ ) + { + // For every item in the available list find its index in + // the tooltip array. + int siblingIndex = 0; + QListBoxItem* item = mDlg->listBoxAvailable->item( i ); + for ( int j = 0; mToolTips[j].first != QString::null; j++ ) + { + if ( mToolTips[j].first == item->text() ) + { + siblingIndex = j; + break; + } + } + + // Check if the index of this item is larger than the index + // of the selected item. + if ( siblingIndex > itemIndex ) + { + // Insert the selected item at position newIndex placing it + // directly in front of the sibling. + newIndex = i; + break; + } + } + + mDlg->listBoxDisplay->setSelected( selected, false ); + mDlg->listBoxDisplay->takeItem( selected ); + mDlg->listBoxAvailable->insertItem( selected, newIndex ); + if ( mDlg->listBoxDisplay->count() == 0 ) + mDlg->pushButtonRemoveToolTip->setEnabled( false ); + if ( mDlg->listBoxAvailable->count() == 1 ) + mDlg->pushButtonAddToolTip->setEnabled( true ); + + mToolTipContent -= mToolTips[itemIndex].second; + changed( true ); + } +} + +void ConfigDialog::buttonNotificationsSelected() +{ + KNotifyDialog dialog( this ); + dialog.addApplicationEvents( "knemo" ); + dialog.exec(); +} + +void ConfigDialog:: buttonStatisticsDirSelected() +{ + KURL url = KDirSelectDialog::selectDirectory(); + if ( url.path() != QString::null ) + { + mDlg->lineEditStatisticsDir->setText( url.path() ); + changed( true ); + } +} + +void ConfigDialog::interfaceSelected( const QString& interface ) +{ + InterfaceSettings* settings = mSettingsDict[interface]; + mLock = true; + mDlg->lineEditAlias->setText( settings->alias ); + mDlg->comboBoxIconSet->setCurrentItem( settings->iconSet ); + mDlg->checkBoxCustom->setChecked( settings->customCommands ); + mDlg->checkBoxNotConnected->setChecked( settings->hideWhenNotAvailable ); + mDlg->checkBoxNotExisting->setChecked( settings->hideWhenNotExisting ); + mDlg->checkBoxStatistics->setChecked( settings->activateStatistics ); + mDlg->spinBoxTrafficThreshold->setValue( settings->trafficThreshold ); + + mDlg->listViewCommands->clear(); + for ( int i = settings->commands.size() - 1; i >= 0; i-- ) + { + KNemoCheckListItem* item = new KNemoCheckListItem( mDlg->listViewCommands ); + item->setOn( settings->commands[i].runAsRoot ); + item->setText( 1, settings->commands[i].menuText ); + item->setRenameEnabled( 1, true ); + item->setText( 2, settings->commands[i].command ); + item->setRenameEnabled( 2, true ); + connect( item, SIGNAL( stateChanged( KNemoCheckListItem*, bool ) ), + this, SLOT( listViewCommandsCheckListItemChanged( KNemoCheckListItem*, bool ) ) ); + } + + iconSetChanged( settings->iconSet ); // to update iconset preview + mLock = false; +} + +void ConfigDialog::aliasChanged( const QString& text ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->alias = text; + if (!mLock) changed( true ); +} + +void ConfigDialog::iconSetChanged( int set ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->iconSet = set; + + // Update the preview of the iconset. + QString suffix; + switch ( set ) + { + case NETWORK: + suffix = SUFFIX_LAN; + break; + case WIRELESS: + suffix = SUFFIX_WLAN; + break; + case MODEM: + suffix = SUFFIX_PPP; + break; + default: + suffix = ""; // use standard icons + } + + mDlg->pixmapDisconnected->setPixmap( SmallIcon( ICON_DISCONNECTED + suffix ) ); + mDlg->pixmapConnected->setPixmap( SmallIcon( ICON_CONNECTED + suffix ) ); + mDlg->pixmapIncoming->setPixmap( SmallIcon( ICON_INCOMING + suffix ) ); + mDlg->pixmapOutgoing->setPixmap( SmallIcon( ICON_OUTGOING + suffix ) ); + mDlg->pixmapTraffic->setPixmap( SmallIcon( ICON_TRAFFIC + suffix ) ); + if (!mLock) changed( true ); +} + +void ConfigDialog::backendChanged( int backend ) +{ + mDlg->textLabelBackendDescription->setText( KCMRegistry[backend].description ); + if (!mLock) changed( true ); +} + +void ConfigDialog::checkBoxNotConnectedToggled( bool on ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->hideWhenNotAvailable = on; + if (!mLock) changed( true ); +} + +void ConfigDialog::checkBoxNotExistingToggled( bool on ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->hideWhenNotExisting = on; + if (!mLock) changed( true ); +} + + +void ConfigDialog::checkBoxStatisticsToggled( bool on ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->activateStatistics = on; + if (!mLock) changed( true ); + + // enable or disable statistics entries + updateStatisticsEntries(); +} + +void ConfigDialog::checkBoxStartKNemoToggled( bool on ) +{ + if ( on ) + { + KConfig* config = new KConfig( "knemorc", false ); + config->setGroup( "General" ); + if ( config->readBoolEntry( "FirstStart", true ) ) + { + config->writeEntry( "FirstStart", false ); + config->sync(); + delete config; + + // Populate the dialog with some default values if the user starts + // KNemo for the very first time. + defaults(); + } + } + + if (!mLock) changed( true ); +} + +void ConfigDialog::spinBoxTrafficValueChanged( int value ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->trafficThreshold = value; + if (!mLock) changed( true ); +} + +void ConfigDialog::checkBoxCustomToggled( bool on ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + InterfaceSettings* settings = mSettingsDict[selected->text()]; + settings->customCommands = on; + if ( on ) + if ( mDlg->listViewCommands->selectedItem() ) + mDlg->pushButtonRemoveCommand->setEnabled( true ); + else + mDlg->pushButtonRemoveCommand->setEnabled( false ); + + if (!mLock) changed( true ); +} + +void ConfigDialog::setupToolTipTab() +{ + mDlg->listBoxDisplay->clear(); + mDlg->listBoxAvailable->clear(); + + for ( int i = 0; mToolTips[i].first != QString::null; i++ ) + { + if ( mToolTipContent & mToolTips[i].second ) + mDlg->listBoxDisplay->insertItem( mToolTips[i].first ); + else + mDlg->listBoxAvailable->insertItem( mToolTips[i].first ); + } + + if ( mDlg->listBoxDisplay->count() > 0 ) + { + mDlg->listBoxDisplay->setSelected( 0, true ); + mDlg->pushButtonRemoveToolTip->setEnabled( true ); + } + else + mDlg->pushButtonRemoveToolTip->setEnabled( false ); + + if ( mDlg->listBoxAvailable->count() > 0 ) + { + mDlg->listBoxAvailable->setSelected( 0, true ); + mDlg->pushButtonAddToolTip->setEnabled( true ); + } + else + mDlg->pushButtonAddToolTip->setEnabled( false ); +} + +void ConfigDialog::setupToolTipArray() +{ + // Cannot make this data static as the i18n macro doesn't seem + // to work when called to early i.e. before setting the catalogue. + mToolTips[0] = QPair<QString, int>( i18n( "Interface" ), INTERFACE ); + mToolTips[1] = QPair<QString, int>( i18n( "Alias" ), ALIAS ); + mToolTips[2] = QPair<QString, int>( i18n( "Status" ), STATUS ); + mToolTips[3] = QPair<QString, int>( i18n( "Uptime" ), UPTIME ); + mToolTips[4] = QPair<QString, int>( i18n( "IP-Address" ), IP_ADDRESS ); + mToolTips[5] = QPair<QString, int>( i18n( "Subnet Mask" ), SUBNET_MASK ); + mToolTips[6] = QPair<QString, int>( i18n( "HW-Address" ), HW_ADDRESS ); + mToolTips[7] = QPair<QString, int>( i18n( "Broadcast Address" ), BCAST_ADDRESS ); + mToolTips[8] = QPair<QString, int>( i18n( "Default Gateway" ), GATEWAY ); + mToolTips[9] = QPair<QString, int>( i18n( "PtP-Address" ), PTP_ADDRESS ); + mToolTips[10] = QPair<QString, int>( i18n( "Packets Received" ), RX_PACKETS ); + mToolTips[11] = QPair<QString, int>( i18n( "Packets Sent" ), TX_PACKETS ); + mToolTips[12] = QPair<QString, int>( i18n( "Bytes Received" ), RX_BYTES ); + mToolTips[13] = QPair<QString, int>( i18n( "Bytes Sent" ), TX_BYTES ); + mToolTips[14] = QPair<QString, int>( i18n( "Download Speed" ), DOWNLOAD_SPEED ); + mToolTips[15] = QPair<QString, int>( i18n( "Upload Speed" ), UPLOAD_SPEED ); + mToolTips[16] = QPair<QString, int>( i18n( "ESSID" ), ESSID ); + mToolTips[17] = QPair<QString, int>( i18n( "Mode" ), MODE ); + mToolTips[18] = QPair<QString, int>( i18n( "Frequency" ), FREQUENCY ); + mToolTips[19] = QPair<QString, int>( i18n( "Bit Rate" ), BIT_RATE ); + mToolTips[20] = QPair<QString, int>( i18n( "Access Point" ), ACCESS_POINT ); + mToolTips[21] = QPair<QString, int>( i18n( "Link Quality" ), LINK_QUALITY ); + mToolTips[22] = QPair<QString, int>( i18n( "Nickname" ), NICK_NAME ); + mToolTips[23] = QPair<QString, int>( i18n( "Encryption" ), ENCRYPTION ); + mToolTips[24] = QPair<QString, int>(); +} + +void ConfigDialog::updateStatisticsEntries( void ) +{ + bool statisticsActive = false; + QDictIterator<InterfaceSettings> it( mSettingsDict ); + for ( ; it.current(); ++it ) + { + if ( it.current()->activateStatistics ) + { + statisticsActive = true; + break; + } + } + + mDlg->groupBoxStatistics->setEnabled( statisticsActive ); + mDlg->groupBoxUpdateInterval->setEnabled( statisticsActive ); +} + +void ConfigDialog::checkBoxToggled( bool ) +{ + changed( true ); +} + +void ConfigDialog::spinBoxValueChanged( int ) +{ + changed( true ); +} + +void ConfigDialog::kColorButtonChanged( const QColor& ) +{ + changed( true ); +} + +void ConfigDialog::listViewCommandsSelectionChanged() +{ + QListViewItem* item = mDlg->listViewCommands->selectedItem(); + if ( item ) + mDlg->pushButtonRemoveCommand->setEnabled( true ); + else + mDlg->pushButtonRemoveCommand->setEnabled( false ); +} + +void ConfigDialog::listViewCommandsCheckListItemChanged( KNemoCheckListItem* item, bool state ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + // Find the row of the item. + int row = 0; + bool foundItem = false; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + if ( i == item ) + { + foundItem = true; + break; + } + row++; + } + + if ( foundItem ) + { + InterfaceSettings* settings = mSettingsDict[selected->text()]; + InterfaceCommand& cmd = settings->commands[row]; + cmd.runAsRoot = state; + + if (!mLock) changed( true ); + } +} + +void ConfigDialog::listViewCommandsRenamed( QListViewItem* item, int col, const QString & text ) +{ + QListBoxItem* selected = mDlg->listBoxInterfaces->selectedItem(); + + if ( selected == 0 ) + return; + + // Find the row of the item. + int row = 0; + bool foundItem = false; + QListViewItem* i = mDlg->listViewCommands->firstChild(); + for ( ; i != 0; i = i->nextSibling() ) + { + if ( i == item ) + { + foundItem = true; + break; + } + row++; + } + + if ( foundItem ) + { + InterfaceSettings* settings = mSettingsDict[selected->text()]; + InterfaceCommand& cmd = settings->commands[row]; + if ( col == 1 ) + cmd.menuText = text; + else if ( col == 2 ) + cmd.command = text; + + if (!mLock) changed( true ); + } +} + +#include "configdialog.moc" diff --git a/src/kcm/configdialog.h b/src/kcm/configdialog.h new file mode 100644 index 0000000..a4ff764 --- /dev/null +++ b/src/kcm/configdialog.h @@ -0,0 +1,150 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2005, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CONFIGDIALOG_H +#define CONFIGDIALOG_H + +#include <qdict.h> +#include <qpair.h> +#include <qstring.h> +#include <qlistview.h> + +#include <kcmodule.h> + +#include "data.h" + +class QTimer; +class ConfigDlg; +class KNemoCheckListItem; + +/** + * This is the configuration dialog for KNemo + * It is implemented as a control center module so that it is still + * possible to configure KNemo even when there is no icon visible + * in the system tray. + * + * @short Configuration dialog for KNemo + * @author Percy Leonhardt <percy@eris23.de> + */ + +class ConfigDialog : public KCModule +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + ConfigDialog( QWidget *parent, const char *name, const QStringList& ); + + /** + * Default Destructor + */ + virtual ~ConfigDialog(); + + void load(); + void save(); + void defaults(); + +private slots: + void buttonNewSelected(); + void buttonDeleteSelected(); + void buttonAddCommandSelected(); + void buttonRemoveCommandSelected(); + void buttonCommandUpSelected(); + void buttonCommandDownSelected(); + void buttonAddToolTipSelected(); + void buttonRemoveToolTipSelected(); + void buttonNotificationsSelected(); + void buttonStatisticsDirSelected(); + void interfaceSelected( const QString& interface ); + void aliasChanged( const QString& text ); + void iconSetChanged( int set ); + void backendChanged( int set ); + void checkBoxNotConnectedToggled( bool on ); + void checkBoxNotExistingToggled( bool on ); + void checkBoxStatisticsToggled( bool on ); + void checkBoxStartKNemoToggled( bool on ); + void spinBoxTrafficValueChanged( int value ); + void checkBoxCustomToggled( bool on ); + void listViewCommandsSelectionChanged(); + void listViewCommandsCheckListItemChanged( KNemoCheckListItem* item, bool state ); + void listViewCommandsRenamed( QListViewItem* item, int col, const QString & text ); + + /** + * These three are generic. + * They are used for all plotter settings to activate the + * 'Apply' button when something was changed by the user. + */ + void checkBoxToggled( bool ); + void spinBoxValueChanged( int ); + void kColorButtonChanged( const QColor& ); + +private: + void setupToolTipTab(); + void setupToolTipArray(); + void updateStatisticsEntries( void ); + + enum IconSet + { + MONITOR = 0, + MODEM, + NETWORK, + WIRELESS + }; + + int mToolTipContent; + bool mLock; + ConfigDlg* mDlg; + QColor mColorVLines; + QColor mColorHLines; + QColor mColorIncoming; + QColor mColorOutgoing; + QColor mColorBackground; + QDict<InterfaceSettings> mSettingsDict; + QPair<QString, int> mToolTips[25]; + + static const QString ICON_DISCONNECTED; + static const QString ICON_CONNECTED; + static const QString ICON_INCOMING; + static const QString ICON_OUTGOING; + static const QString ICON_TRAFFIC; + static const QString SUFFIX_PPP; + static const QString SUFFIX_LAN; + static const QString SUFFIX_WLAN; +}; + +class KNemoCheckListItem : public QObject, public QCheckListItem +{ + Q_OBJECT +public: + KNemoCheckListItem( QListView* view ) + : QCheckListItem( view, QString::null, QCheckListItem::CheckBox ) + {} + +signals: + void stateChanged( KNemoCheckListItem*, bool ); + +protected: + void stateChange( bool state ) + { + emit stateChanged( this, state ); + } +}; + +#endif // CONFIGDIALOG_H diff --git a/src/kcm/configdlg.ui b/src/kcm/configdlg.ui new file mode 100644 index 0000000..6c578ad --- /dev/null +++ b/src/kcm/configdlg.ui @@ -0,0 +1,1299 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigDlg</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>447</width> + <height>465</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxStartKNemo</cstring> + </property> + <property name="text"> + <string>Use KNemo to monitor your interfaces</string> + </property> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidgetConfiguration</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>interfaces</cstring> + </property> + <attribute name="title"> + <string>&Interfaces</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="1" column="0"> + <property name="name"> + <cstring>pushButtonNew</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Add a new interface</string> + </property> + </widget> + <widget class="QListBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>listBoxInterfaces</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>This is the list of icons you wish to monitor. Please +use the names understood by the command 'ifconfig', +for example 'eth0', 'wlan0' or 'ppp0'.</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>pushButtonDelete</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Delete the selected interface</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="1"> + <property name="name"> + <cstring>groupBox6</cstring> + </property> + <property name="title"> + <string>&Context Menu</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>checkBoxCustom</cstring> + </property> + <property name="text"> + <string>&Display custom entries in context menu</string> + </property> + </widget> + <widget class="QListView" row="1" column="0"> + <column> + <property name="text"> + <string>Root</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Menu text</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Command</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>listViewCommands</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="resizeMode"> + <enum>LastColumn</enum> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="1"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButtonAddCommand</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Add a new entry</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButtonRemoveCommand</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Remove the selected entry</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>61</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButtonUp</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Move the selected entry up</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButtonDown</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Move the selected entry down</string> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="0" column="1"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Misce&llaneous</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Alias:</string> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>lineEditAlias</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>You can enter an alias for the interface. +It will be used in the tooltip of the system +tray icon for better differentiation of the +icons.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxNotConnected</cstring> + </property> + <property name="text"> + <string>Hide icon when &not connected</string> + </property> + <property name="whatsThis" stdset="0"> + <string>When selected the icon for this interface will be +hidden when the interface is not connected. +When reconnected the icon will be shown again.</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer4_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxNotExisting</cstring> + </property> + <property name="text"> + <string>Hide icon &when not existing</string> + </property> + <property name="whatsThis" stdset="0"> + <string>When selected the icon for this interface will be +hidden when the interface does not exist. +This is useful for interfaces that are dynamically +created and destroyed, for example interfaces +of bluetooth adaptors.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxStatistics</cstring> + </property> + <property name="text"> + <string>Activate statistics</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7_2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string>Traffic activity threshold:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Use this for networks with high noise i.e. many packets coming in and out all the time. Set this value high enough so that KNemo won't show incoming and outgoing traffic all the time.</string> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>spinBoxTrafficThreshold</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="suffix"> + <string> packets/s</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Iconset:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Monitor</string> + </property> + </item> + <item> + <property name="text"> + <string>Modem</string> + </property> + </item> + <item> + <property name="text"> + <string>Network</string> + </property> + </item> + <item> + <property name="text"> + <string>Wireless</string> + </property> + </item> + <property name="name"> + <cstring>comboBoxIconSet</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pixmapDisconnected</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pixmapConnected</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pixmapIncoming</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pixmapOutgoing</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>pixmapTraffic</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tooltip</cstring> + </property> + <attribute name="title"> + <string>&ToolTip</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string><b>Note: Adding wireless specific information will only show up in the tooltips +of wireless devices not in the tooltips of standard interfaces.</b></string> + </property> + </widget> + <spacer row="3" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>129</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="2" column="1"> + <property name="name"> + <cstring>pushButtonRemoveToolTip</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Remove the selected entry from the list of displayed information</string> + </property> + </widget> + <spacer row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>70</width> + <height>130</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="2" column="2"> + <property name="name"> + <cstring>pushButtonAddToolTip</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Add the selected entry to the list of displayed information.</string> + </property> + </widget> + <widget class="QListBox" row="1" column="0" rowspan="3" colspan="1"> + <property name="name"> + <cstring>listBoxAvailable</cstring> + </property> + <property name="selectionMode"> + <enum>Extended</enum> + </property> + </widget> + <widget class="QListBox" row="1" column="3" rowspan="3" colspan="1"> + <property name="name"> + <cstring>listBoxDisplay</cstring> + </property> + <property name="selectionMode"> + <enum>Extended</enum> + </property> + </widget> + <widget class="QLabel" row="0" column="3"> + <property name="name"> + <cstring>textLabel2_3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Display:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Available:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>misc</cstring> + </property> + <attribute name="title"> + <string>&Misc</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox6_2</cstring> + </property> + <property name="title"> + <string>&Notifications</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>pushButtonNotifications</cstring> + </property> + <property name="text"> + <string>&Configure Sounds && Events...</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxUpdateInterval</cstring> + </property> + <property name="title"> + <string>Update interval</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Update interface information every</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>60</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>numInputPollInterval</cstring> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="suffix"> + <string>s</string> + </property> + <property name="whatsThis" stdset="0"> + <string>How often should KNemo poll for interface information. Lower number means more CPU load but faster reaction on changes. Larger number means less CPU load but slow reaction on changes.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxStatistics</cstring> + </property> + <property name="title"> + <string>Statistics</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="2" column="3"> + <property name="name"> + <cstring>pushButtonStatisticsDir</cstring> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel1_5</cstring> + </property> + <property name="text"> + <string>Statistics are stored in the following directory:</string> + </property> + </widget> + <widget class="QLineEdit" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>lineEditStatisticsDir</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_6</cstring> + </property> + <property name="text"> + <string>Save statistics every</string> + </property> + </widget> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>131</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="KIntNumInput" row="0" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>numInputSaveInterval</cstring> + </property> + <property name="value"> + <number>60</number> + </property> + <property name="suffix"> + <string>s</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox11_2</cstring> + </property> + <property name="title"> + <string>Backend</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel1_7</cstring> + </property> + <property name="text"> + <string>Use the following backend</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Description:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabelBackendDescription</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QComboBox" row="0" column="3"> + <property name="name"> + <cstring>comboBoxBackends</cstring> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>100</width> + <height>21</height> + </size> + </property> + </spacer> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer21</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>30</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>trafficplotter</cstring> + </property> + <attribute name="title"> + <string>Traffic &Plotter</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox7</cstring> + </property> + <property name="title"> + <string>Scale</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntSpinBox" row="0" column="3"> + <property name="name"> + <cstring>spinBoxPixel</cstring> + </property> + <property name="maxValue"> + <number>50</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel8_2</cstring> + </property> + <property name="text"> + <string>Pixel per time period:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel9_2_2</cstring> + </property> + <property name="text"> + <string>Ma&ximum value:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinBoxMaxValue</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="3"> + <property name="name"> + <cstring>spinBoxMaxValue</cstring> + </property> + <property name="maxValue"> + <number>50000</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>checkBoxAutoDetection</cstring> + </property> + <property name="text"> + <string>Automatic &range detection</string> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="1"> + <property name="name"> + <cstring>spinBoxMinValue</cstring> + </property> + <property name="maxValue"> + <number>49999</number> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel9_3</cstring> + </property> + <property name="text"> + <string>&Minimum value:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinBoxMinValue</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="2" column="1"> + <property name="name"> + <cstring>groupBox9</cstring> + </property> + <property name="title"> + <string>Text</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>checkBoxLabels</cstring> + </property> + <property name="text"> + <string>&Labels</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>checkBoxTopBar</cstring> + </property> + <property name="text"> + <string>Top &bar</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string>Fo&nt size:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinBoxFontSize</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="2" column="1"> + <property name="name"> + <cstring>spinBoxFontSize</cstring> + </property> + <property name="maxValue"> + <number>24</number> + </property> + <property name="minValue"> + <number>5</number> + </property> + <property name="value"> + <number>8</number> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="2" column="0"> + <property name="name"> + <cstring>groupBox8</cstring> + </property> + <property name="title"> + <string>Lines</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntSpinBox" row="0" column="2"> + <property name="name"> + <cstring>spinBoxDistance</cstring> + </property> + <property name="maxValue"> + <number>120</number> + </property> + <property name="minValue"> + <number>10</number> + </property> + <property name="value"> + <number>30</number> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string>&Distance:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinBoxDistance</cstring> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>checkBoxVLines</cstring> + </property> + <property name="text"> + <string>Vertic&al lines</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>checkBoxVLinesScroll</cstring> + </property> + <property name="text"> + <string>V&ertical lines scroll</string> + </property> + </widget> + <widget class="KIntSpinBox" row="2" column="2"> + <property name="name"> + <cstring>spinBoxCount</cstring> + </property> + <property name="maxValue"> + <number>20</number> + </property> + <property name="minValue"> + <number>2</number> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabel2_4</cstring> + </property> + <property name="text"> + <string>Co&unt:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinBoxCount</cstring> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>checkBoxHLines</cstring> + </property> + <property name="text"> + <string>Hori&zontal lines</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox10</cstring> + </property> + <property name="title"> + <string>&Colors</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="text"> + <string>Vertical lines:</string> + </property> + </widget> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>kColorButtonVLines</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>kColorButtonHLines</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KColorButton" row="0" column="3"> + <property name="name"> + <cstring>kColorButtonIncoming</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel6_2</cstring> + </property> + <property name="text"> + <string>Background:</string> + </property> + </widget> + <widget class="KColorButton" row="2" column="1"> + <property name="name"> + <cstring>kColorButtonBackground</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel5_2</cstring> + </property> + <property name="text"> + <string>Horizontal lines:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel7_2_2</cstring> + </property> + <property name="text"> + <string>Outgoing traffic:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel7_3</cstring> + </property> + <property name="text"> + <string>Incoming traffic:</string> + </property> + </widget> + <widget class="KColorButton" row="1" column="3"> + <property name="name"> + <cstring>kColorButtonOutgoing</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBox15</cstring> + </property> + <property name="title"> + <string>Traffic</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxIncoming</cstring> + </property> + <property name="text"> + <string>Sho&w incoming traffic</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxOutgoing</cstring> + </property> + <property name="text"> + <string>Show &outgoing traffic</string> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>checkBoxNotConnected</sender> + <signal>toggled(bool)</signal> + <receiver>checkBoxNotExisting</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxAutoDetection</sender> + <signal>toggled(bool)</signal> + <receiver>spinBoxMinValue</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxAutoDetection</sender> + <signal>toggled(bool)</signal> + <receiver>spinBoxMaxValue</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxVLines</sender> + <signal>toggled(bool)</signal> + <receiver>checkBoxVLinesScroll</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxVLines</sender> + <signal>toggled(bool)</signal> + <receiver>spinBoxDistance</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxVLines</sender> + <signal>toggled(bool)</signal> + <receiver>kColorButtonVLines</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxHLines</sender> + <signal>toggled(bool)</signal> + <receiver>spinBoxCount</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxHLines</sender> + <signal>toggled(bool)</signal> + <receiver>checkBoxLabels</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxHLines</sender> + <signal>toggled(bool)</signal> + <receiver>kColorButtonHLines</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxIncoming</sender> + <signal>toggled(bool)</signal> + <receiver>kColorButtonIncoming</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxOutgoing</sender> + <signal>toggled(bool)</signal> + <receiver>kColorButtonOutgoing</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxCustom</sender> + <signal>toggled(bool)</signal> + <receiver>listViewCommands</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxCustom</sender> + <signal>toggled(bool)</signal> + <receiver>pushButtonAddCommand</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkBoxStartKNemo</sender> + <signal>toggled(bool)</signal> + <receiver>tabWidgetConfiguration</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>tabWidgetConfiguration</tabstop> + <tabstop>listBoxInterfaces</tabstop> + <tabstop>pushButtonNew</tabstop> + <tabstop>pushButtonDelete</tabstop> + <tabstop>lineEditAlias</tabstop> + <tabstop>checkBoxNotConnected</tabstop> + <tabstop>checkBoxCustom</tabstop> + <tabstop>listBoxAvailable</tabstop> + <tabstop>listBoxDisplay</tabstop> + <tabstop>pushButtonRemoveToolTip</tabstop> + <tabstop>pushButtonAddToolTip</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/src/kcm/kcm_knemo.desktop b/src/kcm/kcm_knemo.desktop new file mode 100644 index 0000000..b29b94a --- /dev/null +++ b/src/kcm/kcm_knemo.desktop @@ -0,0 +1,89 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Exec=kcmshell kcm_knemo +Icon=knemo + +X-KDE-ModuleType=Library +X-KDE-Library=knemo +X-KDE-FactoryName=knemo +X-KDE-ParentApp=kcontrol + +Name=Network Monitor +Name[bg]=Монитор на мрежата +Name[br]=Eveshaer ar rouedad +Name[cs]=Monitor sítě +Name[da]=Netværkovervågning +Name[de]=Netzwerkmonitor +Name[el]=Επίβλεψη δικτύου +Name[es]=Monitor de red +Name[et]=Võrgumonitor +Name[ga]=Monatóir Líonra +Name[gl]=Monitor da Rede +Name[it]=Monitor di rete +Name[ja]=ネットワークモニタ +Name[ka]=ქსელის მონიტორი +Name[lt]=Tinklo stebėjimas +Name[nl]=Netwerkmonitor +Name[pa]=ਨੈਟਵਰਕ ਨਿਗਰਾਨ +Name[pl]=Monitor sieci +Name[pt]=Monitor da Rede +Name[pt_BR]=Monitor de Rede +Name[ru]=Монитор сети +Name[sr]=Надгледање мреже +Name[sr@Latn]=Nadgledanje mreže +Name[sv]=Nätverksövervakare +Name[tr]=Ağ İzleyici +Name[uk]=Монітор мережі +Name[xx]=xxNetwork Monitorxx +Name[zh_CN]=网络监视器 +Comment=Monitor network interfaces +Comment[bg]=Показване на информация за мрежовите интерфейси +Comment[br]=Eveshaer etrefasoù ar rouedad +Comment[cs]=Rozhraní monitoru sítě +Comment[da]=Overvåger netværkgrænseflader +Comment[de]=Überwachung von Netzwerkschnittstellen +Comment[el]=Επίβλεψη διασυνδέσεων δικτύου +Comment[es]=Monitor de interfaces de red +Comment[et]=Võrguliideste monitor +Comment[ga]=Déan monatóireacht ar chomhéadain líonra +Comment[gl]=Fai seguimento das interfaces de rede +Comment[it]=Controlla le interfacce di rete +Comment[ja]=ネットワークインターフェースを監視 +Comment[ka]=ქსელის ინტერფეისების მონიტორინგი +Comment[lt]=Stebėti tinklo įrenginius +Comment[nl]=Volg netwerkinterfaces +Comment[pa]=ਨੈਟਵਰਕ ਇੰਟਰਫੇਸ ਲਈ ਨਿਗਰਾਨੀ +Comment[pl]=Monitorowanie interfejsów sieciowych +Comment[pt]=Vigia interfaces de rede +Comment[pt_BR]=Monitor das interfaces de rede +Comment[ru]=Наблюдение за сетевыми интерфейсами +Comment[sr]=Интерфејс надгледања мреже +Comment[sr@Latn]=Interfejs nadgledanja mreže +Comment[sv]=Övervaka nätverksgränssnitt +Comment[tr]=Ağ arayüzlerini izler +Comment[uk]=Нагляд за мережними інтерфейсами +Comment[xx]=xxMonitor network interfacesxx +Comment[zh_CN]=监视网络接口 + +Keywords=knemo,network monitor,wlan monitor,wifi monitor,ethernet monitor,wireless monitor,systray +Keywords[cs]=knemo,monitor sítě,monitor wlan,monitor wifi,monitor ethernetu,monitor bezdrátového připojení,systray +Keywords[da]=knemo,netværksovervågning,WLAN-overvågning,WIFI-overvågning,Ethernet-overvågning,trådløs overvågning,statusfelt +Keywords[de]=knemo,netzwerk-monitor,wlan-monitor,wifi-monitor,ethernet-monitor,wireless-monitor,kontrollleiste,überwachung,netzwerk,drahtlos-monitor +Keywords[el]=knemo,επόπτης δικτύου,επόπτης wlan,επόπτης wifi,επόπτης ethernet, επόπτης wireless,πλαίσιο συστήματος +Keywords[es]=knemo,monitor de red,monitor de wlan,monitor wifi,monitor de ethernet,monitor inalámbrico,bandeja del sistema +Keywords[et]=knemo,võrgumonitor,wlan monitor,wifi monitor,ethernet monitor,traadita võrgu monitor,süsteemne salv +Keywords[ga]=knemo,monatóir líonra,monatóir wlan,monatóir wifi,monatóir ethernet,monatóir líonra gan sreang,tráidire an chórais +Keywords[gl]=knemo,monitor, rede, wlan, wifi, ethernet, wireless,systray +Keywords[it]=knemo,monitor di rete,wlan monitor,monitor senza fili,ethernet monitor,vassoio di sistema +Keywords[ja]=knemo,ネットワークモニタ,wlan モニタ,wifi モニタ,ethernet モニタ,ワイヤレスモニタ,システムトレイ +Keywords[nl]=knemo,netwerkmonitor,wlan-monitor,wifi-monitor,ethernetmonitor,wireless-monitor,systeemvak +Keywords[pt]=knemo,monitor da rede,monitor de wlan,monitor wifi,monitor de ethernet,monitor sem-fios,bandeja do sistema +Keywords[pt_BR]=knemo,monitor de rede,wlan,monitor de wifi monitor,monitor ethernet monitor,monitor de wireless,painel do sistema, mini-aplicativo +Keywords[ru]=knemo,мониторинг сети,мониторинг беспроводной сети,wifi монитор,монитор локальной сети,системный лоток,сеть,беспроводная сеть +Keywords[sv]=knemo,nätverksövervakning,WLAN-övervakning,WIFI-övervakning,Ethernet-övervakning,trådlös övervakning,systembricka +Keywords[uk]=knemo,network monitor,wlan monitor,wifi monitor,ethernet monitor,wireless monitor,systray,мережа,монітор,системний лоток,монітор wifi +Keywords[xx]=xxknemo,network monitor,wlan monitor,wifi monitor,ethernet monitor,wireless monitor,systrayxx +Keywords[zh_CN]=knemo,network monitor,wlan monitor,wifi monitor,ethernet monitor,wireless monitor,systray,网络监视器,无限局域网监视器,wifi 监视器以太网监视器,无线网络监视器,系统托盘 + +Categories=Qt;KDE;X-KDE-settings-network;X-KDE-systemsettings-network diff --git a/src/knemo.lsm b/src/knemo.lsm new file mode 100644 index 0000000..021b604 --- /dev/null +++ b/src/knemo.lsm @@ -0,0 +1,16 @@ +Begin4 +Title: KNemo -- Some description +Version: 0.1 +Entered-date: YYYY-MM-DD +Description: +Keywords: KDE3 Qt +Author: Percy Leonhardt <percy@eris23.de> +Maintained-by: Percy Leonhardt <percy@eris23.de> +Home-page: +Alternate-site: +Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils + xxxxxx knemo-0.1.tar.gz + xxx knemo-0.1.lsm +Platform: Linux. Needs KDE 2.x +Copying-policy: GPL +End diff --git a/src/knemo.spec b/src/knemo.spec new file mode 100644 index 0000000..7411ede --- /dev/null +++ b/src/knemo.spec @@ -0,0 +1,41 @@ +%define distversion %( perl -e 'Creating /home/percy/src/knemo-0.1/knemo.spec...=\<\>;/(\d+)\.(\d)\.?(\d)?/; print "".(||0)' /etc/*-release) +Name: knemo +Summary: KNemo -- Some description +Version: 0.1 +Release: %{_vendor}_%{distversion} +Copyright: GPL +Group: X11/KDE/Utilities +Source: ftp://ftp.kde.org/pub/kde/unstable/apps/utils/%{name}-%{version}.tar.gz +Packager: Percy Leonhardt <percy@eris23.de> +BuildRoot: /tmp/%{name}-%{version} +Prefix: /usr/kde/3.2 + +%description +A long description + +%prep +rm -rf $RPM_BUILD_ROOT +%setup -n %{name}-%{version} +CFLAGS="" CXXFLAGS="" ./configure --disable-debug --enable-final --prefix=%{prefix} + +%build +# Setup for parallel builds +numprocs=1 +if [ "" = "0" ]; then + numprocs=1 +fi + +make -j + +%install +make install-strip DESTDIR=$RPM_BUILD_ROOT + +cd +find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > /%{name}-master.list +find . -type f -o -type l | sed 's|^\.||' >> $RPM_BUILD_DIR/%{name}-master.list + +%clean +rm -rf $RPM_BUILD_DIR/%{name}-%{version} +rm -rf $RPM_BUILD_DIR/-master.list + +%files -f $RPM_BUILD_DIR/%{name}-master.list diff --git a/src/knemod/Makefile.am b/src/knemod/Makefile.am new file mode 100644 index 0000000..a9496bc --- /dev/null +++ b/src/knemod/Makefile.am @@ -0,0 +1,47 @@ +## Makefile.am for knemo + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/knemod.pot + +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +SUBDIRS = pics backends + +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +kde_module_LTLIBRARIES = kded_knemod.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/../common -I$(srcdir)/backends $(all_includes) + +# the library search path. +kded_knemod_la_LDFLAGS = -module -avoid-version $(all_libraries) + +# the libraries to link against. +kded_knemod_la_LIBADD = $(LIB_KIO) $(LIB_KUTILS) backends/libknemo_backends.la + +# which sources should be compiled for knemo +kded_knemod_la_SOURCES = knemodaemon.cpp knemodaemon.skel interface.cpp \ + interfaceicon.cpp interfacetray.cpp \ + interfacemonitor.cpp \ + interfacestatusdlg.ui interfacestatusdialog.cpp \ + interfacetooltip.cpp signalplotter.cpp \ + interfacestatistics.cpp interfacestatisticsdlg.ui \ + interfacestatisticsdialog.cpp + +# these are the headers for your project +noinst_HEADERS = knemodaemon.h interface.h interfaceicon.h \ + interfacemonitor.h \ + interfacestatusdialog.h interfacetray.h \ + interfacetooltip.h signalplotter.h \ + interfacestatistics.h global.h \ + interfacestatisticsdialog.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +services_DATA = knemod.desktop +servicesdir = $(kde_servicesdir)/kded + +mydata_DATA = eventsrc +mydatadir = $(kde_datadir)/knemo diff --git a/src/knemod/backends/Makefile.am b/src/knemod/backends/Makefile.am new file mode 100644 index 0000000..aab0fd0 --- /dev/null +++ b/src/knemod/backends/Makefile.am @@ -0,0 +1,22 @@ +## Makefile.am for knemo backends + +noinst_LTLIBRARIES = libknemo_backends.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../common $(all_includes) + +# the library search path. +libknemo_backends_la_LDFLAGS = -module -avoid-version $(all_libraries) + +# the libraries to link against. +libknemo_backends_la_LIBADD = $(LIB_KIO) $(LIB_KUTILS) + +# which sources should be compiled as backends +libknemo_backends_la_SOURCES = backendbase.cpp nettoolsbackend.cpp sysbackend.cpp + +# the headers of the backends +noinst_HEADERS = backendbase.h nettoolsbackend.h sysbackend.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + diff --git a/src/knemod/backends/backendbase.cpp b/src/knemod/backends/backendbase.cpp new file mode 100644 index 0000000..82da372 --- /dev/null +++ b/src/knemod/backends/backendbase.cpp @@ -0,0 +1,38 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "backendbase.h" + +BackendBase::BackendBase( QDict<Interface>& interfaces ) + : mInterfaces( interfaces ) +{ +} + +BackendBase::~BackendBase() +{ +} + +void BackendBase::updateComplete() +{ + QDictIterator<Interface> ifIt( mInterfaces ); + for ( ; ifIt.current(); ++ifIt ) + { + ifIt.current()->activateMonitor(); + } +} diff --git a/src/knemod/backends/backendbase.h b/src/knemod/backends/backendbase.h new file mode 100644 index 0000000..183e40a --- /dev/null +++ b/src/knemod/backends/backendbase.h @@ -0,0 +1,68 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef BACKENDBASE_H +#define BACKENDBASE_H + +#include <qdict.h> +#include <qstring.h> + +#include <klocale.h> + +#include "data.h" +#include "interface.h" + +/** + * This is the baseclass for all backends. Every backend that + * should be used for KNemo must inherit from this class. + * + * @short Baseclass for all backends + * @author Percy Leonhardt <percy@eris23.de> + */ + +class BackendBase +{ +public: + BackendBase( QDict<Interface>& interfaces ); + virtual ~BackendBase(); + + /** + * Create an instance of this backend because KNemo + * does not know about the different types of backends. + */ + + /** + * This function is called from KNemo whenever the + * backend shall update the information of the + * interfaces in the QDict. + */ + virtual void update() = 0; + +protected: + /** + * Call this function when you have completed the + * update. It will trigger the interfaces to check + * if there state has changed. + */ + void updateComplete(); + + const QDict<Interface>& mInterfaces; +}; + +#endif // BACKENDBASE_H diff --git a/src/knemod/backends/daemonregistry.h b/src/knemod/backends/daemonregistry.h new file mode 100644 index 0000000..ba4638d --- /dev/null +++ b/src/knemod/backends/daemonregistry.h @@ -0,0 +1,54 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DAEMONREGISTRY_H +#define DAEMONREGISTRY_H + +#include <qstring.h> + +#include <klocale.h> + +#include "backendbase.h" +#include "sysbackend.h" +#include "nettoolsbackend.h" + +/** + * This registry tells KNemo what backends are available + * and how they can be created. It is only used by the daemon + * to create the selected backend. Two registries were + * necessary to avoid linking the KCM module against all backends. + * + * @short Registry for all backends + * @author Percy Leonhardt <percy@eris23.de> + */ + +struct DaemonRegistryEntry +{ + QString name; + BackendBase* (*function) ( QDict<Interface>& ); +}; + +DaemonRegistryEntry DaemonRegistry[] = +{ + { "Nettools", NetToolsBackend::createInstance }, + { "Sys", SysBackend::createInstance }, + { QString::null, 0 } +}; + +#endif // DAEMONREGISTRY_H diff --git a/src/knemod/backends/kcmregistry.h b/src/knemod/backends/kcmregistry.h new file mode 100644 index 0000000..23820ac --- /dev/null +++ b/src/knemod/backends/kcmregistry.h @@ -0,0 +1,61 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KCMREGISTRY_H +#define KCMREGISTRY_H + +#include <qstring.h> + +#include <klocale.h> + +/** + * This registry tells the KCM module what backends are available + * and how they can be created. It also offers a short description + * for every backend that is used in the configuration dialog of KNemo. + * It should describe how a backend gathers its information. + * + * @short Registry for all backends + * @author Percy Leonhardt <percy@eris23.de> + */ + +struct KCMRegistryEntry +{ + QString name; + QString description; +}; + +KCMRegistryEntry KCMRegistry[] = +{ + { "Nettools", + i18n( "Uses the tools from the nettool packge like ifconfig, " \ + "iwconfig and route to read the necessary information " \ + "from the ouput of these commands.\n" \ + "This backend works rather stable but causes a relativly " \ + "high CPU load." ) }, + { "Sys", + i18n( "Uses the sys filesystem available in 2.6 kernels and " \ + "direct system calls to the Linux kernel.\n" \ + "This backend is rather new, so expect minor problems. " \ + "As an advantage this backend should reduce the CPU load " \ + "and should not access the harddisc while gathering " \ + "information." ) }, + { QString::null, QString::null } +}; + +#endif // KCMREGISTRY_H diff --git a/src/knemod/backends/nettoolsbackend.cpp b/src/knemod/backends/nettoolsbackend.cpp new file mode 100644 index 0000000..dca42e1 --- /dev/null +++ b/src/knemod/backends/nettoolsbackend.cpp @@ -0,0 +1,498 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qmap.h> +#include <qregexp.h> +#include <qstringlist.h> + +#include <kdebug.h> +#include <kprocess.h> +#include <kio/global.h> + +#include "nettoolsbackend.h" + +#include "config.h" + +NetToolsBackend::NetToolsBackend( QDict<Interface>& interfaces ) + : QObject(), + BackendBase( interfaces ), + mRouteProcess(0L), + mIfconfigProcess(0L), + mIwconfigProcess(0L) +{ +} + +NetToolsBackend::~NetToolsBackend() +{ + if ( mRouteProcess ) + { + mRouteProcess->kill(); + delete mRouteProcess; + } + if ( mIfconfigProcess ) + { + mIfconfigProcess->kill(); + delete mIfconfigProcess; + } + if ( mIwconfigProcess ) + { + mIwconfigProcess->kill(); + delete mIwconfigProcess; + } +} + +BackendBase* NetToolsBackend::createInstance( QDict<Interface>& interfaces ) +{ + return new NetToolsBackend( interfaces ); +} + +void NetToolsBackend::update() +{ + if ( !mIfconfigProcess ) + { + mIfconfigStdout = QString::null; + mIfconfigProcess = new KProcess(); + mIfconfigProcess->setEnvironment( "LANG", "C" ); + mIfconfigProcess->setEnvironment( "LC_ALL", "C" ); + *mIfconfigProcess << PATH_IFCONFIG << "-a"; + connect( mIfconfigProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ), + this, SLOT( ifconfigProcessStdout( KProcess*, char*, int ) ) ); + connect( mIfconfigProcess, SIGNAL( processExited( KProcess* ) ), + this, SLOT( ifconfigProcessExited( KProcess* ) ) ); + + if ( !mIfconfigProcess->start( KProcess::NotifyOnExit, KProcess::Stdout ) ) + { + delete mIfconfigProcess; + mIfconfigProcess = 0L; + } + } + +#ifdef PATH_IWCONFIG + if ( !mIwconfigProcess ) + { + mIwconfigStdout = QString::null; + mIwconfigProcess = new KProcess(); + mIwconfigProcess->setEnvironment( "LANG", "C" ); + mIwconfigProcess->setEnvironment( "LC_ALL", "C" ); + *mIwconfigProcess << PATH_IWCONFIG; + connect( mIwconfigProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ), + this, SLOT( iwconfigProcessStdout( KProcess*, char*, int ) ) ); + connect( mIwconfigProcess, SIGNAL( receivedStderr( KProcess*, char*, int ) ), + this, SLOT( iwconfigProcessStdout( KProcess*, char*, int ) ) ); + connect( mIwconfigProcess, SIGNAL( processExited( KProcess* ) ), + this, SLOT( iwconfigProcessExited( KProcess* ) ) ); + + if ( !mIwconfigProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + delete mIwconfigProcess; + mIwconfigProcess = 0L; + } + } +#endif + +#ifdef PATH_ROUTE + if ( !mRouteProcess ) + { + mRouteStdout = QString::null; + mRouteProcess = new KProcess(); + mRouteProcess->setEnvironment( "LANG", "C" ); + mRouteProcess->setEnvironment( "LC_ALL", "C" ); + *mRouteProcess << PATH_ROUTE << "-n"; + connect( mRouteProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ), + this, SLOT( routeProcessStdout( KProcess*, char*, int ) ) ); + connect( mRouteProcess, SIGNAL( receivedStderr( KProcess*, char*, int ) ), + this, SLOT( routeProcessStdout( KProcess*, char*, int ) ) ); + connect( mRouteProcess, SIGNAL( processExited( KProcess* ) ), + this, SLOT( routeProcessExited( KProcess* ) ) ); + + if ( !mRouteProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) + { + delete mRouteProcess; + mRouteProcess = 0L; + } + } +#endif +} + +void NetToolsBackend::routeProcessExited( KProcess* process ) +{ + if ( process == mRouteProcess ) + { + mRouteProcess->deleteLater(); // we're in a slot connected to mRouteProcess + mRouteProcess = 0L; + parseRouteOutput(); + } +} + +void NetToolsBackend::routeProcessStdout( KProcess*, char* buffer, int buflen ) +{ + mRouteStdout += QString::fromLatin1( buffer, buflen ); +} + +void NetToolsBackend::ifconfigProcessExited( KProcess* process ) +{ + if ( process == mIfconfigProcess ) + { + delete mIfconfigProcess; + mIfconfigProcess = 0L; + parseIfconfigOutput(); + } +} + +void NetToolsBackend::ifconfigProcessStdout( KProcess*, char* buffer, int buflen ) +{ + mIfconfigStdout += QString::fromLatin1( buffer, buflen ); +} + +void NetToolsBackend::iwconfigProcessExited( KProcess* process ) +{ + if ( process == mIwconfigProcess ) + { + delete mIwconfigProcess; + mIwconfigProcess = 0L; + parseIwconfigOutput(); + } +} + +void NetToolsBackend::iwconfigProcessStdout( KProcess*, char* buffer, int buflen ) +{ + mIwconfigStdout += QString::fromLatin1( buffer, buflen ); +} + +void NetToolsBackend::parseIfconfigOutput() +{ + /* mIfconfigStdout contains the complete output of 'ifconfig' which we + * are going to parse here. + */ + QMap<QString, QString> configs; + QStringList ifList = QStringList::split( "\n\n", mIfconfigStdout ); + QStringList::Iterator it; + for ( it = ifList.begin(); it != ifList.end(); ++it ) + { + int index = ( *it ).find( ' ' ); + if ( index == -1 ) + continue; + QString key = ( *it ).left( index ); + configs[key] = ( *it ).mid( index ); + } + + /* We loop over the interfaces the user wishs to monitor. + * If we find the interface in the output of 'ifconfig' + * we update its data, otherwise we mark it as + * 'not existing'. + */ + QDictIterator<Interface> ifIt( mInterfaces ); + for ( ; ifIt.current(); ++ifIt ) + { + QString key = ifIt.currentKey(); + Interface* interface = ifIt.current(); + + if ( configs.find( key ) == configs.end() ) + { + // The interface does not exist. Meaning the driver + // isn't loaded and/or the interface has not been created. + interface->getData().existing = false; + interface->getData().available = false; + } + // JJ 2005-07-18: use RUNNING instead of UP to detect whether interface is connected + else if ( !configs[key].contains( "inet " ) || + !configs[key].contains( "RUNNING" ) ) + { + // The interface is up or has an IP assigned but not both + interface->getData().existing = true; + interface->getData().available = false; + } + else + { + // ...determine the type of the interface + if ( configs[key].contains( "Ethernet" ) ) + interface->setType( Interface::ETHERNET ); + else + interface->setType( Interface::PPP ); + + // Update the interface. + interface->getData().existing = true; + interface->getData().available = true; + updateInterfaceData( configs[key], interface->getData(), interface->getType() ); + } + } + updateComplete(); +} + +void NetToolsBackend::updateInterfaceData( QString& config, InterfaceData& data, int type ) +{ + QRegExp regExp( ".*RX.*:(\\d+).*:\\d+.*:\\d+.*:\\d+" ); + if ( regExp.search( config ) > -1 ) + data.rxPackets = regExp.cap( 1 ).toULong(); + + regExp.setPattern( ".*TX.*:(\\d+).*:\\d+.*:\\d+.*:\\d+" ); + if ( regExp.search( config ) > -1 ) + data.txPackets = regExp.cap( 1 ).toULong(); + + regExp.setPattern( "RX bytes:(\\d+)\\s*\\(\\d+\\.\\d+\\s*\\w+\\)" ); + if ( regExp.search( config ) > -1 ) + { + // We count the traffic on ourself to avoid an overflow after + // 4GB of traffic. + unsigned long currentRxBytes = regExp.cap( 1 ).toULong(); + if ( currentRxBytes < data.prevRxBytes ) + { + // there was an overflow + if ( type == Interface::ETHERNET ) + { + // This makes data counting more accurate but will not work + // for interfaces that reset the transfered data to zero + // when deactivated like ppp does. + data.rxBytes += 0xFFFFFFFF - data.prevRxBytes; + } + data.prevRxBytes = 0L; + } + if ( data.rxBytes == 0L ) + { + // on startup set to currently received bytes + data.rxBytes = currentRxBytes; + // this is new: KNemo only counts the traffic transfered + // while it is running. Important to not falsify statistics! + data.prevRxBytes = currentRxBytes; + } + else + // afterwards only add difference to previous number of bytes + data.rxBytes += currentRxBytes - data.prevRxBytes; + + data.incomingBytes = currentRxBytes - data.prevRxBytes; + data.prevRxBytes = currentRxBytes; + data.rxString = KIO::convertSize( data.rxBytes ); + } + + regExp.setPattern( "TX bytes:(\\d+)\\s*\\(\\d+\\.\\d+\\s*\\w+\\)" ); + if ( regExp.search( config ) > -1 ) + { + // We count the traffic on ourself to avoid an overflow after + // 4GB of traffic. + unsigned long currentTxBytes = regExp.cap( 1 ).toULong(); + if ( currentTxBytes < data.prevTxBytes ) + { + // there was an overflow + if ( type == Interface::ETHERNET ) + { + // This makes data counting more accurate but will not work + // for interfaces that reset the transfered data to zero + // when deactivated like ppp does. + data.txBytes += 0xFFFFFFFF - data.prevTxBytes; + } + data.prevTxBytes = 0L; + } + if ( data.txBytes == 0L ) + { + // on startup set to currently transmitted bytes + data.txBytes = currentTxBytes; + // this is new: KNemo only counts the traffic transfered + // while it is running. Important to not falsify statistics! + data.prevTxBytes = currentTxBytes; + } + else + // afterwards only add difference to previous number of bytes + data.txBytes += currentTxBytes - data.prevTxBytes; + + data.outgoingBytes = currentTxBytes - data.prevTxBytes; + data.prevTxBytes = currentTxBytes; + data.txString = KIO::convertSize( data.txBytes ); + } + + regExp.setPattern( "inet\\s+\\w+:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" ); + if ( regExp.search( config ) > -1 ) + data.ipAddress = regExp.cap( 1 ); + + regExp.setPattern( "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" ); + if ( regExp.search( config ) > -1 ) + { + data.broadcastAddress = regExp.cap( 2 ); + data.subnetMask = regExp.cap( 3 ); + } + + if ( type == Interface::ETHERNET ) + { + regExp.setPattern( "(.{2}:.{2}:.{2}:.{2}:.{2}:.{2})" ); + if ( regExp.search( config ) > -1 ) + data.hwAddress = regExp.cap( 1 ); + } + else if ( type == Interface::PPP ) + { + regExp.setPattern( "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" ); + if ( regExp.search( config ) > -1 ) + data.ptpAddress = regExp.cap( 2 ); + } +} + +void NetToolsBackend::parseIwconfigOutput() +{ + /* mIwconfigStdout contains the complete output of 'iwconfig' which we + * are going to parse here. + */ + QMap<QString, QString> configs; + QStringList ifList = QStringList::split( "\n\n", mIwconfigStdout ); + QStringList::Iterator it; + for ( it = ifList.begin(); it != ifList.end(); ++it ) + { + int index = ( *it ).find( ' ' ); + if ( index == -1 ) + continue; + QString key = ( *it ).left( index ); + configs[key] = ( *it ).mid( index ); + } + + /* We loop over the interfaces the user wishs to monitor. + * If we find the interface in the output of 'iwconfig' + * we update its data. + */ + QDictIterator<Interface> ifIt( mInterfaces ); + for ( ; ifIt.current(); ++ifIt ) + { + QString key = ifIt.currentKey(); + Interface* interface = ifIt.current(); + + if ( configs.find( key ) == configs.end() ) + { + // The interface was not found. + continue; + } + else if ( configs[key].contains( "no wireless extensions" ) ) + { + // The interface isn't a wireless device. + interface->getData().wirelessDevice = false; + } + else + { + // Update the wireless data of the interface. + interface->getData().wirelessDevice = true; + updateWirelessData( configs[key], interface->getWirelessData() ); + } + } +} + +void NetToolsBackend::updateWirelessData( QString& config, WirelessData& data ) +{ + QRegExp regExp( "ESSID:([^\"][\\S]*)" ); + if ( regExp.search( config ) > -1 ) + data.essid = regExp.cap( 1 ); + else + { + regExp.setPattern( "ESSID:\"([^\"]*)" ); + if ( regExp.search( config ) > -1 ) + data.essid = regExp.cap( 1 ); + else + data.essid = QString::null; + } + + regExp.setPattern( "Mode:(\\w*)" ); + if ( regExp.search( config ) > -1 ) + data.mode = regExp.cap( 1 ); + + regExp.setPattern( "Frequency:([\\w|\\.]*\\s*\\w*)" ); + if ( regExp.search( config ) > -1 ) + { + data.frequency = regExp.cap( 1 ); + data.channel = "-"; + } + else + { + data.frequency = "-"; + regExp.setPattern( "Channel:(\\d*)" ); + if ( regExp.search( config ) > -1 ) + data.channel = regExp.cap( 1 ); + else + data.channel = "-"; + } + + regExp.setPattern( "Bit Rate[=:](\\d*\\s*[\\w/]*)" ); + if ( regExp.search( config ) > -1 ) + data.bitRate = regExp.cap( 1 ); + + regExp.setPattern( "(.{2}:.{2}:.{2}:.{2}:.{2}:.{2})" ); + if ( regExp.search( config ) > -1 ) + data.accessPoint = regExp.cap( 1 ); + + regExp.setPattern( "Nickname:\"(\\w*)\"" ); + if ( regExp.search( config ) > -1 ) + data.nickName = regExp.cap( 1 ); + + regExp.setPattern( "Link Quality[=:]([\\d]*)" ); + if ( regExp.search( config ) > -1 ) + data.linkQuality = regExp.cap( 1 ); + + regExp.setPattern( "Encryption key:" ); + if ( regExp.search( config ) > -1 ) + { + regExp.setPattern( "Encryption key:off" ); + if ( regExp.search( config ) > -1 ) + { + data.encryption = false; + } + else + { + data.encryption = true; + } + } + else + { + data.encryption = false; + } +} + +void NetToolsBackend::parseRouteOutput() +{ + /* mRouteStdout contains the complete output of 'route' which we + * are going to parse here. + */ + QMap<QString, QStringList> configs; + QStringList routeList = QStringList::split( "\n", mRouteStdout ); + QStringList::Iterator it; + for ( it = routeList.begin(); it != routeList.end(); ++it ) + { + QStringList routeParameter = QStringList::split( " ", *it ); + if ( routeParameter.count() < 8 ) // no routing entry + continue; + if ( routeParameter[0] != "0.0.0.0" ) // no default route + continue; + configs[routeParameter[7]] = routeParameter; + } + + /* We loop over the interfaces the user wishs to monitor. + * If we find the interface in the output of 'route' we update + * the data of the interface. + */ + QDictIterator<Interface> ifIt( mInterfaces ); + for ( ; ifIt.current(); ++ifIt ) + { + QString key = ifIt.currentKey(); + Interface* interface = ifIt.current(); + + if ( configs.find( key ) != configs.end() ) + { + // Update the default gateway. + QStringList routeParameter = configs[key]; + interface->getData().defaultGateway = routeParameter[1]; + } + else + { + // Reset the default gateway. + interface->getData().defaultGateway = QString::null; + } + } +} diff --git a/src/knemod/backends/nettoolsbackend.h b/src/knemod/backends/nettoolsbackend.h new file mode 100644 index 0000000..788938c --- /dev/null +++ b/src/knemod/backends/nettoolsbackend.h @@ -0,0 +1,72 @@ +/* This file is part of KNemo + Copyright (C) 2004 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef NETTOOLSBACKEND_H +#define NETTOOLSBACKEND_H + +#include <qobject.h> + +#include "backendbase.h" + +class KProcess; + +/** + * The nettools backend runs 'ifconfig', 'iwconfig' and 'route' + * and parses their output. It then triggers the interface + * monitor to look for changes in the state of the interface. + * + * @short Update the information of the interfaces via nettools + * @author Percy Leonhardt <percy@eris23.de> + */ + +class NetToolsBackend : public QObject, BackendBase +{ + Q_OBJECT +public: + NetToolsBackend(QDict<Interface>& interfaces ); + virtual ~NetToolsBackend(); + + static BackendBase* createInstance( QDict<Interface>& interfaces ); + + void update(); + +private slots: + void routeProcessExited( KProcess* process ); + void routeProcessStdout( KProcess* process, char* buffer, int buflen ); + void ifconfigProcessExited( KProcess* process ); + void ifconfigProcessStdout( KProcess* process, char* buffer, int buflen ); + void iwconfigProcessExited( KProcess* process ); + void iwconfigProcessStdout( KProcess* process, char* buffer, int buflen ); + +private: + void parseRouteOutput(); + void parseIfconfigOutput(); + void updateInterfaceData( QString& config, InterfaceData& data, int type ); + void parseIwconfigOutput(); + void updateWirelessData( QString& config, WirelessData& data ); + + QString mRouteStdout; + QString mIfconfigStdout; + QString mIwconfigStdout; + KProcess* mRouteProcess; + KProcess* mIfconfigProcess; + KProcess* mIwconfigProcess; +}; + +#endif // NETTOOLSBACKEND_H diff --git a/src/knemod/backends/sysbackend.cpp b/src/knemod/backends/sysbackend.cpp new file mode 100644 index 0000000..2caf325 --- /dev/null +++ b/src/knemod/backends/sysbackend.cpp @@ -0,0 +1,428 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include <qmap.h> +#include <qdir.h> +#include <qregexp.h> +#include <qstringlist.h> + +#include <kdebug.h> +#include <kprocess.h> +#include <kio/global.h> + +#include "sysbackend.h" + +#include "config.h" + +#ifdef HAVE_LIBIW +#include <iwlib.h> +#else +#include <net/if.h> +#endif + +#define RTF_GATEWAY 0x0002 +#define SYSPATH "/sys/class/net/" +#define PROCROUTE "/proc/net/route" + +SysBackend::SysBackend( QDict<Interface>& interfaces ) + : BackendBase( interfaces ) +{ +} + +SysBackend::~SysBackend() +{ +} + +BackendBase* SysBackend::createInstance( QDict<Interface>& interfaces ) +{ + return new SysBackend( interfaces ); +} + +void SysBackend::update() +{ + QDir dir( SYSPATH ); + QStringList ifList = dir.entryList( QDir::Dirs ); + + QDictIterator<Interface> ifIt( mInterfaces ); + for ( ; ifIt.current(); ++ifIt ) + { + QString key = ifIt.currentKey(); + Interface* interface = ifIt.current(); + + if ( ifList.find( key ) == ifList.end() ) + { + // The interface does not exist. Meaning the driver + // isn't loaded and/or the interface has not been created. + interface->getData().existing = false; + interface->getData().available = false; + } + else + { + if ( QFile::exists( SYSPATH + key + "/wireless" ) ) + { + interface->getData().wirelessDevice = true; + } + + unsigned int carrier = 0; + if ( !readNumberFromFile( SYSPATH + key + "/carrier", carrier ) || + carrier == 0 ) + { + // The interface is there but not useable. + interface->getData().existing = true; + interface->getData().available = false; + } + else + { + // ...determine the type of the interface + unsigned int type = 0; + if ( readNumberFromFile( SYSPATH + key + "/type", type ) && + type == 512 ) + { + interface->setType( Interface::PPP ); + } + else + { + interface->setType( Interface::ETHERNET ); + } + + // Update the interface. + interface->getData().existing = true; + interface->getData().available = true; + updateInterfaceData( key, interface->getData(), interface->getType() ); + + if ( interface->getData().wirelessDevice == true ) + { + updateWirelessData( key, interface->getWirelessData() ); + } + } + } + } + updateComplete(); +} + +bool SysBackend::readNumberFromFile( const QString& fileName, unsigned int& value ) +{ + FILE* file = fopen( fileName.latin1(), "r" ); + if ( file != NULL ) + { + if ( fscanf( file, "%ul", &value ) > 0 ) + { + fclose( file ); + return true; + } + fclose( file ); + } + + return false; +} + +bool SysBackend::readStringFromFile( const QString& fileName, QString& string ) +{ + char buffer[64]; + FILE* file = fopen( fileName.latin1(), "r" ); + if ( file != NULL ) + { + if ( fscanf( file, "%s", buffer ) > 0 ) + { + fclose( file ); + string = buffer; + return true; + } + fclose( file ); + } + + return false; +} + +void SysBackend::updateInterfaceData( const QString& ifName, InterfaceData& data, int type ) +{ + QString ifFolder = SYSPATH + ifName + "/"; + + unsigned int rxPackets = 0; + if ( readNumberFromFile( ifFolder + "statistics/rx_packets", rxPackets ) ) + { + data.rxPackets = rxPackets; + } + + unsigned int txPackets = 0; + if ( readNumberFromFile( ifFolder + "statistics/tx_packets", txPackets ) ) + { + data.txPackets = txPackets; + } + + unsigned int rxBytes = 0; + if ( readNumberFromFile( ifFolder + "statistics/rx_bytes", rxBytes ) ) + { + // We count the traffic on ourself to avoid an overflow after + // 4GB of traffic. + if ( rxBytes < data.prevRxBytes ) + { + // there was an overflow + if ( type == Interface::ETHERNET ) + { + // This makes data counting more accurate but will not work + // for interfaces that reset the transfered data to zero + // when deactivated like ppp does. + data.rxBytes += 0xFFFFFFFF - data.prevRxBytes; + } + data.prevRxBytes = 0L; + } + if ( data.rxBytes == 0L ) + { + // on startup set to currently received bytes + data.rxBytes = rxBytes; + // this is new: KNemo only counts the traffic transfered + // while it is running. Important to not falsify statistics! + data.prevRxBytes = rxBytes; + } + else + // afterwards only add difference to previous number of bytes + data.rxBytes += rxBytes - data.prevRxBytes; + + data.incomingBytes = rxBytes - data.prevRxBytes; + data.prevRxBytes = rxBytes; + data.rxString = KIO::convertSize( data.rxBytes ); + } + + unsigned int txBytes = 0; + if ( readNumberFromFile( ifFolder + "statistics/tx_bytes", txBytes ) ) + { + // We count the traffic on ourself to avoid an overflow after + // 4GB of traffic. + if ( txBytes < data.prevTxBytes ) + { + // there was an overflow + if ( type == Interface::ETHERNET ) + { + // This makes data counting more accurate but will not work + // for interfaces that reset the transfered data to zero + // when deactivated like ppp does. + data.txBytes += 0xFFFFFFFF - data.prevTxBytes; + } + data.prevTxBytes = 0L; + } + if ( data.txBytes == 0L ) + { + // on startup set to currently received bytes + data.txBytes = txBytes; + // this is new: KNemo only counts the traffic transfered + // while it is running. Important to not falsify statistics! + data.prevTxBytes = txBytes; + } + else + // afterwards only add difference to previous number of bytes + data.txBytes += txBytes - data.prevTxBytes; + + data.outgoingBytes = txBytes - data.prevTxBytes; + data.prevTxBytes = txBytes; + data.txString = KIO::convertSize( data.txBytes ); + } + + if ( type == Interface::ETHERNET ) + { + QString hwAddress; + if ( readStringFromFile( ifFolder + "address", hwAddress ) ) + { + data.hwAddress = hwAddress; + } + + // for the default gateway we use the proc filesystem + QFile routeFile( PROCROUTE ); + if ( routeFile.open( IO_ReadOnly ) ) + { + QString routeData( routeFile.readAll().data() ); + QStringList routeEntries = QStringList::split( "\n", routeData ); + QStringList::Iterator it; + for ( it = routeEntries.begin(); it != routeEntries.end(); ++it ) + { + QRegExp regExp( ".*\\s+[\\w\\d]{8}\\s+([\\w\\d]{8})\\s+(\\d{4})" ); + if ( ( regExp.search( *it ) > -1 ) + && ( regExp.cap( 2 ).toUInt() & RTF_GATEWAY ) ) + { + bool ok; + struct in_addr in; + in.s_addr = regExp.cap( 1 ).toULong( &ok, 16 ); + data.defaultGateway = inet_ntoa( in ); + break; + } + } + routeFile.close(); + } + + } + + // use ioctls for the rest + int fd; + struct ifreq ifr; + if ( ( fd = socket(AF_INET, SOCK_DGRAM, 0) ) > -1 ) + { + strcpy( ifr.ifr_name, ifName.latin1() ); + ifr.ifr_addr.sa_family = AF_INET; + if ( ioctl( fd, SIOCGIFADDR, &ifr ) > -1 ) + { + data.ipAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr); + } + if ( ioctl( fd, SIOCGIFDSTADDR, &ifr) > -1 ) + { + data.ptpAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_dstaddr)->sin_addr); + } + + if ( ioctl( fd, SIOCGIFBRDADDR, &ifr ) > -1 ) + { + data.broadcastAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr); + } + + if ( ioctl( fd, SIOCGIFNETMASK, &ifr ) > -1 ) + { + data.subnetMask = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr); + } + close( fd ); + } +} + +void SysBackend::updateWirelessData( const QString& ifName, WirelessData& data ) +{ + QString wirelessFolder = SYSPATH + ifName + "/wireless/"; + + unsigned int link = 0; + if ( readNumberFromFile( wirelessFolder + "link", link ) ) + { + data.linkQuality = QString::number( link ); + } + +#ifdef HAVE_LIBIW + // The following code was taken from iwconfig.c and iwlib.c. + int fd; + if ( ( fd = iw_sockets_open() ) > 0 ) + { + struct iwreq wrq; + char buffer[128]; + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWFREQ, &wrq ) >= 0 ) + { + int channel = -1; + double freq = iw_freq2float( &( wrq.u.freq ) ); + struct iw_range range; + if( iw_get_range_info( fd, ifName.latin1(), &range ) >= 0 ) + { + if ( freq < KILO ) + { + channel = iw_channel_to_freq( (int) freq, &freq, &range ); + } + else + { + channel = iw_freq_to_channel( freq, &range ); + } + iw_print_freq_value( buffer, sizeof( buffer ), freq ); + data.frequency = buffer; + data.channel = QString::number( channel ); + } + } + + char essid[IW_ESSID_MAX_SIZE + 1]; + memset( essid, 0, IW_ESSID_MAX_SIZE + 1 ); + wrq.u.essid.pointer = (caddr_t) essid; + wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; + wrq.u.essid.flags = 0; + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWESSID, &wrq ) >= 0 ) + { + if ( wrq.u.data.flags > 0 ) + { + data.essid = essid; + } + else + { + data.essid = "any"; + } + } + + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWAP, &wrq ) >= 0 ) + { + char ap_addr[128]; + iw_ether_ntop( (const ether_addr*) wrq.u.ap_addr.sa_data, ap_addr); + data.accessPoint = ap_addr; + } + + memset( essid, 0, IW_ESSID_MAX_SIZE + 1 ); + wrq.u.essid.pointer = (caddr_t) essid; + wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; + wrq.u.essid.flags = 0; + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWNICKN, &wrq ) >= 0 ) + { + if ( wrq.u.data.length > 1 ) + { + data.nickName = essid; + } + else + { + data.nickName = QString::null; + } + } + + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWRATE, &wrq ) >= 0 ) + { + iwparam bitrate; + memcpy (&(bitrate), &(wrq.u.bitrate), sizeof (iwparam)); + iw_print_bitrate( buffer, sizeof( buffer ), wrq.u.bitrate.value ); + data.bitRate = buffer; + } + + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWMODE, &wrq ) >= 0 ) + { + int mode = wrq.u.mode; + if ( mode < IW_NUM_OPER_MODE && mode >= 0 ) + { + data.mode = iw_operation_mode[mode]; + } + else + { + data.mode = QString::null; + } + } + + unsigned char key[IW_ENCODING_TOKEN_MAX]; + wrq.u.data.pointer = (caddr_t) key; + wrq.u.data.length = IW_ENCODING_TOKEN_MAX; + wrq.u.data.flags = 0; + if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWENCODE, &wrq ) >= 0 ) + { + if ( ( wrq.u.data.flags & IW_ENCODE_DISABLED ) || ( wrq.u.data.length == 0 ) ) + { + data.encryption = false; + } + else + { + data.encryption = true; + } + } + else + { + data.encryption = false; + } + close( fd ); + } +#endif +} + diff --git a/src/knemod/backends/sysbackend.h b/src/knemod/backends/sysbackend.h new file mode 100644 index 0000000..10650b6 --- /dev/null +++ b/src/knemod/backends/sysbackend.h @@ -0,0 +1,54 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SYSBACKEND_H +#define SYSBACKEND_H + +#include "backendbase.h" + +/** + * The sys backend uses the sys filesystem available in 2.6 + * kernels. It reads all necessary information from the files + * and folders located at /sys and parses their output. + * It then triggers the interface monitor to look for changes + * in the state of the interface. + * + * @short Update the information of the interfaces via sys filesystem + * @author Percy Leonhardt <percy@eris23.de> + */ + +class SysBackend : public BackendBase +{ +public: + SysBackend(QDict<Interface>& interfaces ); + virtual ~SysBackend(); + + static BackendBase* createInstance( QDict<Interface>& interfaces ); + + void update(); + +private: + bool readNumberFromFile( const QString& fileName, unsigned int& value ); + bool readStringFromFile( const QString& fileName, QString& string ); + void updateWirelessData( const QString& ifName, WirelessData& data ); + void updateInterfaceData( const QString& ifName, InterfaceData& data, int type ); + +}; + +#endif // SYSBACKEND_H diff --git a/src/knemod/eventsrc b/src/knemod/eventsrc new file mode 100644 index 0000000..13f8aff --- /dev/null +++ b/src/knemod/eventsrc @@ -0,0 +1,220 @@ +[!Global!] +IconName=knemo +Comment=KDE Network Monitor +Comment[bg]=Монитор на мрежата +Comment[br]=Eveshaer ar rouedad evit KDE +Comment[cs]=KDE monitor sítě +Comment[da]=KDE's netværksovervågning +Comment[de]=KDE-Netzwerkmonitor +Comment[el]=Επίβλεψη δικτύου του KDE +Comment[es]=Monitor de red de KDE +Comment[et]=KDE võrgumonitor +Comment[ga]=Monatóir Líonra KDE +Comment[gl]=Un Monitor de Rede para KDE +Comment[it]=Monitor di rete di KDE +Comment[ja]=KDE ネットワークモニタ +Comment[ka]=KDE-ის ქსელის მონიტორი +Comment[lt]=Tinklo įrenginių stebėjimo KDE programa +Comment[nl]=KDE networkmonitor +Comment[pa]=KDE ਨੈਟਵਰਕ ਨਿਗਰਾਨ +Comment[pl]=Monitor sieci dla KDE +Comment[pt]=Monitor da Rede do KDE +Comment[pt_BR]=Monitor de Rede do KDE +Comment[ru]=Сетевой монитор KDE +Comment[sr]=Надгледање мреже за KDE +Comment[sr@Latn]=Nadgledanje mreže za KDE +Comment[sv]=KDE-nätverksövervakning +Comment[tr]=KDE Ağ İzleyici +Comment[uk]=Монітор мережі для KDE +Comment[xx]=xxKDE Network Monitorxx +Comment[zh_CN]=KDE 网络监视器 + +[knemo_connected] +Name=Connected +Name[bg]=Активно +Name[br]=Kevreet +Name[ca]=Connectat +Name[cs]=Připojen +Name[cy]=Wedi cysylltu +Name[da]=Forbundet +Name[de]=Verbunden +Name[el]=Συνδέθηκε +Name[es]=Conectado +Name[et]=Ühendatud +Name[fr]=Connecté +Name[ga]=Nasctha +Name[gl]=Conectado +Name[hi]=कनेक्टेड +Name[it]=Connesso +Name[ja]=接続 +Name[ka]=დაკავშირებულია +Name[lt]=Prijungta +Name[nl]=Verbonden +Name[pa]=ਜੁੜਿਆ +Name[pl]=Podłączony +Name[pt]=Ligado +Name[pt_BR]=Conectado +Name[ru]=Соединено +Name[sr]=Повезан +Name[sr@Latn]=Povezan +Name[sv]=Uppkopplat +Name[ta]=இணைக்கப்பட்டது +Name[tr]=Bağlı +Name[uk]=З'єднано +Name[xx]=xxConnectedxx +Name[zh_CN]=已连接 +Comment=Interface is connected +Comment[bg]=Интерфейсът е активен +Comment[br]=Kevreet eo an etrefas +Comment[cs]=Rozhraní je připojeno +Comment[da]=Grænseflade er forbundet +Comment[de]=Die Schnittstelle ist verbunden +Comment[el]=Η διασύνδεση είναι συνδεδεμένη +Comment[es]=La interfaz está conectada +Comment[et]=Liides on ühendatud +Comment[ga]=Tá an comhéadan nasctha +Comment[gl]=A interface está conectada +Comment[it]=L'interfaccia è connessa +Comment[ja]=インターフェースが接続されました +Comment[ka]=ინტერფეისი დაკავშირებულია +Comment[lt]=Įrenginys prijungtas +Comment[nl]=Interface is verbonden +Comment[pa]=ਇੰਟਰਫੇਸ ਜੁੜਿਆ ਹੈ +Comment[pl]=Interfejs jest podłączony +Comment[pt]=A interface foi ligada +Comment[pt_BR]=A interface está conectada +Comment[ru]=Интерфейс подключен +Comment[sr]=Интерфејс је повезан +Comment[sr@Latn]=Interfejs je povezan +Comment[sv]=Gränssnittet är uppkopplat +Comment[tr]=Arayüz bağlandı +Comment[uk]=Інтерфейс з'єднано +Comment[xx]=xxInterface is connectedxx +Comment[zh_CN]=接口已连接 +default_sound=KDE_Dialog_Appear.wav +default_presentation=17 + +[knemo_disconnected] +Name=Disconnected +Name[bg]=Неактивен +Name[br]=Digevreet +Name[ca]=Desconnectat +Name[cs]=Odpojen +Name[cy]=Datgysylltwyd +Name[da]=Afbrudt +Name[de]=Getrennt +Name[el]=Αποσυνδέθηκε +Name[es]=Desconectado +Name[et]=Lahutatud +Name[fr]=Déconnecté +Name[ga]=Dínasctha +Name[gl]=Desconectada +Name[hi]=डिस्कनेक्टेड +Name[it]=Disconnesso +Name[ja]=切断 +Name[ka]=კავშირი გაწყვეტილია +Name[lt]=Atjungta +Name[nl]=Niet verbonden +Name[pa]=ਜੁੜਿਆ ਨਹੀਂ +Name[pl]=Rozłączony +Name[pt]=Desligado +Name[pt_BR]=Desconectado +Name[ru]=Отключено +Name[sr]=Неповезан +Name[sr@Latn]=Nepovezan +Name[sv]=Nerkopplat +Name[ta]=துண்டிக்கப்பட்டது +Name[tr]=Bağlantı kesildi +Name[uk]=Роз'єднано +Name[xx]=xxDisconnectedxx +Name[zh_CN]=已断开 +Comment=Interface is disconnected +Comment[bg]=Интерфейсът е неактивен +Comment[br]=Digevreet eo an etrefas +Comment[cs]=Rozhraní je odpojeno +Comment[da]=Grænseflade er afbrudt +Comment[de]=Die Schnittstelle ist nicht verbunden +Comment[el]=Η διασύνδεση αποσυνδέθηκε +Comment[es]=La interfaz está desconectada +Comment[et]=Liides on lahutatud +Comment[ga]=Tá an comhéadan dínasctha +Comment[gl]=A interface está desconectada +Comment[it]=L'interfaccia è disconnessa +Comment[ja]=インターフェースが切断されました +Comment[ka]=ინტერფეისის კავშირი გაწყვეტილია +Comment[lt]=Įrenginys atjungtas +Comment[nl]=Interface is niet verbonden +Comment[pa]=ਇੰਟਰਫੇਸ ਜੁੜਿਆ ਨਹੀਂ ਹੈ +Comment[pl]=Interfejs jest rozłączony +Comment[pt]=A interface foi desligada +Comment[pt_BR]=A interface está desconectada +Comment[ru]=Интерфейс не подключен +Comment[sr]=Интерфејс је неповезан +Comment[sr@Latn]=Interfejs je nepovezan +Comment[sv]=Gränssnittet är nerkopplat +Comment[tr]=Arayüz bağlantısı kesildi +Comment[uk]=Інтерфейс роз'єднано +Comment[xx]=xxInterface is disconnectedxx +Comment[zh_CN]=接口已断开 +default_sound=KDE_Dialog_Disappear.wav +default_presentation=17 + +[knemo_notexisting] +Name=Not existing +Name[bg]=Несъществуващ +Name[br]=N'eo ket endeo +Name[cs]=Neexistuje +Name[da]=Eksisterer ikke +Name[de]=Existiert nicht +Name[el]=Δεν υπάρχει +Name[es]=Inexistente +Name[et]=Pole olemas +Name[ga]=Níl sé ann +Name[gl]=Non existe +Name[it]=Inesistente +Name[ja]=存在しません +Name[ka]=არ არსებობს +Name[lt]=Nėra +Name[nl]=Niet-bestaand +Name[pa]=ਮੌਜੂਦ ਨਹੀਂ +Name[pl]=Nie istnieje +Name[pt]=Não existente +Name[pt_BR]=Inexistente +Name[ru]=Не существует +Name[sr]=Не постоји +Name[sr@Latn]=Ne postoji +Name[sv]=Existerar inte +Name[tr]=Mevcut değil +Name[uk]=Не існує +Name[xx]=xxNot existingxx +Name[zh_CN]=不存在 +Comment=Interface does not exist +Comment[bg]=Интерфейсът не съществува +Comment[br]=N'eo ket endeo an etrefas +Comment[cs]=Rozhraní neexistuje +Comment[da]=Grænsefladen eksisterer ikke +Comment[de]=Die Schnittstelle existiert nicht +Comment[el]=Η διασύνδεση δεν υπάρχει +Comment[es]=La interfaz no existe +Comment[et]=Liidest pole olemas +Comment[ga]=Níl an comhéadan ann +Comment[gl]=A interface non existe +Comment[it]=L'interfaccia non esiste +Comment[ja]=インターフェースが存在しません +Comment[ka]=ინტერფეისი არ არსებობს +Comment[lt]=Įrenginio nėra +Comment[nl]=De interface bestaat niet +Comment[pa]=ਇੰਟਰਫੇਸ ਮੌਜੂਦ ਨਹੀਂ ਹੈ +Comment[pl]=Interfejs nie istnieje +Comment[pt]=A interface não existe +Comment[pt_BR]=A interface não existe +Comment[ru]=Интерфейс не существует +Comment[sr]=Интерфејс не постоји +Comment[sr@Latn]=Interfejs ne postoji +Comment[sv]=Gränssnittet finns inte +Comment[tr]=Arayüz mevcut değil +Comment[uk]=Інтерфейсу не існує +Comment[xx]=xxInterface does not existxx +Comment[zh_CN]=接口不存在 +default_sound=KDE_Notify.wav +default_presentation=0 diff --git a/src/knemod/global.h b/src/knemod/global.h new file mode 100644 index 0000000..d00a54e --- /dev/null +++ b/src/knemod/global.h @@ -0,0 +1,130 @@ +/* This file is part of KNemo + Copyright (C) 2005 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef GLOBAL_H +#define GLOBAL_H + +#include <qpair.h> +#include <qcolor.h> +#include <qstring.h> + +/** + * This file contains data structures and enums used in the knemo daemon. + * + * @short Daemon wide structures and enums + * @author Percy Leonhardt <percy@eris23.de> + */ + +struct GeneralData +{ + int toolTipContent; + int pollInterval; + int saveInterval; + QString statisticsDir; +}; + +struct InterfaceData +{ + InterfaceData() + : existing( false ), + available( false ), + wirelessDevice( false ), + prevRxPackets( 0L ), + prevTxPackets( 0L ), + rxPackets( 0L ), + txPackets( 0L ), + prevRxBytes( 0L ), + prevTxBytes( 0L ), + incomingBytes( 0L ), + outgoingBytes( 0L ), + rxBytes( 0L ), + txBytes( 0L ) + {} + + bool existing; + bool available; + bool wirelessDevice; + unsigned long prevRxPackets; + unsigned long prevTxPackets; + unsigned long rxPackets; + unsigned long txPackets; + unsigned long prevRxBytes; + unsigned long prevTxBytes; + unsigned long incomingBytes; + unsigned long outgoingBytes; + QString ipAddress; + QString subnetMask; + QString hwAddress; + QString ptpAddress; + QString broadcastAddress; + QString defaultGateway; + QString rxString; + QString txString; + Q_UINT64 rxBytes; + Q_UINT64 txBytes; +}; + +struct WirelessData +{ + QString essid; + QString mode; + QString frequency; + QString channel; + QString bitRate; + QString linkQuality; + QString accessPoint; + QString nickName; + bool encryption; +}; + +struct PlotterSettings +{ + int pixel; + int count; + int distance; + int fontSize; + int minimumValue; + int maximumValue; + bool labels; + bool topBar; + bool showIncoming; + bool showOutgoing; + bool verticalLines; + bool horizontalLines; + bool automaticDetection; + bool verticalLinesScroll; + QColor colorVLines; + QColor colorHLines; + QColor colorIncoming; + QColor colorOutgoing; + QColor colorBackground; +}; + +struct StatisticEntry +{ + int day; + int month; + int year; + Q_UINT64 rxBytes; + Q_UINT64 txBytes; +}; + +extern QPair<QString, int> ToolTips[]; + +#endif // GLOBAL_H diff --git a/src/knemod/interface.cpp b/src/knemod/interface.cpp new file mode 100644 index 0000000..2378662 --- /dev/null +++ b/src/knemod/interface.cpp @@ -0,0 +1,487 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qtimer.h> +#include <qpixmap.h> + +#include <kwin.h> +#include <kdebug.h> +#include <klocale.h> +#include <kwinmodule.h> +#include <kiconloader.h> + +#include "interface.h" +#include "signalplotter.h" +#include "interfacestatistics.h" +#include "interfacestatusdialog.h" +#include "interfacestatisticsdialog.h" + +Interface::Interface( QString ifname, + const GeneralData& generalData, + const PlotterSettings& plotterSettings ) + : QObject(), + mType( UNKNOWN_TYPE ), + mState( UNKNOWN_STATE ), + mOutgoingPos( 0 ), + mIncomingPos( 0 ), + mName( ifname ), + mPlotterTimer( 0 ), + mIcon( this ), + mStatistics( 0 ), + mStatusDialog( 0 ), + mStatisticsDialog( 0 ), + mPlotter( 0 ), + mVisibleBeams( NONE ), + mGeneralData( generalData ), + mPlotterSettings( plotterSettings ) +{ + connect( &mMonitor, SIGNAL( statusChanged( int ) ), + &mIcon, SLOT( updateStatus( int ) ) ); + connect( &mMonitor, SIGNAL( available( int ) ), + &mIcon, SLOT( updateTrayStatus( int ) ) ); + connect( &mMonitor, SIGNAL( notAvailable( int ) ), + &mIcon, SLOT( updateTrayStatus( int ) ) ); + connect( &mMonitor, SIGNAL( notExisting( int ) ), + &mIcon, SLOT( updateTrayStatus( int ) ) ); + connect( &mMonitor, SIGNAL( available( int ) ), + this, SLOT( setStartTime( int ) ) ); + connect( &mMonitor, SIGNAL( statusChanged( int ) ), + this, SLOT( resetData( int ) ) ); + connect( &mIcon, SIGNAL( statisticsSelected() ), + this, SLOT( showStatisticsDialog() ) ); +} + +Interface::~Interface() +{ + if ( mStatusDialog != 0 ) + { + delete mStatusDialog; + } + if ( mPlotter != 0 ) + { + delete mPlotter; + } + if ( mPlotterTimer != 0 ) + { + mPlotterTimer->stop(); + delete mPlotterTimer; + } + if ( mStatistics != 0 ) + { + // this will also delete a possibly open statistics dialog + stopStatistics(); + } +} + +void Interface::configChanged() +{ + // UNKNOWN_STATE to avoid notification + mIcon.updateTrayStatus( UNKNOWN_STATE ); + // handle changed iconset by user + mIcon.updateStatus( mState ); + mIcon.updateToolTip(); + mIcon.updateMenu(); + + if ( mPlotter != 0L ) + { + configurePlotter(); + } + + if ( mStatistics != 0 ) + { + mStatistics->configChanged(); + } + + if ( mSettings.activateStatistics && mStatistics == 0 ) + { + // user turned on statistics + startStatistics(); + } + else if ( !mSettings.activateStatistics && mStatistics != 0 ) + { + // user turned off statistics + stopStatistics(); + } + + if ( mStatusDialog ) + { + mStatusDialog->setStatisticsGroupEnabled( mSettings.activateStatistics ); + } +} + +void Interface::activateMonitor() +{ + mMonitor.checkStatus( this ); +} + +void Interface::setStartTime( int ) +{ + mStartTime.setDate( QDate::currentDate() ); + mStartTime.setTime( QTime::currentTime() ); +} + +void Interface::showStatusDialog() +{ + // Toggle the status dialog. + // First click will show the status dialog, second will hide it. + if ( mStatusDialog == 0L ) + { + mStatusDialog = new InterfaceStatusDialog( this ); + connect( &mMonitor, SIGNAL( available( int ) ), + mStatusDialog, SLOT( enableNetworkGroups( int ) ) ); + connect( &mMonitor, SIGNAL( notAvailable( int ) ), + mStatusDialog, SLOT( disableNetworkGroups( int ) ) ); + connect( &mMonitor, SIGNAL( notExisting( int ) ), + mStatusDialog, SLOT( disableNetworkGroups( int ) ) ); + if ( mStatistics != 0 ) + { + connect( mStatistics, SIGNAL( currentEntryChanged() ), + mStatusDialog, SLOT( statisticsChanged() ) ); + mStatusDialog->statisticsChanged(); + } + activateOrHide( mStatusDialog, true ); + } + else + { + // Toggle the status dialog. + activateOrHide( mStatusDialog ); + } +} + +void Interface::showSignalPlotter( bool wasMiddleButton ) +{ + // No plotter, create it. + if ( mPlotter == 0L ) + { + mPlotter = new SignalPlotter( 0L, mName.local8Bit() ); + mPlotter->setIcon( SmallIcon( "knemo" ) ); + mPlotter->setCaption( mName + " " + i18n( "Traffic" ) ); + mPlotter->setTitle( mName ); + configurePlotter(); + activateOrHide( mPlotter, true ); + + mPlotterTimer = new QTimer(); + connect( mPlotterTimer, SIGNAL( timeout() ), + this, SLOT( updatePlotter() ) ); + mPlotterTimer->start( 1000 ); + } + else + { + if ( wasMiddleButton ) + { + // Toggle the signal plotter. + activateOrHide( mPlotter ); + } + else + { + // Called from the context menu, show the dialog. + activateOrHide( mPlotter, true ); + } + } +} + +void Interface::showStatisticsDialog() +{ + if ( mStatisticsDialog == 0 ) + { + mStatisticsDialog = new InterfaceStatisticsDialog( this ); + if ( mStatistics == 0 ) + { + // should never happen but you never know... + startStatistics(); + } + connect( mStatistics, SIGNAL( dayStatisticsChanged() ), + mStatisticsDialog, SLOT( updateDays() ) ); + connect( mStatistics, SIGNAL( monthStatisticsChanged() ), + mStatisticsDialog, SLOT( updateMonths() ) ); + connect( mStatistics, SIGNAL( yearStatisticsChanged() ), + mStatisticsDialog, SLOT( updateYears() ) ); + connect( mStatistics, SIGNAL( currentEntryChanged() ), + mStatisticsDialog, SLOT( updateCurrentEntry() ) ); + connect( mStatisticsDialog, SIGNAL( clearDailyStatisticsClicked() ), + mStatistics, SLOT( clearDayStatistics() ) ); + connect( mStatisticsDialog, SIGNAL( clearMonthlyStatisticsClicked() ), + mStatistics, SLOT( clearMonthStatistics() ) ); + connect( mStatisticsDialog, SIGNAL( clearYearlyStatisticsClicked() ), + mStatistics, SLOT( clearYearStatistics() ) ); + + mStatisticsDialog->updateDays(); + mStatisticsDialog->updateMonths(); + mStatisticsDialog->updateYears(); + } + mStatisticsDialog->show(); +} + +void Interface::resetData( int state ) +{ + // For PPP interfaces we will reset all data to zero when the + // interface gets disconnected. If the driver also resets its data + // (like PPP seems to do) we will start from zero for every new + // connection. + if ( mType == PPP && + ( state == NOT_AVAILABLE || + state == NOT_EXISTING ) ) + { + mData.prevTxBytes = mData.txBytes = 0; + mData.prevRxBytes = mData.rxBytes = 0; + mData.prevTxPackets = mData.txPackets = 0; + mData.prevRxPackets = mData.rxPackets = 0; + } +} + +void Interface::updatePlotter() +{ + if ( mPlotter ) + { + double outgoingBytes = mData.outgoingBytes / 1024.0 / (double) mGeneralData.pollInterval; + double incomingBytes = mData.incomingBytes / 1024.0 / (double) mGeneralData.pollInterval; + + QValueList<double> trafficList; + switch ( mVisibleBeams ) + { + case BOTH: + if ( mIncomingPos == 1 ) + { + trafficList.append( outgoingBytes ); + trafficList.append( incomingBytes ); + } + else + { + trafficList.append( incomingBytes ); + trafficList.append( outgoingBytes ); + } + mPlotter->addSample( trafficList ); + break; + case INCOMING_TRAFFIC: + trafficList.append( incomingBytes ); + mPlotter->addSample( trafficList ); + break; + case OUTGOING_TRAFFIC: + trafficList.append( outgoingBytes ); + mPlotter->addSample( trafficList ); + break; + case NONE: + break; + } + } +} + +void Interface::configurePlotter() +{ + mPlotter->setFontSize( mPlotterSettings.fontSize ); + if ( !mPlotterSettings.automaticDetection ) + { + mPlotter->setMinValue( mPlotterSettings.minimumValue ); + mPlotter->setMaxValue( mPlotterSettings.maximumValue ); + } + mPlotter->setHorizontalScale( mPlotterSettings.pixel ); + mPlotter->setHorizontalLinesCount( mPlotterSettings.count ); + mPlotter->setVerticalLinesDistance( mPlotterSettings.distance ); + mPlotter->setShowLabels( mPlotterSettings.labels ); + mPlotter->setShowTopBar( mPlotterSettings.topBar ); + mPlotter->setShowVerticalLines( mPlotterSettings.verticalLines ); + mPlotter->setShowHorizontalLines( mPlotterSettings.horizontalLines ); + mPlotter->setUseAutoRange( mPlotterSettings.automaticDetection ); + mPlotter->setVerticalLinesScroll( mPlotterSettings.verticalLinesScroll ); + mPlotter->setVerticalLinesColor( mPlotterSettings.colorVLines ); + mPlotter->setHorizontalLinesColor( mPlotterSettings.colorHLines ); + mPlotter->setBackgroundColor( mPlotterSettings.colorBackground ); + + // add or remove beams according to user settings + VisibleBeams nextVisibleBeams = NONE; + if ( mPlotterSettings.showOutgoing ) + nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | OUTGOING_TRAFFIC ); + if ( mPlotterSettings.showIncoming ) + nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | INCOMING_TRAFFIC ); + + QValueList<QColor>& colors = mPlotter->beamColors(); + switch( mVisibleBeams ) + { + case NONE: + if ( nextVisibleBeams == BOTH ) + { + mOutgoingPos = 0; + mPlotter->addBeam( mPlotterSettings.colorOutgoing ); + mIncomingPos = 1; + mPlotter->addBeam( mPlotterSettings.colorIncoming ); + } + else if ( nextVisibleBeams == OUTGOING_TRAFFIC ) + { + mOutgoingPos = 0; + mPlotter->addBeam( mPlotterSettings.colorOutgoing ); + } + else if ( nextVisibleBeams == INCOMING_TRAFFIC ) + { + mIncomingPos = 0; + mPlotter->addBeam( mPlotterSettings.colorIncoming ); + } + break; + case INCOMING_TRAFFIC: + if ( nextVisibleBeams == BOTH ) + { + mOutgoingPos = 1; + mPlotter->addBeam( mPlotterSettings.colorOutgoing ); + } + else if ( nextVisibleBeams == OUTGOING_TRAFFIC ) + { + mPlotter->removeBeam( mIncomingPos ); + mOutgoingPos = 0; + mPlotter->addBeam( mPlotterSettings.colorOutgoing ); + } + else if ( nextVisibleBeams == INCOMING_TRAFFIC ) + { + colors[mIncomingPos] = ( mPlotterSettings.colorIncoming ); + } + else if ( nextVisibleBeams == NONE ) + { + mPlotter->removeBeam( mIncomingPos ); + } + break; + case OUTGOING_TRAFFIC: + if ( nextVisibleBeams == BOTH ) + { + mIncomingPos = 1; + mPlotter->addBeam( mPlotterSettings.colorIncoming ); + } + else if ( nextVisibleBeams == INCOMING_TRAFFIC ) + { + mPlotter->removeBeam( mOutgoingPos ); + mIncomingPos = 0; + mPlotter->addBeam( mPlotterSettings.colorIncoming ); + } + else if ( nextVisibleBeams == OUTGOING_TRAFFIC ) + { + colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing ); + } + else if ( nextVisibleBeams == NONE ) + { + mPlotter->removeBeam( mOutgoingPos ); + } + break; + case BOTH: + if ( nextVisibleBeams == BOTH ) + { + colors[mIncomingPos] = ( mPlotterSettings.colorIncoming ); + colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing ); + } + else if ( nextVisibleBeams == OUTGOING_TRAFFIC ) + { + mOutgoingPos = 0; + mPlotter->removeBeam( mIncomingPos ); + } + else if ( nextVisibleBeams == INCOMING_TRAFFIC ) + { + mIncomingPos = 0; + mPlotter->removeBeam( mOutgoingPos ); + } + else if ( nextVisibleBeams == NONE ) + { + mPlotter->removeBeam( 0 ); + mPlotter->removeBeam( 0 ); + } + break; + } + mVisibleBeams = nextVisibleBeams; + mPlotter->repaint(); +} + +void Interface::startStatistics() +{ + mStatistics = new InterfaceStatistics( this ); + connect( &mMonitor, SIGNAL( incomingData( unsigned long ) ), + mStatistics, SLOT( addIncomingData( unsigned long ) ) ); + connect( &mMonitor, SIGNAL( outgoingData( unsigned long ) ), + mStatistics, SLOT( addOutgoingData( unsigned long ) ) ); + if ( mStatusDialog != 0 ) + { + connect( mStatistics, SIGNAL( currentEntryChanged() ), + mStatusDialog, SLOT( statisticsChanged() ) ); + mStatusDialog->statisticsChanged(); + } + + mStatistics->loadStatistics(); +} + +void Interface::stopStatistics() +{ + if ( mStatisticsDialog != 0 ) + { + // this will close an open statistics dialog + delete mStatisticsDialog; + mStatisticsDialog = 0; + } + + mStatistics->saveStatistics(); + + delete mStatistics; + mStatistics = 0; +} + +// taken from ksystemtray.cpp +void Interface::activateOrHide( QWidget* widget, bool onlyActivate ) +{ + if ( !widget ) + return; + + KWin::WindowInfo info1 = KWin::windowInfo( widget->winId(), NET::XAWMState | NET::WMState ); + // mapped = visible (but possibly obscured) + bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); + // - not mapped -> show, raise, focus + // - mapped + // - obscured -> raise, focus + // - not obscured -> hide + if( !mapped ) + { + KWin::setOnDesktop( widget->winId(), KWin::currentDesktop() ); + widget->show(); + widget->raise(); + KWin::activateWindow( widget->winId() ); + } + else + { + KWinModule module; + for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast(); + it != module.stackingOrder().end() && (*it) != widget->winId(); + --it ) + { + KWin::WindowInfo info2 = KWin::windowInfo( *it, (unsigned long) + NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType ); + if( info2.mappingState() != NET::Visible ) + continue; // not visible on current desktop -> ignore + if( !info2.geometry().intersects( widget->geometry())) + continue; // not obscuring the window -> ignore + if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove )) + continue; // obscured by window kept above -> ignore + NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask + | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask + | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask ); + if( type == NET::Dock || type == NET::TopMenu ) + continue; // obscured by dock or topmenu -> ignore + widget->raise(); + KWin::activateWindow( widget->winId()); + return; + } + if ( !onlyActivate ) + { + widget->hide(); + } + } +} + +#include "interface.moc" diff --git a/src/knemod/interface.h b/src/knemod/interface.h new file mode 100644 index 0000000..06bea0a --- /dev/null +++ b/src/knemod/interface.h @@ -0,0 +1,243 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include <qobject.h> +#include <qstring.h> +#include <qdatetime.h> + +#include "data.h" +#include "global.h" +#include "interfaceicon.h" +#include "interfacemonitor.h" + +class QTimer; +class SignalPlotter; +class InterfaceStatistics; +class InterfaceStatusDialog; +class InterfaceStatisticsDialog; + +/** + * This class is the central place for all things that belong to an + * interface. It stores some information and knows about the interface + * data, icon, monitor and settings. + * + * @short Central class for every interface + * @author Percy Leonhardt <percy@eris23.de> + */ +class Interface : public QObject +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + Interface(QString ifname, + const GeneralData& generalData, + const PlotterSettings& plotterSettings ); + + /** + * Default Destructor + */ + virtual ~Interface(); + + void setType( int type ) + { + mType = type; + } + + int getType() + { + return mType; + } + + void setState( int state ) + { + mState = state; + } + + int getState() + { + return mState; + } + + const QDateTime& getStartTime() const + { + return mStartTime; + } + + const QString& getName() const + { + return mName; + } + + InterfaceData& getData() + { + return mData; + } + + InterfaceSettings& getSettings() + { + return mSettings; + } + + WirelessData& getWirelessData() + { + return mWirelessData; + } + + const GeneralData& getGeneralData() const + { + return mGeneralData; + } + + InterfaceStatistics* getStatistics() + { + return mStatistics; + } + + /** + * Called from reparseConfiguration() when the user changed + * the settings. + */ + void configChanged(); + + /** + * Called from the interface updater class after new data from + * 'ifconfig' has been read. This will trigger the monitor to + * to look for changes in interface data or interface state. + */ + void activateMonitor(); + + enum InterfaceState + { + UNKNOWN_STATE = -1, + NOT_EXISTING = 0, + NOT_AVAILABLE = 1, + AVAILABLE = 2, + RX_TRAFFIC = 4, + TX_TRAFFIC = 8 + }; + + enum InterfaceType + { + UNKNOWN_TYPE, + ETHERNET, + PPP + }; + + enum IconSet + { + MONITOR = 0, + MODEM, + NETWORK, + WIRELESS + }; + +public slots: + /* + * Called when the user left-clicks on the tray icon + * Toggles the status dialog by showing it on the first click and + * hiding it on the second click. + */ + void showStatusDialog(); + + /* + * Called when the user middle-clicks on the tray icon + * Toggles the signal plotter that displays the incoming and + * outgoing traffic. + */ + void showSignalPlotter( bool wasMiddleButton ); + + /* + * Called when the user selects the appropriate entry in the context menu. + */ + void showStatisticsDialog(); + + /* + * Reset data when PPP interface is disconnected + */ + void resetData( int state ); + +private slots: + /** + * Start the uptimer when the interface is connected + */ + void setStartTime( int ); + + /** + * Update the signal plotter with new data + */ + void updatePlotter(); + + /** + * Configure the signal plotter with user settings + */ + void configurePlotter(); + +private: + /** + * Start the statistics and load previously saved ones + */ + void startStatistics(); + + /** + * Store the statistics and stop collecting any further data + */ + void stopStatistics(); + + /** + * The following function is taken from ksystemtray.cpp for + * correct show, raise, focus and hide of status dialog and + * signal plotter. + */ + void activateOrHide( QWidget* widget, bool onlyActivate = false ); + + enum VisibleBeams + { + NONE = 0, + INCOMING_TRAFFIC = 1, + OUTGOING_TRAFFIC = 2, + BOTH = 3 + }; + + int mType; + int mState; + int mOutgoingPos; + int mIncomingPos; + QString mName; + QTimer* mPlotterTimer; + QDateTime mStartTime; + InterfaceIcon mIcon; + InterfaceData mData; + InterfaceMonitor mMonitor; + InterfaceSettings mSettings; + InterfaceStatistics* mStatistics; + WirelessData mWirelessData; + InterfaceStatusDialog* mStatusDialog; + InterfaceStatisticsDialog* mStatisticsDialog; + SignalPlotter* mPlotter; + VisibleBeams mVisibleBeams; + const GeneralData& mGeneralData; + const PlotterSettings& mPlotterSettings; +}; + +#endif // INTERFACE_H diff --git a/src/knemod/interfaceicon.cpp b/src/knemod/interfaceicon.cpp new file mode 100644 index 0000000..4bda3df --- /dev/null +++ b/src/knemod/interfaceicon.cpp @@ -0,0 +1,309 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2005 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <unistd.h> + +#include <qpixmap.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kprocess.h> +#include <kpopupmenu.h> +#include <kiconloader.h> +#include <knotifyclient.h> + +#include "data.h" +#include "interface.h" +#include "knemodaemon.h" +#include "interfaceicon.h" +#include "interfacetray.h" +#include "interfacemonitor.h" +#include "interfacetooltip.h" + +const QString InterfaceIcon::ICON_DISCONNECTED = "network_disconnected"; +const QString InterfaceIcon::ICON_CONNECTED = "network_connected"; +const QString InterfaceIcon::ICON_INCOMING = "network_incoming"; +const QString InterfaceIcon::ICON_OUTGOING = "network_outgoing"; +const QString InterfaceIcon::ICON_TRAFFIC = "network_traffic"; +const QString InterfaceIcon::SUFFIX_PPP = "_ppp"; +const QString InterfaceIcon::SUFFIX_LAN = "_lan"; +const QString InterfaceIcon::SUFFIX_WLAN = "_wlan"; + +InterfaceIcon::InterfaceIcon( Interface* interface ) + : QObject(), + mInterface( interface ), + mTray( 0L ) +{ +} + +InterfaceIcon::~InterfaceIcon() +{ + if ( mTray != 0L ) + delete mTray; +} + +void InterfaceIcon::updateStatus( int status ) +{ + if ( mTray == 0L ) + return; + + // If the user wants something different than the default icons + // append the correct suffix to the filename. + QString suffix; + if ( mInterface->getSettings().iconSet == Interface::NETWORK ) + { + suffix = SUFFIX_LAN; + } + else if ( mInterface->getSettings().iconSet == Interface::WIRELESS ) + { + suffix = SUFFIX_WLAN; + } + else if ( mInterface->getSettings().iconSet == Interface::MODEM ) + { + suffix = SUFFIX_PPP; + } + else + { + suffix = ""; // use standard icons + } + + // Now set the correct icon depending on the status of the interface. + if ( status == Interface::NOT_AVAILABLE || + status == Interface::NOT_EXISTING ) + { + mTray->setPixmap( mTray->loadIcon( ICON_DISCONNECTED + suffix ) ); + } + else if ( ( status & Interface::RX_TRAFFIC ) && + ( status & Interface::TX_TRAFFIC ) ) + { + mTray->setPixmap( mTray->loadIcon( ICON_TRAFFIC + suffix ) ); + } + else if ( status & Interface::RX_TRAFFIC ) + { + mTray->setPixmap( mTray->loadIcon( ICON_INCOMING + suffix ) ); + } + else if ( status & Interface::TX_TRAFFIC ) + { + mTray->setPixmap( mTray->loadIcon( ICON_OUTGOING + suffix ) ); + } + else + { + mTray->setPixmap( mTray->loadIcon( ICON_CONNECTED + suffix ) ); + } +} + +void InterfaceIcon::updateToolTip() +{ + if ( mTray == 0L ) + return; + + QString toolTip = mInterface->getSettings().alias; + if ( toolTip == QString::null ) + toolTip = mInterface->getName(); + new InterfaceToolTip( mInterface, mTray ); +} + +void InterfaceIcon::updateMenu() +{ + if ( mTray == 0L ) + return; + + // Remove all old entries. + KPopupMenu* menu = mTray->contextMenu(); + int count = menu->count(); + for ( int i = 0; i < count - 6; i++ ) + menu->removeItemAt( 6 ); + + InterfaceSettings& settings = mInterface->getSettings(); + + // If the user wants statistics, add an entry to show them. + if ( settings.activateStatistics ) + { + menu->insertItem( i18n( "Open &Statistics" ), this, + SIGNAL( statisticsSelected() ) ); + } + + // If the user wants custom commands, add them. + if ( settings.customCommands ) + { + menu->insertSeparator(); + QValueVector<InterfaceCommand>::iterator it; + for ( it = settings.commands.begin(); it != settings.commands.end(); it++ ) + (*it).id = menu->insertItem( (*it).menuText ); + } +} + +void InterfaceIcon::updateTrayStatus( int previousState ) +{ + bool interfaceExists = mInterface->getData().existing; + bool interfaceAvailable = mInterface->getData().available; + bool hideWhenNotExisting = mInterface->getSettings().hideWhenNotExisting; + bool hideWhenNotAvailable = mInterface->getSettings().hideWhenNotAvailable; + + // notification 'interface not available' + if ( !interfaceAvailable && mTray != 0L && + previousState == Interface::AVAILABLE ) + { + /* When KNemo is starting we don't show the change in connection + * status as this would be annoying when KDE starts. + */ + QString title; + if ( mInterface->getSettings().alias != QString::null ) + title = mInterface->getSettings().alias; + else + title = mInterface->getName(); + + KNotifyClient::event( mTray->winId(), "knemo_disconnected", + title + ":\n" + i18n( "Not connected." ) ); + /* Wait half a second before deleting the tray so that the call + * to the notification daemon has a chance to run before the + * winId gets invalid. + */ + usleep( 500000 ); + } + + // notification 'interface not existing' + if ( !interfaceExists && mTray != 0L && + previousState != Interface::UNKNOWN_STATE ) + { + /* When KNemo is starting we don't show the change in connection + * status as this would be annoying when KDE starts. + */ + QString title; + if ( mInterface->getSettings().alias != QString::null ) + title = mInterface->getSettings().alias; + else + title = mInterface->getName(); + + KNotifyClient::event( mTray->winId(), "knemo_notexisting", + title + ":\n" + i18n( "Not existing." ) ); + /* Wait half a second before deleting the tray so that the call + * to the notification daemon has a chance to run before the + * winId gets invalid. + */ + usleep( 500000 ); + } + + /* Remove the icon if + * - the interface is not available and the option to hide it is selected + * - the interface does not exist, the option to hide it is selected + * and the other option is not selected + */ + if ( mTray != 0L && + ( ( !interfaceAvailable && hideWhenNotAvailable ) || + ( !interfaceExists && hideWhenNotExisting && !hideWhenNotAvailable ) ) ) + { + delete mTray; + mTray = 0L; + } + /* Create the icon if + * - the interface is available + * - the interface is not available and the option to hide it is not + * selected and the interface does exist + * - the interface does not exist and the option to hide it is not selected + * and the other option is not selected + */ + else if ( mTray == 0L && + ( interfaceAvailable || + ( !interfaceAvailable && !hideWhenNotAvailable && interfaceExists ) || + ( !interfaceExists && !hideWhenNotExisting && !hideWhenNotAvailable ) ) ) + { + mTray = new InterfaceTray( mInterface->getName() ); + QToolTip::add( mTray, mInterface->getName() ); + KPopupMenu* menu = mTray->contextMenu(); + connect( menu, SIGNAL( activated( int ) ), + this, SLOT( menuActivated( int ) ) ); + connect( mTray, SIGNAL( leftClicked() ), + mInterface, SLOT( showStatusDialog() ) ); + connect( mTray, SIGNAL( graphSelected( bool ) ), + mInterface, SLOT( showSignalPlotter( bool ) ) ); + connect( mTray, SIGNAL( configSelected() ), + this, SLOT( showConfigDialog() ) ); + + updateStatus( mInterface->getState() ); + updateToolTip(); + updateMenu(); + mTray->show(); + } + + // notification 'interface available' + if ( interfaceAvailable && mTray != 0L && + previousState != Interface::UNKNOWN_STATE ) + { + /* When KNemo is starting we don't show the change in connection + * status as this would be annoying when KDE starts. + */ + QString title; + if ( mInterface->getSettings().alias != QString::null ) + title = mInterface->getSettings().alias; + else + title = mInterface->getName(); + + /* Wait half a second before calling the notification daemon + * so that the winId of the tray is valid when used below. + */ + usleep( 500000 ); + if ( mInterface->getData().wirelessDevice ) + { + KNotifyClient::event( mTray->winId(), "knemo_connected", + title + ":\n" + i18n( "Connection established to\n" ) + + mInterface->getWirelessData().essid ); + } + else + { + KNotifyClient::event( mTray->winId(), "knemo_connected", + title + ":\n" + i18n( "Connection established." ) ); + } + } +} + +void InterfaceIcon::showConfigDialog() +{ + KNemoDaemon::sSelectedInterface = mInterface->getName(); + + KProcess process; + process << "kcmshell" << "kcm_knemo"; + process.start( KProcess::DontCare ); +} + +void InterfaceIcon::menuActivated( int id ) +{ + InterfaceSettings& settings = mInterface->getSettings(); + QValueVector<InterfaceCommand>::iterator it; + for ( it = settings.commands.begin(); it != settings.commands.end(); it++ ) + { + if ( (*it).id == id ) + { + KProcess process; + if ( (*it).runAsRoot ) + { + process << "kdesu"; + process << (*it).command; + } + else + process << QStringList::split( ' ', (*it).command ); + + process.start( KProcess::DontCare ); + break; + } + } +} + +#include "interfaceicon.moc" diff --git a/src/knemod/interfaceicon.h b/src/knemod/interfaceicon.h new file mode 100644 index 0000000..96d320b --- /dev/null +++ b/src/knemod/interfaceicon.h @@ -0,0 +1,105 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2005 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACEICON_H +#define INTERFACEICON_H + +#include <qobject.h> +#include <qstring.h> + +class Interface; +class InterfaceTray; + +/** + * This is the logical representation of the systemtray icon. It handles + * creation and deletion of the real icon, setting the tooltip, setting + * the correct icon image and displaying of the settings dialog. + * + * @short Logical representation of the systemtray icon + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceIcon : public QObject +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceIcon( Interface* interface ); + + /** + * Default Destructor + */ + virtual ~InterfaceIcon(); + + /* + * Change the tooltip according to the alias of the interface + */ + void updateToolTip(); + + /* + * Fill the context menu with entries if the user configured + * start and stop command + */ + void updateMenu(); + +signals: + void statisticsSelected(); + +public slots: + /* + * Changes the icon image displayed in the tray + */ + void updateStatus( int status ); + + /* + * Creates or deletes the tray icon + */ + void updateTrayStatus( int previousState ); + +private slots: + /* + * Called when the user selects 'Configure KNemo' from the context menu + */ + void showConfigDialog(); + + /* + * Called when the user setup custom commands and selects one + * in the context menu + */ + void menuActivated( int id ); + +private: + // the interface this icon belongs to + Interface* mInterface; + // the real tray icon + InterfaceTray* mTray; + + static const QString ICON_DISCONNECTED; + static const QString ICON_CONNECTED; + static const QString ICON_INCOMING; + static const QString ICON_OUTGOING; + static const QString ICON_TRAFFIC; + static const QString SUFFIX_PPP; + static const QString SUFFIX_LAN; + static const QString SUFFIX_WLAN; +}; + +#endif // INTERFACEICON_H diff --git a/src/knemod/interfacemonitor.cpp b/src/knemod/interfacemonitor.cpp new file mode 100644 index 0000000..b75d35e --- /dev/null +++ b/src/knemod/interfacemonitor.cpp @@ -0,0 +1,100 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> + +#include "interface.h" +#include "interfacemonitor.h" + +InterfaceMonitor::InterfaceMonitor( QObject* parent, const char* name ) + : QObject( parent, name ) +{ +} + +InterfaceMonitor::~InterfaceMonitor() +{ +} + +void InterfaceMonitor::checkStatus( Interface* interface ) +{ + int currentState; + int previousState = interface->getState(); + InterfaceData& data = interface->getData(); + int trafficThreshold = interface->getSettings().trafficThreshold; + + if ( !data.existing ) + // the interface does not exist + currentState = Interface::NOT_EXISTING; + else if ( !data.available ) + // the interface exists but is not connected + currentState = Interface::NOT_AVAILABLE; + else + { + // the interface is connected, look for traffic + currentState = Interface::AVAILABLE; + if ( ( data.rxPackets - data.prevRxPackets ) > (unsigned int) trafficThreshold ) + currentState |= Interface::RX_TRAFFIC; + if ( ( data.txPackets - data.prevTxPackets ) > (unsigned int) trafficThreshold ) + currentState |= Interface::TX_TRAFFIC; + } + + // update the statistics + if ( data.incomingBytes > 0 ) + { + emit incomingData( data.incomingBytes ); + } + if ( data.outgoingBytes > 0 ) + { + emit outgoingData( data.outgoingBytes ); + } + + data.prevRxPackets = data.rxPackets; + data.prevTxPackets = data.txPackets; + + if ( ( previousState == Interface::NOT_EXISTING || + previousState == Interface::NOT_AVAILABLE || + previousState == Interface::UNKNOWN_STATE ) && + currentState & Interface::AVAILABLE ) + { + emit available( previousState ); + } + else if ( ( previousState == Interface::NOT_EXISTING || + previousState & Interface::AVAILABLE || + previousState == Interface::UNKNOWN_STATE ) && + currentState == Interface::NOT_AVAILABLE ) + { + emit notAvailable( previousState ); + } + else if ( ( previousState == Interface::NOT_AVAILABLE || + previousState & Interface::AVAILABLE || + previousState == Interface::UNKNOWN_STATE ) && + currentState == Interface::NOT_EXISTING ) + { + emit notExisting( previousState ); + } + + // make sure the icon fits the current state + if ( previousState != currentState ) + { + emit statusChanged( currentState ); + interface->setState( currentState ); + } +} + +#include "interfacemonitor.moc" diff --git a/src/knemod/interfacemonitor.h b/src/knemod/interfacemonitor.h new file mode 100644 index 0000000..eacc1ea --- /dev/null +++ b/src/knemod/interfacemonitor.h @@ -0,0 +1,72 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACEMONITOR_H +#define INTERFACEMONITOR_H + +#include <qobject.h> + +#include "data.h" + +class Interface; + +/** + * This class monitors the interface for possible state changes and + * for incoming and outgong traffic. If the state changed or traffic + * was transmitted it sends an according signal. + * + * @short Monitor changes of the interface + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceMonitor : public QObject +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceMonitor(QObject* parent = 0L, const char* name = 0L); + + /** + * Default Destructor + */ + virtual ~InterfaceMonitor(); + + /** + * Tell the monitor to check the status of the interface + */ + void checkStatus( Interface* interface ); + +signals: + // the interface is now connected + void available( int ); + // the interface is now disconnected + void notAvailable( int ); + // the interface no longer exists + void notExisting( int ); + // there was incoming and/or outgoing traffic + void statusChanged( int ); + // the amount of incoming traffic (for statistics) + void incomingData( unsigned long ); + // the amount of outgoing traffic (for statistics) + void outgoingData( unsigned long ); +}; + +#endif // INTERFACEMONITOR_H diff --git a/src/knemod/interfacestatistics.cpp b/src/knemod/interfacestatistics.cpp new file mode 100644 index 0000000..a73d04b --- /dev/null +++ b/src/knemod/interfacestatistics.cpp @@ -0,0 +1,384 @@ +/* This file is part of KNemo + Copyright (C) 2005, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qdom.h> +#include <qfile.h> +#include <qtimer.h> +#include <qstring.h> +#include <qdatetime.h> + +#include <kdebug.h> + +#include "interface.h" +#include "interfacestatistics.h" + +InterfaceStatistics::InterfaceStatistics( Interface* interface ) + : QObject(), + mInterface( interface ) +{ + mDayStatistics.setAutoDelete( true ); + mMonthStatistics.setAutoDelete( true ); + mYearStatistics.setAutoDelete( true ); + initStatistics(); + + mSaveTimer = new QTimer(); + connect( mSaveTimer, SIGNAL( timeout() ), this, SLOT( saveStatistics() ) ); + mSaveTimer->start( mInterface->getGeneralData().saveInterval * 1000 ); +} + +InterfaceStatistics::~InterfaceStatistics() +{ + mSaveTimer->stop(); + delete mSaveTimer; + + mDayStatistics.clear(); + mMonthStatistics.clear(); + mYearStatistics.clear(); +} + +void InterfaceStatistics::loadStatistics() +{ + QDomDocument doc( "statistics" ); + QString dir = mInterface->getGeneralData().statisticsDir; + QFile file( dir + "/statistics_" + mInterface->getName() ); + + if ( !file.open( IO_ReadOnly ) ) + return; + if ( !doc.setContent( &file ) ) + { + file.close(); + return; + } + file.close(); + + mDayStatistics.clear(); + mMonthStatistics.clear(); + mYearStatistics.clear(); + + QDomElement root = doc.documentElement(); + QDomNode n = root.namedItem( "days" ); + if ( !n.isNull() ) + { + QDomNode dayNode = n.firstChild(); + while ( !dayNode.isNull() ) + { + QDomElement day = dayNode.toElement(); + if ( !day.isNull() ) + { + StatisticEntry* entry = new StatisticEntry(); + entry->day = day.attribute( "day" ).toInt(); + entry->month = day.attribute( "month" ).toInt(); + entry->year = day.attribute( "year" ).toInt(); + entry->rxBytes = (Q_UINT64) day.attribute( "rxBytes" ).toDouble(); + entry->txBytes = (Q_UINT64) day.attribute( "txBytes" ).toDouble(); + mDayStatistics.append( entry ); + } + dayNode = dayNode.nextSibling(); + } + mDayStatistics.sort(); + } + + n = root.namedItem( "months" ); + if ( !n.isNull() ) + { + QDomNode monthNode = n.firstChild(); + while ( !monthNode.isNull() ) + { + QDomElement month = monthNode.toElement(); + if ( !month.isNull() ) + { + StatisticEntry* entry = new StatisticEntry(); + entry->day = 0; + entry->month = month.attribute( "month" ).toInt(); + entry->year = month.attribute( "year" ).toInt(); + entry->rxBytes = (Q_UINT64) month.attribute( "rxBytes" ).toDouble(); + entry->txBytes = (Q_UINT64) month.attribute( "txBytes" ).toDouble(); + mMonthStatistics.append( entry ); + } + monthNode = monthNode.nextSibling(); + } + mMonthStatistics.sort(); + } + + n = root.namedItem( "years" ); + if ( !n.isNull() ) + { + QDomNode yearNode = n.firstChild(); + while ( !yearNode.isNull() ) + { + QDomElement year = yearNode.toElement(); + if ( !year.isNull() ) + { + StatisticEntry* entry = new StatisticEntry(); + entry->day = 0; + entry->month = 0; + entry->year = year.attribute( "year" ).toInt(); + entry->rxBytes = (Q_UINT64) year.attribute( "rxBytes" ).toDouble(); + entry->txBytes = (Q_UINT64) year.attribute( "txBytes" ).toDouble(); + mYearStatistics.append( entry ); + } + yearNode = yearNode.nextSibling(); + } + mYearStatistics.sort(); + } + initStatistics(); +} + +void InterfaceStatistics::saveStatistics() +{ + QDomDocument doc( "statistics" ); + QDomElement root = doc.createElement( "statistics" ); + doc.appendChild( root ); + + QDomElement days = doc.createElement( "days" ); + StatisticEntry* iterator = mDayStatistics.first(); + while ( iterator ) + { + QDomElement day = doc.createElement( "day" ); + day.setAttribute( "day", iterator->day ); + day.setAttribute( "month", iterator->month ); + day.setAttribute( "year", iterator->year ); + day.setAttribute( "rxBytes", (double) iterator->rxBytes ); + day.setAttribute( "txBytes", (double) iterator->txBytes ); + days.appendChild( day ); + iterator = mDayStatistics.next(); + } + root.appendChild( days ); + + QDomElement months = doc.createElement( "months" ); + iterator = mMonthStatistics.first(); + while ( iterator ) + { + QDomElement month = doc.createElement( "month" ); + month.setAttribute( "month", iterator->month ); + month.setAttribute( "year", iterator->year ); + month.setAttribute( "rxBytes", (double) iterator->rxBytes ); + month.setAttribute( "txBytes", (double) iterator->txBytes ); + months.appendChild( month ); + iterator = mMonthStatistics.next(); + } + root.appendChild( months ); + + QDomElement years = doc.createElement( "years" ); + iterator = mYearStatistics.first(); + while ( iterator ) + { + QDomElement year = doc.createElement( "year" ); + year.setAttribute( "year", iterator->year ); + year.setAttribute( "rxBytes", (double) iterator->rxBytes ); + year.setAttribute( "txBytes", (double) iterator->txBytes ); + years.appendChild( year ); + iterator = mYearStatistics.next(); + } + root.appendChild( years ); + + QString dir = mInterface->getGeneralData().statisticsDir; + QFile file( dir + "/statistics_" + mInterface->getName() ); + if ( !file.open( IO_WriteOnly ) ) + return; + + QTextStream stream( &file ); + stream << doc.toString(); + file.close(); +} + +void InterfaceStatistics::configChanged() +{ + // restart the timer with the new value + mSaveTimer->changeInterval( mInterface->getGeneralData().saveInterval * 1000 ); +} + +const StatisticEntry* InterfaceStatistics::getCurrentDay() const +{ + return mCurrentDay; +} + +const StatisticEntry* InterfaceStatistics::getCurrentMonth() const +{ + return mCurrentMonth; +} + +const StatisticEntry* InterfaceStatistics::getCurrentYear() const +{ + return mCurrentYear; +} + +const StatisticsPtrList<StatisticEntry>& InterfaceStatistics::getDayStatistics() const +{ + return mDayStatistics; +} + +const StatisticsPtrList<StatisticEntry>& InterfaceStatistics::getMonthStatistics() const +{ + return mMonthStatistics; +} + +const StatisticsPtrList<StatisticEntry>& InterfaceStatistics::getYearStatistics() const +{ + return mYearStatistics; +} + +void InterfaceStatistics::addIncomingData( unsigned long data ) +{ + checkCurrentEntry(); + + mCurrentDay->rxBytes += data; + mCurrentMonth->rxBytes += data; + mCurrentYear->rxBytes += data; + + emit currentEntryChanged(); +} + +void InterfaceStatistics::addOutgoingData( unsigned long data ) +{ + checkCurrentEntry(); + + mCurrentDay->txBytes += data; + mCurrentMonth->txBytes += data; + mCurrentYear->txBytes += data; + + emit currentEntryChanged(); +} + +void InterfaceStatistics::clearDayStatistics() +{ + mDayStatistics.clear(); + updateCurrentDay(); +} + +void InterfaceStatistics::clearMonthStatistics() +{ + mMonthStatistics.clear(); + updateCurrentMonth(); +} + +void InterfaceStatistics::clearYearStatistics() +{ + mYearStatistics.clear(); + updateCurrentYear(); +} + +void InterfaceStatistics::checkCurrentEntry() +{ + if ( mCurrentDay->day != QDate::currentDate().day() || + mCurrentDay->month != QDate::currentDate().month() || + mCurrentDay->year != QDate::currentDate().year() ) + { + // current day has changed + updateCurrentDay(); + + if ( mCurrentMonth->month != QDate::currentDate().month() || + mCurrentMonth->year != QDate::currentDate().year() ) + { + // current month has also changed + updateCurrentMonth(); + } + + if ( mCurrentYear->year != QDate::currentDate().year() ) + { + // current year has also changed + updateCurrentYear(); + } + } +} + +void InterfaceStatistics::initStatistics() +{ + updateCurrentDay(); + updateCurrentMonth(); + updateCurrentYear(); + + emit currentEntryChanged(); +} + +void InterfaceStatistics::updateCurrentDay() +{ + mCurrentDay = mDayStatistics.first(); + while ( mCurrentDay ) + { + if ( mCurrentDay->day == QDate::currentDate().day() && + mCurrentDay->month == QDate::currentDate().month() && + mCurrentDay->year == QDate::currentDate().year() ) + { + // found current day in list + return; + } + mCurrentDay = mDayStatistics.next(); + } + + // the current day is not in the list + mCurrentDay = new StatisticEntry(); + mCurrentDay->day = QDate::currentDate().day(); + mCurrentDay->month = QDate::currentDate().month(); + mCurrentDay->year = QDate::currentDate().year(); + mCurrentDay->rxBytes = 0; + mCurrentDay->txBytes = 0; + mDayStatistics.append( mCurrentDay ); // TODO: insert at correct position + emit dayStatisticsChanged(); +} + +void InterfaceStatistics::updateCurrentMonth() +{ + mCurrentMonth = mMonthStatistics.first(); + while ( mCurrentMonth ) + { + if ( mCurrentMonth->month == QDate::currentDate().month() && + mCurrentMonth->year == QDate::currentDate().year() ) + { + // found current month in list + return; + } + mCurrentMonth = mMonthStatistics.next(); + } + + // the current month is not in the list + mCurrentMonth = new StatisticEntry(); + mCurrentMonth->day = 0; + mCurrentMonth->month = QDate::currentDate().month(); + mCurrentMonth->year = QDate::currentDate().year(); + mCurrentMonth->rxBytes = 0; + mCurrentMonth->txBytes = 0; + mMonthStatistics.append( mCurrentMonth ); // TODO: insert at correct position + emit monthStatisticsChanged(); +} + +void InterfaceStatistics::updateCurrentYear() +{ + mCurrentYear = mYearStatistics.first(); + while ( mCurrentYear ) + { + if ( mCurrentYear->year == QDate::currentDate().year() ) + { + // found current year in list + return; + } + mCurrentYear = mYearStatistics.next(); + } + + // the current year is not in the list + mCurrentYear = new StatisticEntry(); + mCurrentYear->day = 0; + mCurrentYear->month = 0; + mCurrentYear->year = QDate::currentDate().year(); + mCurrentYear->rxBytes = 0; + mCurrentYear->txBytes = 0; + mYearStatistics.append( mCurrentYear ); // TODO: insert at correct position + emit yearStatisticsChanged(); +} + diff --git a/src/knemod/interfacestatistics.h b/src/knemod/interfacestatistics.h new file mode 100644 index 0000000..a4e3246 --- /dev/null +++ b/src/knemod/interfacestatistics.h @@ -0,0 +1,191 @@ +/* This file is part of KNemo + Copyright (C) 2005, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACESTATISTICS_H +#define INTERFACESTATISTICS_H + +#include <qobject.h> +#include <qptrlist.h> + +#include "global.h" + +class QTimer; +class Interface; + +template<class type> +class StatisticsPtrList : public QPtrList<type> +{ +protected: + virtual int compareItems ( QPtrCollection::Item item1, QPtrCollection::Item item2 ) + { + StatisticEntry* entry1 = static_cast<StatisticEntry*>( item1 ); + StatisticEntry* entry2 = static_cast<StatisticEntry*>( item2 ); + + if ( entry1->year > entry2->year ) + { + return 1; + } + else if ( entry2->year > entry1->year ) + { + return -1; + } // ...here we know that years are the same... + else if ( entry1->month > entry2->month ) + { + return 1; + } + else if ( entry2->month > entry1->month ) + { + return -1; + } // ...here we know that months are the same... + else if ( entry1->day > entry2->day ) + { + return 1; + } + else if ( entry2->day > entry1->day ) + { + return -1; + } // ...here we know that dates are equal. + + return 0; + }; +}; + +/** + * This class is able to collect transfered data for an interface, + * store it in a file and deliver it on request. + * + * @short Statistics of transfered data for an interface + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceStatistics : public QObject +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceStatistics( Interface* interface ); + + /** + * Default Destructor + */ + virtual ~InterfaceStatistics(); + + /** + * Load the statistics from a xml file + */ + void loadStatistics(); + + /** + * Called from Interface::configChanged() when the user + * changed the settings. + */ + void configChanged(); + + const StatisticEntry* getCurrentDay() const; + const StatisticEntry* getCurrentMonth() const; + const StatisticEntry* getCurrentYear() const; + const StatisticsPtrList<StatisticEntry>& getDayStatistics() const; + const StatisticsPtrList<StatisticEntry>& getMonthStatistics() const; + const StatisticsPtrList<StatisticEntry>& getYearStatistics() const; + +signals: + /** + * The current entry has changed. There is only one signal + * for day, month and year because if the day changes, + * month and year also change. + */ + void currentEntryChanged(); + /** + * The list has changed i.e. there is a new day entry or the list was cleared + */ + void dayStatisticsChanged(); + /** + * The list has changed i.e. there is a new month entry or the list was cleared + */ + void monthStatisticsChanged(); + /** + * The list has changed i.e. there is a new year entry or the list was cleared + */ + void yearStatisticsChanged(); + +public slots: + /** + * Save the statistics to a xml file + * (slot so it can be triggered by a timer signal) + */ + void saveStatistics(); + /** + * Add incoming data to the current day, month and year + */ + void addIncomingData( unsigned long data ); + /** + * Add outgoing data to the current day, month and year + */ + void addOutgoingData( unsigned long data ); + /** + * Clear all entries of the day statistics + */ + void clearDayStatistics(); + /** + * Clear all entries of the month statistics + */ + void clearMonthStatistics(); + /** + * Clear all entries of the year statistics + */ + void clearYearStatistics(); + +private: + /** + * Make sure the current entry corresponds with the current date + */ + void checkCurrentEntry(); + /** + * Fill the statistics with a current entry + */ + void initStatistics(); + /** + * Check if the current day is in the day statistics. If found set + * mCurrentDay to the found entry else create a new one. + */ + void updateCurrentDay(); + /** + * Check if the current month is in the month statistics. If found set + * mCurrentMonth to the found entry else create a new one. + */ + void updateCurrentMonth(); + /** + * Check if the current year is in the year statistics. If found set + * mCurrentYear to the found entry else create a new one. + */ + void updateCurrentYear(); + + QTimer* mSaveTimer; + Interface* mInterface; + StatisticEntry* mCurrentDay; + StatisticEntry* mCurrentMonth; + StatisticEntry* mCurrentYear; + StatisticsPtrList<StatisticEntry> mDayStatistics; + StatisticsPtrList<StatisticEntry> mMonthStatistics; + StatisticsPtrList<StatisticEntry> mYearStatistics; +}; + +#endif // INTERFACESTATISTICS_H diff --git a/src/knemod/interfacestatisticsdialog.cpp b/src/knemod/interfacestatisticsdialog.cpp new file mode 100644 index 0000000..55ee49a --- /dev/null +++ b/src/knemod/interfacestatisticsdialog.cpp @@ -0,0 +1,139 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qtable.h> +#include <qdatetime.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <kio/global.h> +#include <kiconloader.h> +#include <kcalendarsystem.h> + +#include "data.h" +#include "interface.h" +#include "interfacestatistics.h" +#include "interfacestatisticsdialog.h" + +/* + * I assume that the last entry in each table is also the current. This will fail + * if we walk back in time, so better not play with the system date... + */ + +InterfaceStatisticsDialog::InterfaceStatisticsDialog( Interface* interface, QWidget* parent, const char* name ) + : InterfaceStatisticsDlg( parent, name ), + mInterface( interface ) +{ + setIcon( SmallIcon( "knemo" ) ); + setCaption( interface->getName() + " " + i18n( "Statistics" ) ); + + connect( buttonClearDaily, SIGNAL( clicked() ), SIGNAL( clearDailyStatisticsClicked() ) ); + connect( buttonClearMonthly, SIGNAL( clicked() ), SIGNAL( clearMonthlyStatisticsClicked() ) ); + connect( buttonClearYearly, SIGNAL( clicked() ), SIGNAL( clearYearlyStatisticsClicked() ) ); +} + +InterfaceStatisticsDialog::~InterfaceStatisticsDialog() +{ +} + +void InterfaceStatisticsDialog::updateDays() +{ + QPtrList<StatisticEntry> dayStatistics = mInterface->getStatistics()->getDayStatistics(); + StatisticEntry* iterator = dayStatistics.first(); + tableDaily->setNumRows( dayStatistics.count() ); + int row = 0; + while ( iterator ) + { + QDate date( iterator->year, iterator->month, iterator->day ); + tableDaily->verticalHeader()->setLabel( row, KGlobal::locale()->formatDate( date, true ) ); + tableDaily->setText( row, 0, KIO::convertSize( iterator->txBytes ) ); + tableDaily->setText( row, 1, KIO::convertSize( iterator->rxBytes ) ); + tableDaily->setText( row, 2, KIO::convertSize( iterator->rxBytes + iterator->txBytes ) ); + row++; + iterator = dayStatistics.next(); + } + + tableDaily->setCurrentCell( row - 1, 2 ); + tableDaily->ensureCellVisible( row - 1, 2 ); +} + +void InterfaceStatisticsDialog::updateMonths() +{ + QPtrList<StatisticEntry> monthStatistics = mInterface->getStatistics()->getMonthStatistics(); + StatisticEntry* iterator = monthStatistics.first(); + tableMonthly->setNumRows( monthStatistics.count() ); + int row = 0; + while ( iterator ) + { + const KCalendarSystem* calendar = KGlobal::locale()->calendar(); + QString monthName = calendar->monthName( iterator->month, iterator->year ) + " " + QString::number( iterator->year ); + tableMonthly->verticalHeader()->setLabel( row, monthName ); + tableMonthly->setText( row, 0, KIO::convertSize( iterator->txBytes ) ); + tableMonthly->setText( row, 1, KIO::convertSize( iterator->rxBytes ) ); + tableMonthly->setText( row, 2, KIO::convertSize( iterator->rxBytes + iterator->txBytes ) ); + row++; + iterator = monthStatistics.next(); + } + + tableMonthly->setCurrentCell( row - 1, 2 ); + tableMonthly->ensureCellVisible( row - 1, 2 ); +} + +void InterfaceStatisticsDialog::updateYears() +{ + QPtrList<StatisticEntry> yearStatistics = mInterface->getStatistics()->getYearStatistics(); + StatisticEntry* iterator = yearStatistics.first(); + tableYearly->setNumRows( yearStatistics.count() ); + int row = 0; + while ( iterator ) + { + tableYearly->verticalHeader()->setLabel( row, QString::number( iterator->year ) ); + tableYearly->setText( row, 0, KIO::convertSize( iterator->txBytes ) ); + tableYearly->setText( row, 1, KIO::convertSize( iterator->rxBytes ) ); + tableYearly->setText( row, 2, KIO::convertSize( iterator->rxBytes + iterator->txBytes ) ); + row++; + iterator = yearStatistics.next(); + } + + tableYearly->setCurrentCell( row - 1, 2 ); + tableYearly->ensureCellVisible( row - 1, 2 ); +} + +void InterfaceStatisticsDialog::updateCurrentEntry() +{ + int lastRow = tableDaily->numRows() - 1; + const StatisticEntry* currentEntry = mInterface->getStatistics()->getCurrentDay(); + tableDaily->setText( lastRow, 0, KIO::convertSize( currentEntry->txBytes ) ); + tableDaily->setText( lastRow, 1, KIO::convertSize( currentEntry->rxBytes ) ); + tableDaily->setText( lastRow, 2, KIO::convertSize( currentEntry->rxBytes + currentEntry->txBytes ) ); + + lastRow = tableMonthly->numRows() - 1; + currentEntry = mInterface->getStatistics()->getCurrentMonth(); + tableMonthly->setText( lastRow, 0, KIO::convertSize( currentEntry->txBytes ) ); + tableMonthly->setText( lastRow, 1, KIO::convertSize( currentEntry->rxBytes ) ); + tableMonthly->setText( lastRow, 2, KIO::convertSize( currentEntry->rxBytes + currentEntry->txBytes ) ); + + lastRow = tableYearly->numRows() - 1; + currentEntry = mInterface->getStatistics()->getCurrentYear(); + tableYearly->setText( lastRow, 0, KIO::convertSize( currentEntry->txBytes ) ); + tableYearly->setText( lastRow, 1, KIO::convertSize( currentEntry->rxBytes ) ); + tableYearly->setText( lastRow, 2, KIO::convertSize( currentEntry->rxBytes + currentEntry->txBytes ) ); +} + +#include "interfacestatisticsdialog.moc" diff --git a/src/knemod/interfacestatisticsdialog.h b/src/knemod/interfacestatisticsdialog.h new file mode 100644 index 0000000..ce5e0e3 --- /dev/null +++ b/src/knemod/interfacestatisticsdialog.h @@ -0,0 +1,68 @@ +/* This file is part of KNemo + Copyright (C) 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACESTATISTICSDIALOG_H +#define INTERFACESTATISTICSDIALOG_H + +#include <qwidget.h> + +#include "interfacestatisticsdlg.h" + +class QTimer; +class Interface; + +/** + * This class shows the statistics dialog. It contains the tables for the + * different statistics. + * + * @short Statistics dialog + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceStatisticsDialog : public InterfaceStatisticsDlg +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceStatisticsDialog( Interface* interface, + QWidget* parent = 0L, const char* name = 0L ); + + /** + * Default Destructor + */ + virtual ~InterfaceStatisticsDialog(); + +signals: + void clearDailyStatisticsClicked(); + void clearMonthlyStatisticsClicked(); + void clearYearlyStatisticsClicked(); + +public slots: + void updateDays(); + void updateMonths(); + void updateYears(); + void updateCurrentEntry(); + +private: + Interface* mInterface; +}; + +#endif // INTERFACESTATISTICSDIALOG_H diff --git a/src/knemod/interfacestatisticsdlg.ui b/src/knemod/interfacestatisticsdlg.ui new file mode 100644 index 0000000..b028832 --- /dev/null +++ b/src/knemod/interfacestatisticsdlg.ui @@ -0,0 +1,230 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>InterfaceStatisticsDlg</class> +<widget class="QDialog"> + <property name="name"> + <cstring>InterfaceStatisticsDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>490</width> + <height>502</height> + </rect> + </property> + <property name="caption"> + <string>Statistics</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>buttonClose</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QTabWidget" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>tabWidget</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>daily</cstring> + </property> + <attribute name="title"> + <string>Daily</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTable"> + <column> + <property name="text"> + <string>Sent</string> + </property> + </column> + <column> + <property name="text"> + <string>Received</string> + </property> + </column> + <column> + <property name="text"> + <string>Total</string> + </property> + </column> + <property name="name"> + <cstring>tableDaily</cstring> + </property> + <property name="numRows"> + <number>1</number> + </property> + <property name="numCols"> + <number>3</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonClearDaily</cstring> + </property> + <property name="text"> + <string>Clear daily statistics</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>monthy</cstring> + </property> + <attribute name="title"> + <string>Monthly</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTable"> + <column> + <property name="text"> + <string>Sent</string> + </property> + </column> + <column> + <property name="text"> + <string>Received</string> + </property> + </column> + <column> + <property name="text"> + <string>Total</string> + </property> + </column> + <property name="name"> + <cstring>tableMonthly</cstring> + </property> + <property name="numRows"> + <number>1</number> + </property> + <property name="numCols"> + <number>3</number> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonClearMonthly</cstring> + </property> + <property name="text"> + <string>Clear monthly statistics</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>yearly</cstring> + </property> + <attribute name="title"> + <string>Yearly</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTable"> + <column> + <property name="text"> + <string>Sent</string> + </property> + </column> + <column> + <property name="text"> + <string>Received</string> + </property> + </column> + <column> + <property name="text"> + <string>Total</string> + </property> + </column> + <property name="name"> + <cstring>tableYearly</cstring> + </property> + <property name="numRows"> + <number>1</number> + </property> + <property name="numCols"> + <number>3</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonClearYearly</cstring> + </property> + <property name="text"> + <string>Clear yearly statistics</string> + </property> + </widget> + </vbox> + </widget> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer28</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>211</width> + <height>31</height> + </size> + </property> + </spacer> + <spacer row="1" column="2"> + <property name="name"> + <cstring>spacer29</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>201</width> + <height>31</height> + </size> + </property> + </spacer> + </grid> +</widget> +<connections> + <connection> + <sender>buttonClose</sender> + <signal>clicked()</signal> + <receiver>InterfaceStatisticsDlg</receiver> + <slot>close()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/knemod/interfacestatusdialog.cpp b/src/knemod/interfacestatusdialog.cpp new file mode 100644 index 0000000..87260af --- /dev/null +++ b/src/knemod/interfacestatusdialog.cpp @@ -0,0 +1,308 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qtimer.h> +#include <qlabel.h> +#include <qstring.h> +#include <qgroupbox.h> +#include <qdatetime.h> +#include <qtabwidget.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kactivelabel.h> +#include <kio/global.h> + +#include "data.h" +#include "interface.h" +#include "interfacestatistics.h" +#include "interfacestatusdialog.h" + +InterfaceStatusDialog::InterfaceStatusDialog( Interface* interface, QWidget* parent, const char* name ) + : InterfaceStatusDlg( parent, name ), + mPosInitialized( false ), + mInterface( interface ) +{ + setIcon( SmallIcon( "knemo" ) ); + setCaption( interface->getName() + " " + i18n( "Interface Status" ) ); + updateDialog(); + if ( interface->getData().available ) + { + enableNetworkGroups( 0 ); + } + else + { + disableNetworkGroups( 0 ); + } + if ( !interface->getData().wirelessDevice ) + { + QWidget* wirelessTab = tabWidget->page( 2 ); + tabWidget->removePage( wirelessTab ); + delete wirelessTab; + } + + if ( !interface->getSettings().activateStatistics ) + { + setStatisticsGroupEnabled( false ); + } + + // Restore window size and position. + KConfig* config = new KConfig( "knemorc", false ); + if ( config->hasGroup( "Interface_" + mInterface->getName() ) ) + { + config->setGroup( "Interface_" + mInterface->getName() ); + if ( config->hasKey( "StatusX" ) && config->hasKey( "StatusY" ) ) + { + mPos.setX( config->readNumEntry( "StatusX" ) ); + mPos.setY( config->readNumEntry( "StatusY" ) ); + mPosInitialized = true; + } + if ( config->hasKey( "StatusWidth" ) && config->hasKey( "StatusHeight" ) ) + resize( config->readNumEntry( "StatusWidth" ), + config->readNumEntry( "StatusHeight" ) ); + } + delete config; + + statisticsChanged(); + + mTimer = new QTimer(); + connect( mTimer, SIGNAL( timeout() ), this, SLOT( updateDialog() ) ); + mTimer->start( 1000 ); +} + +InterfaceStatusDialog::~InterfaceStatusDialog() +{ + mTimer->stop(); + delete mTimer; + + // Store window size and position. + KConfig* config = new KConfig( "knemorc", false ); + if ( config->hasGroup( "Interface_" + mInterface->getName() ) ) + { + config->setGroup( "Interface_" + mInterface->getName() ); + config->writeEntry( "StatusX", x() ); + config->writeEntry( "StatusY", y() ); + config->writeEntry( "StatusWidth", width() ); + config->writeEntry( "StatusHeight", height() ); + config->sync(); + } + delete config; +} + +void InterfaceStatusDialog::hide() +{ + mPos = pos(); + mPosInitialized = true; + QDialog::hide(); +} + +void InterfaceStatusDialog::show() +{ + QDialog::show(); + /** + * mPosInitialized should always be true, except when + * starting KNemo for the very first time. + */ + if ( mPosInitialized ) + move( mPos ); +} + +void InterfaceStatusDialog::setStatisticsGroupEnabled( bool enabled ) +{ + groupBoxStatistics->setEnabled( enabled ); +} + +void InterfaceStatusDialog::updateDialog() +{ + InterfaceData& data = mInterface->getData(); + InterfaceSettings& settings = mInterface->getSettings(); + + // connection tab + textLabelInterface->setText( mInterface->getName() ); + textLabelAlias->setText( settings.alias ); + if ( data.available ) + { + textLabelStatus->setText( i18n( "Connection established." ) ); + int upsecs = mInterface->getStartTime().secsTo( QDateTime::currentDateTime() ); + int updays = upsecs / 86400; // don't use QDateTime::daysTo() because + // we only want complete days + + QString uptime; + if ( updays == 1 ) + uptime = "1 day, "; + else if ( updays > 1 ) + uptime = QString( "%1 days, " ).arg( updays ); + + upsecs -= 86400 * updays; // we only want the seconds of today + int hrs = upsecs / 3600; + int mins = ( upsecs - hrs * 3600 ) / 60; + int secs = upsecs - hrs * 3600 - mins * 60; + QString time; + time.sprintf( "%02d:%02d:%02d", hrs, mins, secs ); + uptime += time; + textLabelUptime->setText( uptime ); + } + else if ( data.existing ) + { + textLabelStatus->setText( i18n( "Not connected." ) ); + textLabelUptime->setText( "00:00:00" ); + } + else + { + textLabelStatus->setText( i18n( "Not existing." ) ); + textLabelUptime->setText( "00:00:00" ); + } + + if ( data.available ) + { + // ip tab + textLabelIP->setText( data.ipAddress ); + textLabelSubnet->setText( data.subnetMask ); + if ( mInterface->getType() == Interface::ETHERNET ) + { + variableLabel1->setText( i18n( "Broadcast Address:" ) ); + variableText1->setText( data.broadcastAddress ); + variableLabel2->setText( i18n( "Default Gateway:" ) ); + variableText2->setText( data.defaultGateway ); + variableLabel3->setText( i18n( "HW-Address:" ) ); + variableText3->setText( data.hwAddress ); + } + else if ( mInterface->getType() == Interface::PPP ) + { + variableLabel1->setText( i18n( "PtP-Address:" ) ); + variableText1->setText( data.ptpAddress ); + variableLabel2->setText( QString::null ); + variableText2->setText( QString::null ); + variableLabel3->setText( QString::null ); + variableText3->setText( QString::null ); + } + else + { + // shouldn't happen + variableLabel1->setText( QString::null ); + variableText1->setText( QString::null ); + variableLabel2->setText( QString::null ); + variableText2->setText( QString::null ); + variableLabel3->setText( QString::null ); + variableText3->setText( QString::null ); + } + + // traffic tab + textLabelPacketsSend->setText( QString::number( data.txPackets ) ); + textLabelPacketsReceived->setText( QString::number( data.rxPackets ) ); + textLabelBytesSend->setText( data.txString ); + textLabelBytesReceived->setText( data.rxString ); + unsigned long bytesPerSecond = data.outgoingBytes / mInterface->getGeneralData().pollInterval; + textLabelSpeedSend->setText( KIO::convertSize( bytesPerSecond ) + i18n( "/s" ) ); + bytesPerSecond = data.incomingBytes / mInterface->getGeneralData().pollInterval; + textLabelSpeedReceived->setText( KIO::convertSize( bytesPerSecond ) + i18n( "/s" ) ); + + if ( data.wirelessDevice ) + { + WirelessData& wdata = mInterface->getWirelessData(); + + // wireless tab + textLabelESSID->setText( wdata.essid ); + textLabelAccessPoint->setText( wdata.accessPoint ); + textLabelNickName->setText( wdata.nickName ); + textLabelMode->setText( wdata.mode ); + textLabelFreqChannel->setText( wdata.frequency + " [" + wdata.channel + "]" ); + textLabelBitRate->setText( wdata.bitRate ); + textLabelLinkQuality->setText( wdata.linkQuality + "%" ); + if ( wdata.encryption == true ) + { + textLabelEncryption->setText( i18n( "active" ) ); + } + else + { + textLabelEncryption->setText( i18n( "off" ) ); + } + } + } +} + +void InterfaceStatusDialog::enableNetworkGroups( int ) +{ + groupBoxIP->setEnabled( true ); + groupBoxCurrentConnection->setEnabled( true ); +} + +void InterfaceStatusDialog::disableNetworkGroups( int ) +{ + groupBoxIP->setEnabled( false ); + groupBoxCurrentConnection->setEnabled( false ); + + // clear IP group + textLabelIP->setText( QString::null ); + textLabelSubnet->setText( QString::null ); + variableText1->setText( QString::null ); + variableText2->setText( QString::null ); + variableText3->setText( QString::null ); + + // clear current connection group + textLabelPacketsSend->setText( QString::null ); + textLabelPacketsReceived->setText( QString::null ); + textLabelBytesSend->setText( QString::null ); + textLabelBytesReceived->setText( QString::null ); + textLabelSpeedSend->setText( QString::null ); + textLabelSpeedReceived->setText( QString::null ); + + // clear wireless tab + if ( mInterface->getData().wirelessDevice ) + { + textLabelESSID->setText( QString::null ); + textLabelAccessPoint->setText( QString::null ); + textLabelNickName->setText( QString::null ); + textLabelMode->setText( QString::null ); + textLabelFreqChannel->setText( QString::null ); + textLabelBitRate->setText( QString::null ); + textLabelLinkQuality->setText( QString::null ); + textLabelEncryption->setText( QString::null ); + } +} + +void InterfaceStatusDialog::statisticsChanged() +{ + InterfaceStatistics* statistics = mInterface->getStatistics(); + + if ( statistics == 0 ) + { + return; + } + + const StatisticEntry* entry = statistics->getCurrentDay(); + textLabelTodaySent->setText( KIO::convertSize( entry->txBytes ) ); + textLabelTodayReceived->setText( KIO::convertSize( entry->rxBytes ) ); + textLabelTodayTotal->setText( KIO::convertSize( entry->txBytes + entry->rxBytes ) ); + + entry = statistics->getCurrentMonth(); + textLabelMonthSent->setText( KIO::convertSize( entry->txBytes ) ); + textLabelMonthReceived->setText( KIO::convertSize( entry->rxBytes ) ); + textLabelMonthTotal->setText( KIO::convertSize( entry->txBytes + entry->rxBytes ) ); + + entry = statistics->getCurrentYear(); + textLabelYearSent->setText( KIO::convertSize( entry->txBytes ) ); + textLabelYearReceived->setText( KIO::convertSize( entry->rxBytes ) ); + textLabelYearTotal->setText( KIO::convertSize( entry->txBytes + entry->rxBytes ) ); +} + +#include "interfacestatusdialog.moc" diff --git a/src/knemod/interfacestatusdialog.h b/src/knemod/interfacestatusdialog.h new file mode 100644 index 0000000..3b15362 --- /dev/null +++ b/src/knemod/interfacestatusdialog.h @@ -0,0 +1,89 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACESTATUSDIALOG_H +#define INTERFACESTATUSDIALOG_H + +#include <qwidget.h> + +#include "interfacestatusdlg.h" + +class QTimer; +class Interface; + +/** + * This class serves as the main window for KNemo. It handles the + * menus, toolbars, and status bars. + * + * @short Main window class + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceStatusDialog : public InterfaceStatusDlg +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceStatusDialog( Interface* interface, + QWidget* parent = 0L, const char* name = 0L ); + + /** + * Default Destructor + */ + virtual ~InterfaceStatusDialog(); + + /** + * Implemented to store position. + */ + void hide(); + void show(); + + /** + * Enable or disable the statistics group when the user turned statistics on or off. + */ + void setStatisticsGroupEnabled( bool enabled ); + +public slots: + /** + * Enable the network groups when the interface is connected + */ + void enableNetworkGroups( int ); + /** + * Disable the network groups when the interface is not connected + */ + void disableNetworkGroups( int ); + /** + * Update the statistics tab when data changed + */ + void statisticsChanged(); + +private slots: + void updateDialog(); + +private: + QPoint mPos; + bool mPosInitialized; + + QTimer* mTimer; + Interface* mInterface; +}; + +#endif // INTERFACESTATUSDIALOG_H diff --git a/src/knemod/interfacestatusdlg.ui b/src/knemod/interfacestatusdlg.ui new file mode 100644 index 0000000..f707ef3 --- /dev/null +++ b/src/knemod/interfacestatusdlg.ui @@ -0,0 +1,759 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>InterfaceStatusDlg</class> +<widget class="QDialog"> + <property name="name"> + <cstring>InterfaceStatusDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>292</width> + <height>328</height> + </rect> + </property> + <property name="caption"> + <string>Interface Status</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidget</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>connection</cstring> + </property> + <attribute name="title"> + <string>Connection</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="5" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>groupBoxIP</cstring> + </property> + <property name="title"> + <string>IP</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabelIP</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabelSubnet</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>variableText1</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>variableText2</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="4" column="1"> + <property name="name"> + <cstring>variableText3</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="text"> + <string>IP-Address:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel5_2</cstring> + </property> + <property name="text"> + <string>Subnet Mask:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>variableLabel1</cstring> + </property> + <property name="text"> + <string>Broadcast Address:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>variableLabel2</cstring> + </property> + <property name="text"> + <string>Default Gateway:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>variableLabel3</cstring> + </property> + <property name="text"> + <string>HW-Address:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabelAlias</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabelInterface</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabelStatus</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabelUptime</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel24</cstring> + </property> + <property name="text"> + <string>Interface:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel14</cstring> + </property> + <property name="text"> + <string>Alias:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Status:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Uptime:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>traffic</cstring> + </property> + <attribute name="title"> + <string>Traffic</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxCurrentConnection</cstring> + </property> + <property name="title"> + <string>Current connection</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel8</cstring> + </property> + <property name="text"> + <string>Received</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel7</cstring> + </property> + <property name="text"> + <string>Sent</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabelPacketsSend</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabelPacketsReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel9</cstring> + </property> + <property name="text"> + <string>Packets:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel10</cstring> + </property> + <property name="text"> + <string>Bytes:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel10_2</cstring> + </property> + <property name="text"> + <string>Speed:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabelBytesSend</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>textLabelBytesReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabelSpeedSend</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="2"> + <property name="name"> + <cstring>textLabelSpeedReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxStatistics</cstring> + </property> + <property name="title"> + <string>Statistics</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel9_2_2</cstring> + </property> + <property name="text"> + <string>Today:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel10_2_2_2</cstring> + </property> + <property name="text"> + <string>This year:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel8_2_3</cstring> + </property> + <property name="text"> + <string>Received</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="3"> + <property name="name"> + <cstring>textLabel8_2_2_2</cstring> + </property> + <property name="text"> + <string>Total</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel10_3_2</cstring> + </property> + <property name="text"> + <string>This month:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabelTodayReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>textLabelMonthReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="2"> + <property name="name"> + <cstring>textLabelYearReceived</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="3"> + <property name="name"> + <cstring>textLabelTodayTotal</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="3"> + <property name="name"> + <cstring>textLabelMonthTotal</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="3"> + <property name="name"> + <cstring>textLabelYearTotal</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel7_2_2</cstring> + </property> + <property name="text"> + <string>Sent</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabelMonthSent</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabelYearSent</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabelTodaySent</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4_3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>wireless</cstring> + </property> + <attribute name="title"> + <string>Wireless</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string>Connected to:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabelESSID</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3_2_2_2</cstring> + </property> + <property name="text"> + <string>Access point:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabelAccessPoint</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel3_2_4</cstring> + </property> + <property name="text"> + <string>Bit Rate:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabelFC</cstring> + </property> + <property name="text"> + <string>Frequency [Channel]:</string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel3_2_2</cstring> + </property> + <property name="text"> + <string>Mode:</string> + </property> + </widget> + <widget class="QLabel" row="5" column="1"> + <property name="name"> + <cstring>textLabelBitRate</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="4" column="1"> + <property name="name"> + <cstring>textLabelFreqChannel</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="3" column="1"> + <property name="name"> + <cstring>textLabelMode</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="1"> + <property name="name"> + <cstring>textLabelNickName</cstring> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3_2_5</cstring> + </property> + <property name="text"> + <string>Nickname:</string> + </property> + </widget> + <spacer row="8" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>spacer4_4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>50</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>textLabel3_2_6</cstring> + </property> + <property name="text"> + <string>Link Quality:</string> + </property> + </widget> + <widget class="QLabel" row="7" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Encryption:</string> + </property> + </widget> + <widget class="QLabel" row="6" column="1"> + <property name="name"> + <cstring>textLabelLinkQuality</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="7" column="1"> + <property name="name"> + <cstring>textLabelEncryption</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </grid> + </widget> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>0</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonClose</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>0</width> + <height>21</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>buttonClose</sender> + <signal>clicked()</signal> + <receiver>InterfaceStatusDlg</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/knemod/interfacetooltip.cpp b/src/knemod/interfacetooltip.cpp new file mode 100644 index 0000000..77d6505 --- /dev/null +++ b/src/knemod/interfacetooltip.cpp @@ -0,0 +1,204 @@ +/* This file is part of KNemo + Copyright (C) 2004 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qrect.h> +#include <qstring.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kio/global.h> + +#include "data.h" +#include "interface.h" +#include "interfacetooltip.h" + +InterfaceToolTip::InterfaceToolTip( Interface* interface, + QWidget* parent ) + : QToolTip( parent ), + mInterface( interface ) +{ + setupToolTipArray(); +} + +InterfaceToolTip::~InterfaceToolTip() +{ +} + +void InterfaceToolTip::maybeTip( const QPoint& ) +{ + QRect rect( parentWidget()->rect() ); + if ( !rect.isValid() ) + return; + + QString tooltip; + setupText( tooltip ); + tip( rect, tooltip ); +} + +void InterfaceToolTip::setupText( QString& text ) +{ + int toolTipContent = mInterface->getGeneralData().toolTipContent; + InterfaceData& data = mInterface->getData(); + + text += "<table cellspacing=0 cellpadding=0 border=0>"; + if ( ( toolTipContent & ALIAS ) && + mInterface->getSettings().alias != QString::null ) + text += "<tr><th colspan=2 align=center>" + mInterface->getSettings().alias + "</th></tr>"; + if ( toolTipContent & INTERFACE ) + text += "<tr><td>" + mToolTips[0].first + "</td><td>" + mInterface->getName() + "</td></tr>"; + if ( data.available ) + { + if ( toolTipContent & STATUS ) + text += "<tr><td>" + mToolTips[2].first + "</td><td>" + i18n( "Connection established." ) + "</td></tr>"; + if ( toolTipContent & UPTIME ) + { + int upsecs = mInterface->getStartTime().secsTo( QDateTime::currentDateTime() ); + int updays = upsecs / 86400; // don't use QDateTime::daysTo() because + // we only want complete days + + QString uptime; + if ( updays == 1 ) + uptime = "1 day, "; + else if ( updays > 1 ) + uptime = QString( "%1 days, " ).arg( updays ); + + upsecs -= 86400 * updays; // we only want the seconds of today + int hrs = upsecs / 3600; + int mins = ( upsecs - hrs * 3600 ) / 60; + int secs = upsecs - hrs * 3600 - mins * 60; + QString time; + time.sprintf( "%02d:%02d:%02d", hrs, mins, secs ); + uptime += time; + text += "<tr><td>" + mToolTips[3].first + "</td><td>" + uptime + "</td></tr>"; + } + } + else if ( data.existing ) + { + if ( toolTipContent & STATUS ) + text += "<tr><td>" + mToolTips[2].first + "</td><td>" + i18n( "Not connected." ) + "</td></tr>"; + } + else + { + if ( toolTipContent & STATUS ) + text += "<tr><td>" + mToolTips[2].first + "</td><td>" + i18n( "Not existing." ) + "</td></tr>"; + } + + if ( data.available ) + { + if ( toolTipContent & IP_ADDRESS ) + text += "<tr><td>" + mToolTips[4].first + "</td><td>" + data.ipAddress + "</td></tr>"; + if ( toolTipContent & SUBNET_MASK ) + text += "<tr><td>" + mToolTips[5].first + "</td><td>" + data.subnetMask + "</td></tr>"; + if ( mInterface->getType() == Interface::ETHERNET ) + { + if ( toolTipContent & BCAST_ADDRESS ) + text += "<tr><td>" + mToolTips[18].first + "</td><td>" + data.broadcastAddress + "</td></tr>"; + if ( toolTipContent & GATEWAY ) + text += "<tr><td>" + mToolTips[19].first + "</td><td>" + data.defaultGateway + "</td></tr>"; + if ( toolTipContent & HW_ADDRESS ) + text += "<tr><td>" + mToolTips[6].first + "</td><td>" + data.hwAddress + "</td></tr>"; + } + if ( mInterface->getType() == Interface::PPP ) + { + if ( toolTipContent & PTP_ADDRESS ) + text += "<tr><td>" + mToolTips[7].first + "</td><td>" + data.ptpAddress + "</td></tr>"; + } + if ( toolTipContent & RX_PACKETS ) + text += "<tr><td>" + mToolTips[8].first + "</td><td>" + QString::number( data.rxPackets ) + "</td></tr>"; + if ( toolTipContent & TX_PACKETS ) + text += "<tr><td>" + mToolTips[9].first + "</td><td>" + QString::number( data.txPackets ) + "</td></tr>"; + if ( toolTipContent & RX_BYTES ) + text += "<tr><td>" + mToolTips[10].first + "</td><td>" + data.rxString + "</td></tr>"; + if ( toolTipContent & TX_BYTES ) + text += "<tr><td>" + mToolTips[11].first + "</td><td>" + data.txString + "</td></tr>"; + if ( toolTipContent & DOWNLOAD_SPEED ) + { + unsigned long bytesPerSecond = data.incomingBytes / mInterface->getGeneralData().pollInterval; + text += "<tr><td>" + mToolTips[20].first + "</td><td>" + KIO::convertSize( bytesPerSecond ) + i18n( "/s" ) + "</td></tr>"; + } + if ( toolTipContent & UPLOAD_SPEED ) + { + unsigned long bytesPerSecond = data.outgoingBytes / mInterface->getGeneralData().pollInterval; + text += "<tr><td>" + mToolTips[21].first + "</td><td>" + KIO::convertSize( bytesPerSecond ) + i18n( "/s" ) + "</td></tr>"; + } + } + + if ( data.available && data.wirelessDevice ) + { + WirelessData& wdata = mInterface->getWirelessData(); + if ( toolTipContent & ESSID ) + text += "<tr><td>" + mToolTips[12].first + "</td><td>" + wdata.essid + "</td></tr>"; + if ( toolTipContent & MODE ) + text += "<tr><td>" + mToolTips[13].first + "</td><td>" + wdata.mode + "</td></tr>"; + if ( toolTipContent & FREQUENCY ) + text += "<tr><td>" + mToolTips[14].first + "</td><td>" + wdata.frequency + "</td></tr>"; + if ( toolTipContent & BIT_RATE ) + text += "<tr><td>" + mToolTips[15].first + "</td><td>" + wdata.bitRate + "</td></tr>"; + if ( toolTipContent & ACCESS_POINT ) + text += "<tr><td>" + mToolTips[16].first + "</td><td>" + wdata.accessPoint + "</td></tr>"; + if ( toolTipContent & LINK_QUALITY ) + text += "<tr><td>" + mToolTips[17].first + "</td><td>" + wdata.linkQuality + "</td></tr>"; + if ( toolTipContent & NICK_NAME ) + text += "<tr><td>" + mToolTips[22].first + "</td><td>" + wdata.nickName + "</td></tr>"; + if ( toolTipContent & ENCRYPTION ) + { + if ( wdata.encryption == true ) + { + text += "<tr><td>" + mToolTips[23].first + "</td><td>" + i18n( "active" ) + "</td></tr>"; + } + else + { + text += "<tr><td>" + mToolTips[23].first + "</td><td>" + i18n( "off" ) + "</td></tr>"; + } + } + } + text += "</table>"; +} + +void InterfaceToolTip::setupToolTipArray() +{ + // Cannot make this data static as the i18n macro doesn't seem + // to work when called to early i.e. before setting the catalogue. + mToolTips[0] = QPair<QString, int>( i18n( "Interface" ), INTERFACE ); + mToolTips[1] = QPair<QString, int>( i18n( "Alias" ), ALIAS ); + mToolTips[2] = QPair<QString, int>( i18n( "Status" ), STATUS ); + mToolTips[3] = QPair<QString, int>( i18n( "Uptime" ), UPTIME ); + mToolTips[4] = QPair<QString, int>( i18n( "IP-Address" ), IP_ADDRESS ); + mToolTips[5] = QPair<QString, int>( i18n( "Subnet Mask" ), SUBNET_MASK ); + mToolTips[6] = QPair<QString, int>( i18n( "HW-Address" ), HW_ADDRESS ); + mToolTips[7] = QPair<QString, int>( i18n( "PtP-Address" ), PTP_ADDRESS ); + mToolTips[8] = QPair<QString, int>( i18n( "Packets Received" ), RX_PACKETS ); + mToolTips[9] = QPair<QString, int>( i18n( "Packets Sent" ), TX_PACKETS ); + mToolTips[10] = QPair<QString, int>( i18n( "Bytes Received" ), RX_BYTES ); + mToolTips[11] = QPair<QString, int>( i18n( "Bytes Sent" ), TX_BYTES ); + mToolTips[12] = QPair<QString, int>( i18n( "ESSID" ), ESSID ); + mToolTips[13] = QPair<QString, int>( i18n( "Mode" ), MODE ); + mToolTips[14] = QPair<QString, int>( i18n( "Frequency" ), FREQUENCY ); + mToolTips[15] = QPair<QString, int>( i18n( "Bit Rate" ), BIT_RATE ); + mToolTips[16] = QPair<QString, int>( i18n( "Access Point" ), ACCESS_POINT ); + mToolTips[17] = QPair<QString, int>( i18n( "Link Quality" ), LINK_QUALITY ); + mToolTips[18] = QPair<QString, int>( i18n( "Broadcast Address" ), BCAST_ADDRESS ); + mToolTips[19] = QPair<QString, int>( i18n( "Default Gateway" ), LINK_QUALITY ); + mToolTips[20] = QPair<QString, int>( i18n( "Download Speed" ), DOWNLOAD_SPEED ); + mToolTips[21] = QPair<QString, int>( i18n( "Upload Speed" ), UPLOAD_SPEED ); + mToolTips[22] = QPair<QString, int>( i18n( "Nickname" ), NICK_NAME ); + mToolTips[23] = QPair<QString, int>( i18n( "Encryption" ), ENCRYPTION ); + mToolTips[24] = QPair<QString, int>(); +} + diff --git a/src/knemod/interfacetooltip.h b/src/knemod/interfacetooltip.h new file mode 100644 index 0000000..7c4dbd9 --- /dev/null +++ b/src/knemod/interfacetooltip.h @@ -0,0 +1,72 @@ +/* This file is part of KNemo + Copyright (C) 2004 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACETOOLTIP_H +#define INTERFACETOOLTIP_H + +#include <qpair.h> +#include <qtooltip.h> + +class Interface; + +/** + * This call is responsible for displaying the tooltip of an + * interface icon. It is derived from QToolTip and overwrites + * the function maybeTip(const QPoint & p) to update the tooltip + * text just before it is going to be displayed. + * + * @short Display tooltip according to user settings + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceToolTip : public QToolTip +{ +public: + /** + * Default Constructor + */ + InterfaceToolTip( Interface* interface, QWidget* parent = 0L ); + + /** + * Default Destructor + */ + virtual ~InterfaceToolTip(); + + /** + * From the Qt documentation: + * It is called when there is a possibility that a tool tip should + * be shown and must decide whether there is a tool tip for the point p + * in the widget that this QToolTip object relates to. If so, maybeTip() + * must call tip() with the rectangle the tip applies to, the tip's text + * and optionally the QToolTipGroup details and the geometry in screen + * coordinates. + */ + void maybeTip( const QPoint& ); + +private: + void setupText( QString& text ); + void setupToolTipArray(); + + // the interface this tooltip belongs to + Interface* mInterface; + // the tooltip text for each information + QPair<QString, int> mToolTips[25]; +}; + +#endif // INTERFACETOOLTIP_H diff --git a/src/knemod/interfacetray.cpp b/src/knemod/interfacetray.cpp new file mode 100644 index 0000000..5e2e154 --- /dev/null +++ b/src/knemod/interfacetray.cpp @@ -0,0 +1,121 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2005 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qwidget.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kbugreport.h> +#include <kaboutdata.h> +#include <kpopupmenu.h> +#include <kiconloader.h> +#include <kapplication.h> +#include <kaboutapplication.h> +#include <kactioncollection.h> + +#include "interfacetray.h" + +static const char description[] = + I18N_NOOP( "KNemo - the KDE Network Monitor" ); + +static const char version[] = "0.4.8"; + +InterfaceTray::InterfaceTray( const QString& ifname, + QWidget* parent, const char* name ) + : KSystemTray( parent, name ) +{ + actionCollection()->clear(); // remove the quit entry + + KPopupMenu* popup = contextMenu(); + int id = popup->idAt( 0 ); + popup->changeTitle( id, SmallIcon( "knemo" ), + "KNemo - " + ifname ); + popup->insertItem( SmallIcon( "knemo" ), + i18n( "&About KNemo" ), this, + SLOT( showAboutDialog() ) ); + popup->insertItem( i18n( "&Report Bug..." ), this, + SLOT( showReportBugDialog() ) ); + popup->insertSeparator(); + popup->insertItem( SmallIcon( "configure" ), + i18n( "&Configure KNemo..." ), this, + SIGNAL( configSelected() ) ); + popup->insertItem( SmallIcon( "ksysguard" ), + i18n( "&Open Traffic Plotter" ), this, + SLOT( showGraph() ) ); +} + +InterfaceTray::~InterfaceTray() +{ +} + +void InterfaceTray::mousePressEvent( QMouseEvent* e ) +{ + if ( !rect().contains( e->pos() ) ) + return; + + switch( e->button() ) + { + case LeftButton: + emit leftClicked(); + break; + case MidButton: + emit graphSelected( true ); + break; + case RightButton: + KSystemTray::mousePressEvent( e ); + break; + default: + break; + } +} + +void InterfaceTray::showAboutDialog() +{ + KAboutData data ( "knemo", I18N_NOOP( "KNemo" ), version, + description, KAboutData::License_GPL, + "(c) 2004, 2005, 2006 Percy Leonhardt\n\nSignal plotter taken from KSysGuard\n(c) 1999 - 2002, Chris Schlaeger", + 0, + "http://extragear.kde.org/apps/knemo/" + ); + data.addAuthor( "Percy Leonhardt", I18N_NOOP( "Author" ), + "percy@eris23.de" ); + data.addCredit( "Michael Olbrich", I18N_NOOP( "Threshold support" ), + "michael.olbrich@gmx.net" ); + data.addCredit( "Chris Schlaeger", I18N_NOOP( "Signal plotter" ), + "cs@kde.org" ); + + KAboutApplication about( &data ); + about.setProgramLogo( DesktopIcon( "knemo" ) ); + about.exec(); +} + +void InterfaceTray::showReportBugDialog() +{ + KAboutData data ( "knemo", I18N_NOOP( "KNemo" ), version ); + KBugReport bugReport( 0, true, &data ); + bugReport.exec(); +} + +void InterfaceTray::showGraph() +{ + emit graphSelected( false ); +} + +#include "interfacetray.moc" diff --git a/src/knemod/interfacetray.h b/src/knemod/interfacetray.h new file mode 100644 index 0000000..b783c45 --- /dev/null +++ b/src/knemod/interfacetray.h @@ -0,0 +1,81 @@ +/* This file is part of KNemo + Copyright (C) 2004 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACETRAY_H +#define INTERFACETRAY_H + +#include <ksystemtray.h> + +class QWidget; + +/** + * This class is the graphical representation of and interface + * in the system tray. It has a customized context menu and will + * emit a signal when the user left clicks the icon. + * + * @short Graphical representation of the tray icon + * @author Percy Leonhardt <percy@eris23.de> + */ + +class InterfaceTray : public KSystemTray +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + InterfaceTray( const QString& ifname, + QWidget* parent = 0L, const char* name = 0L ); + + /** + * Default Destructor + */ + virtual ~InterfaceTray(); + +signals: + void leftClicked(); + void graphSelected( bool ); + void configSelected(); + void startCommandSelected(); + void stopCommandSelected(); + +protected: + void mousePressEvent( QMouseEvent* e ); + +protected slots: + /** + * Will display the about dialog if the user selected + * the corresponding entry in the context menu. + */ + void showAboutDialog(); + + /** + * Will display the report bug dialog that allows the user + * to send a bug report by mail. + */ + void showReportBugDialog(); + + /** + * Opens the traffic plotter or brings it to the front if it + * is hidden. + */ + void showGraph(); +}; + +#endif // INTERFACETRAY_H diff --git a/src/knemod/knemod.desktop b/src/knemod/knemod.desktop new file mode 100644 index 0000000..d4f41e6 --- /dev/null +++ b/src/knemod/knemod.desktop @@ -0,0 +1,41 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Service +ServiceTypes=KDEDModule +X-KDE-ModuleType=Library +X-KDE-Library=knemod +X-KDE-FactoryName=knemod +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=false +Name=KNemo +Name[de]=Netzwerküberwachung KNemo +Name[sv]=Knemo +Name[xx]=xxKNemoxx +Comment=KDE Network Monitor +Comment[bg]=Монитор на мрежата +Comment[br]=Eveshaer ar rouedad evit KDE +Comment[cs]=KDE monitor sítě +Comment[da]=KDE's netværksovervågning +Comment[de]=KDE-Netzwerkmonitor +Comment[el]=Επίβλεψη δικτύου του KDE +Comment[es]=Monitor de red de KDE +Comment[et]=KDE võrgumonitor +Comment[ga]=Monatóir Líonra KDE +Comment[gl]=Un Monitor de Rede para KDE +Comment[it]=Monitor di rete di KDE +Comment[ja]=KDE ネットワークモニタ +Comment[ka]=KDE-ის ქსელის მონიტორი +Comment[lt]=Tinklo įrenginių stebėjimo KDE programa +Comment[nl]=KDE networkmonitor +Comment[pa]=KDE ਨੈਟਵਰਕ ਨਿਗਰਾਨ +Comment[pl]=Monitor sieci dla KDE +Comment[pt]=Monitor da Rede do KDE +Comment[pt_BR]=Monitor de Rede do KDE +Comment[ru]=Сетевой монитор KDE +Comment[sr]=Надгледање мреже за KDE +Comment[sr@Latn]=Nadgledanje mreže za KDE +Comment[sv]=KDE-nätverksövervakning +Comment[tr]=KDE Ağ İzleyici +Comment[uk]=Монітор мережі для KDE +Comment[xx]=xxKDE Network Monitorxx +Comment[zh_CN]=KDE 网络监视器 diff --git a/src/knemod/knemodaemon.cpp b/src/knemod/knemodaemon.cpp new file mode 100644 index 0000000..e5a7f88 --- /dev/null +++ b/src/knemod/knemodaemon.cpp @@ -0,0 +1,344 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qtimer.h> +#include <qstrlist.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <kprocess.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + +#include "knemodaemon.h" +#include "interface.h" +#include "backendbase.h" +#include "daemonregistry.h" + +QString KNemoDaemon::sSelectedInterface = QString::null; + +extern "C" { + KDE_EXPORT KDEDModule *create_knemod(const QCString &name) { + return new KNemoDaemon(name); + } +} + +KNemoDaemon::KNemoDaemon( const QCString& name ) + : KDEDModule( name ), + mColorVLines( 0x04FB1D ), + mColorHLines( 0x04FB1D ), + mColorIncoming( 0x1889FF ), + mColorOutgoing( 0xFF7F08 ), + mColorBackground( 0x313031 ), + mInstance( new KInstance( "knemo" ) ), + mNotifyInstance( new KNotifyClient::Instance( mInstance ) ) +{ + KGlobal::locale()->insertCatalogue( "knemod" ); + readConfig(); + + // select the backend from the config file + KConfig* config = new KConfig( "knemorc", true ); + config->setGroup( "General" ); + mBackendName = config->readEntry( "Backend", "Nettools" ); + delete config; + + bool foundBackend = false; + int i; + for ( i = 0; DaemonRegistry[i].name != QString::null; i++ ) + { + if ( DaemonRegistry[i].name == mBackendName ) + { + foundBackend = true; + break; + } + } + + if ( !foundBackend ) + { + i = 0; // use the first backend (Nettools) + } + mBackend = ( *DaemonRegistry[i].function )( mInterfaceDict ); + + mInterfaceDict.setAutoDelete( true ); + + mPollTimer = new QTimer(); + connect( mPollTimer, SIGNAL( timeout() ), this, SLOT( updateInterfaces() ) ); + mPollTimer->start( mGeneralData.pollInterval * 1000 ); +} + +KNemoDaemon::~KNemoDaemon() +{ + mPollTimer->stop(); + delete mPollTimer; + delete mBackend; + delete mNotifyInstance; + delete mInstance; + + QDictIterator<Interface> it( mInterfaceDict ); + for ( ; it.current(); ) + { + mInterfaceDict.remove( it.currentKey() ); + // 'remove' already advanced the iterator to the next item + } +} + +void KNemoDaemon::readConfig() +{ + KConfig* config = new KConfig( "knemorc", true ); + + config->setGroup( "General" ); + mGeneralData.pollInterval = config->readNumEntry( "PollInterval", 1 ); + mGeneralData.saveInterval = config->readNumEntry( "SaveInterval", 60 ); + mGeneralData.statisticsDir = config->readEntry( "StatisticsDir", KGlobal::dirs()->saveLocation( "data", "knemo/" ) ); + mGeneralData.toolTipContent = config->readNumEntry( "ToolTipContent", 2 ); + QStrList list; + int numEntries = config->readListEntry( "Interfaces", list ); + + if ( numEntries == 0 ) + return; + + char* interface; + for ( interface = list.first(); interface; interface = list.next() ) + { + Interface* iface = new Interface( interface, mGeneralData, mPlotterSettings ); + QString group( "Interface_" ); + group += interface; + if ( config->hasGroup( group ) ) + { + config->setGroup( group ); + InterfaceSettings& settings = iface->getSettings(); + settings.alias = config->readEntry( "Alias" ); + settings.iconSet = config->readNumEntry( "IconSet", 0 ); + settings.customCommands = config->readBoolEntry( "CustomCommands" ); + settings.hideWhenNotAvailable = config->readBoolEntry( "HideWhenNotAvailable" ); + settings.hideWhenNotExisting = config->readBoolEntry( "HideWhenNotExisting" ); + settings.activateStatistics = config->readBoolEntry( "ActivateStatistics" ); + settings.trafficThreshold = config->readNumEntry( "TrafficThreshold", 0 ); + if ( settings.customCommands ) + { + int numCommands = config->readNumEntry( "NumCommands" ); + for ( int i = 0; i < numCommands; i++ ) + { + QString entry; + InterfaceCommand cmd; + entry = QString( "RunAsRoot%1" ).arg( i + 1 ); + cmd.runAsRoot = config->readBoolEntry( entry ); + entry = QString( "Command%1" ).arg( i + 1 ); + cmd.command = config->readEntry( entry ); + entry = QString( "MenuText%1" ).arg( i + 1 ); + cmd.menuText = config->readEntry( entry ); + settings.commands.append( cmd ); + } + } + iface->configChanged(); // important to activate the statistics + } + mInterfaceDict.insert( interface, iface ); + } + + // load the settings for the plotter + config->setGroup( "PlotterSettings" ); + mPlotterSettings.pixel = config->readNumEntry( "Pixel", 1 ); + mPlotterSettings.count = config->readNumEntry( "Count", 5 ); + mPlotterSettings.distance = config->readNumEntry( "Distance", 30 ); + mPlotterSettings.fontSize = config->readNumEntry( "FontSize", 8 ); + mPlotterSettings.minimumValue = config->readNumEntry( "MinimumValue", 0 ); + mPlotterSettings.maximumValue = config->readNumEntry( "MaximumValue", 1 ); + mPlotterSettings.labels = config->readBoolEntry( "Labels", true ); + mPlotterSettings.topBar = config->readBoolEntry( "TopBar", false ); + mPlotterSettings.showIncoming = config->readBoolEntry( "ShowIncoming", true ); + mPlotterSettings.showOutgoing = config->readBoolEntry( "ShowOutgoing", true ); + mPlotterSettings.verticalLines = config->readBoolEntry( "VerticalLines", true ); + mPlotterSettings.horizontalLines = config->readBoolEntry( "HorizontalLines", true ); + mPlotterSettings.automaticDetection = config->readBoolEntry( "AutomaticDetection", true ); + mPlotterSettings.verticalLinesScroll = config->readBoolEntry( "VerticalLinesScroll", true ); + mPlotterSettings.colorVLines = config->readColorEntry( "ColorVLines", &mColorVLines ); + mPlotterSettings.colorHLines = config->readColorEntry( "ColorHLines", &mColorHLines ); + mPlotterSettings.colorIncoming = config->readColorEntry( "ColorIncoming", &mColorIncoming ); + mPlotterSettings.colorOutgoing = config->readColorEntry( "ColorOutgoing", &mColorOutgoing ); + mPlotterSettings.colorBackground = config->readColorEntry( "ColorBackground", &mColorBackground ); + + delete config; +} + +void KNemoDaemon::reparseConfiguration() +{ + // Read the settings from the config file. + QDict<InterfaceSettings> settingsDict; + KConfig* config = new KConfig( "knemorc", false ); + + config->setGroup( "General" ); + mGeneralData.pollInterval = config->readNumEntry( "PollInterval", 1 ); + mGeneralData.saveInterval = config->readNumEntry( "SaveInterval", 60 ); + mGeneralData.statisticsDir = config->readEntry( "StatisticsDir", KGlobal::dirs()->saveLocation( "data", "knemo/" ) ); + mGeneralData.toolTipContent = config->readNumEntry( "ToolTipContent", 2 ); + + // restart the timer with the new interval + mPollTimer->changeInterval( mGeneralData.pollInterval * 1000 ); + + // select the backend from the config file + QString backend = config->readEntry( "Backend", "Nettools" ); + + if ( mBackendName != backend ) + { + bool foundBackend = false; + mBackendName = backend; + int i; + for ( i = 0; DaemonRegistry[i].name != QString::null; i++ ) + { + if ( DaemonRegistry[i].name == backend ) + { + foundBackend = true; + break; + } + } + + if ( foundBackend ) + { + delete mBackend; + mBackend = ( *DaemonRegistry[i].function )( mInterfaceDict ); + } + } + + QStrList list; + int numEntries = config->readListEntry( "Interfaces", list ); + + if ( numEntries == 0 ) + return; + + char* interface; + for ( interface = list.first(); interface; interface = list.next() ) + { + QString group( "Interface_" ); + group += interface; + InterfaceSettings* settings = new InterfaceSettings(); + if ( config->hasGroup( group ) ) + { + config->setGroup( group ); + settings->alias = config->readEntry( "Alias" ); + settings->iconSet = config->readNumEntry( "IconSet", 0 ); + settings->customCommands = config->readBoolEntry( "CustomCommands" ); + settings->hideWhenNotAvailable = config->readBoolEntry( "HideWhenNotAvailable" ); + settings->hideWhenNotExisting = config->readBoolEntry( "HideWhenNotExisting" ); + settings->activateStatistics = config->readBoolEntry( "ActivateStatistics" ); + settings->trafficThreshold = config->readNumEntry( "TrafficThreshold", 0 ); + if ( settings->customCommands ) + { + int numCommands = config->readNumEntry( "NumCommands" ); + for ( int i = 0; i < numCommands; i++ ) + { + QString entry; + InterfaceCommand cmd; + entry = QString( "RunAsRoot%1" ).arg( i + 1 ); + cmd.runAsRoot = config->readBoolEntry( entry ); + entry = QString( "Command%1" ).arg( i + 1 ); + cmd.command = config->readEntry( entry ); + entry = QString( "MenuText%1" ).arg( i + 1 ); + cmd.menuText = config->readEntry( entry ); + settings->commands.append( cmd ); + } + } + } + settingsDict.insert( interface, settings ); + } + + // load the settings for the plotter + config->setGroup( "PlotterSettings" ); + mPlotterSettings.pixel = config->readNumEntry( "Pixel", 1 ); + mPlotterSettings.count = config->readNumEntry( "Count", 5 ); + mPlotterSettings.distance = config->readNumEntry( "Distance", 30 ); + mPlotterSettings.fontSize = config->readNumEntry( "FontSize", 8 ); + mPlotterSettings.minimumValue = config->readNumEntry( "MinimumValue", 0 ); + mPlotterSettings.maximumValue = config->readNumEntry( "MaximumValue", 1 ); + mPlotterSettings.labels = config->readBoolEntry( "Labels", true ); + mPlotterSettings.topBar = config->readBoolEntry( "TopBar", false ); + mPlotterSettings.showIncoming = config->readBoolEntry( "ShowIncoming", true ); + mPlotterSettings.showOutgoing = config->readBoolEntry( "ShowOutgoing", true ); + mPlotterSettings.verticalLines = config->readBoolEntry( "VerticalLines", true ); + mPlotterSettings.horizontalLines = config->readBoolEntry( "HorizontalLines", true ); + mPlotterSettings.automaticDetection = config->readBoolEntry( "AutomaticDetection", true ); + mPlotterSettings.verticalLinesScroll = config->readBoolEntry( "VerticalLinesScroll", true ); + mPlotterSettings.colorVLines = config->readColorEntry( "ColorVLines", &mColorVLines ); + mPlotterSettings.colorHLines = config->readColorEntry( "ColorHLines", &mColorHLines ); + mPlotterSettings.colorIncoming = config->readColorEntry( "ColorIncoming", &mColorIncoming ); + mPlotterSettings.colorOutgoing = config->readColorEntry( "ColorOutgoing", &mColorOutgoing ); + mPlotterSettings.colorBackground = config->readColorEntry( "ColorBackground", &mColorBackground ); + + // Remove all interfaces that the user deleted from + // the internal list. + QDictIterator<Interface> it( mInterfaceDict ); + for ( ; it.current(); ) + { + if ( settingsDict.find( it.currentKey() ) == 0 ) + { + config->deleteGroup( "Interface_" + it.currentKey() ); + mInterfaceDict.remove( it.currentKey() ); + // 'remove' already advanced the iterator to the next item + } + else + ++it; + } + config->sync(); + delete config; + + // Update all other interfaces and add new ones. + QDictIterator<InterfaceSettings> setIt( settingsDict ); + for ( ; setIt.current(); ++setIt ) + { + Interface* iface; + if ( mInterfaceDict.find( setIt.currentKey() ) == 0 ) + { + iface = new Interface( setIt.currentKey(), mGeneralData, mPlotterSettings ); + mInterfaceDict.insert( setIt.currentKey(), iface ); + } + else + iface = mInterfaceDict[setIt.currentKey()]; + + InterfaceSettings& settings = iface->getSettings(); + settings.alias = setIt.current()->alias; + settings.iconSet = setIt.current()->iconSet; + settings.customCommands = setIt.current()->customCommands; + settings.hideWhenNotAvailable = setIt.current()->hideWhenNotAvailable; + settings.hideWhenNotExisting = setIt.current()->hideWhenNotExisting; + settings.activateStatistics = setIt.current()->activateStatistics; + settings.trafficThreshold = setIt.current()->trafficThreshold; + settings.commands = setIt.current()->commands; + iface->configChanged(); + } +} + +QString KNemoDaemon::getSelectedInterface() +{ + // Reset the variable to avoid preselecting an interface when + // the user opens the control center module from the control + // center afterwards. + QString tmp = sSelectedInterface; + sSelectedInterface = QString::null; + + return tmp; +} + +void KNemoDaemon::updateInterfaces() +{ + mBackend->update(); +} + +#include "knemodaemon.moc" diff --git a/src/knemod/knemodaemon.h b/src/knemod/knemodaemon.h new file mode 100644 index 0000000..d62c288 --- /dev/null +++ b/src/knemod/knemodaemon.h @@ -0,0 +1,120 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de> + + KNemo is free software; you can redistribute it and/or modify + it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + KNemo 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KNEMODAEMON_H +#define KNEMODAEMON_H + +#include <qdict.h> +#include <qcolor.h> +#include <qcstring.h> +#include <qdatetime.h> + +#include <kdedmodule.h> +#include <knotifyclient.h> + +#include "data.h" +#include "global.h" + +class QTimer; +class KInstance; +class Interface; +class BackendBase; +class KNotifyClient::Instance; + +/** + * This class is the main entry point of KNemo. It reads the configuration, + * creates the logical interfaces and starts an interface updater. It also + * takes care of configuration changes by the user. + * + * @short KNemos main entry point + * @author Percy Leonhardt <percy@eris23.de> + */ +class KNemoDaemon : public KDEDModule +{ + K_DCOP + Q_OBJECT +public: + /** + * Default Constructor + */ + KNemoDaemon( const QCString& name ); + + /** + * Default Destructor + */ + virtual ~KNemoDaemon(); + + // tell the control center module which interface the user selected + static QString sSelectedInterface; + +k_dcop: + /* + * Called from the control center module when the user changed + * the settings. It updates the internal list of interfaces + * that should be monitored. + */ + virtual void reparseConfiguration(); + + /* When the user selects 'Configure KNemo...' from the context + * menus this functions gets called from the control center + * module. This way the module knows for which interface the + * user opened the dialog and can preselect the appropriate + * interface in the list. + */ + virtual QString getSelectedInterface(); + +private: + /* + * Read the configuration on startup + */ + void readConfig(); + +private slots: + /** + * trigger the backend to update the interface informations + */ + void updateInterfaces(); + +private: + QColor mColorVLines; + QColor mColorHLines; + QColor mColorIncoming; + QColor mColorOutgoing; + QColor mColorBackground; + + // every time this timer expires we will + // gather new informations from the backend + QTimer* mPollTimer; + // our own instance + KInstance* mInstance; + // needed so that KNotifyClient::event will work + KNotifyClient::Instance* mNotifyInstance; + // application wide settings are stored here + GeneralData mGeneralData; + // settings for the traffic plotter are stored here + PlotterSettings mPlotterSettings; + // the name of backend we currently use + QString mBackendName; + // the backend used to update the interface informations + BackendBase* mBackend; + // a list of all interfaces the user wants to monitor + QDict<Interface> mInterfaceDict; +}; + +#endif // KNEMODAEMON_H diff --git a/src/knemod/pics/Makefile.am b/src/knemod/pics/Makefile.am new file mode 100644 index 0000000..d085bb3 --- /dev/null +++ b/src/knemod/pics/Makefile.am @@ -0,0 +1,2 @@ +# Install the icons into the global KDE directories +KDE_ICON = AUTO diff --git a/src/knemod/pics/cr16-app-knemo.png b/src/knemod/pics/cr16-app-knemo.png Binary files differnew file mode 100644 index 0000000..1989704 --- /dev/null +++ b/src/knemod/pics/cr16-app-knemo.png diff --git a/src/knemod/pics/cr22-action-network_connected.png b/src/knemod/pics/cr22-action-network_connected.png Binary files differnew file mode 100644 index 0000000..86a0872 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_connected.png diff --git a/src/knemod/pics/cr22-action-network_connected_lan.png b/src/knemod/pics/cr22-action-network_connected_lan.png Binary files differnew file mode 100644 index 0000000..a72c89f --- /dev/null +++ b/src/knemod/pics/cr22-action-network_connected_lan.png diff --git a/src/knemod/pics/cr22-action-network_connected_ppp.png b/src/knemod/pics/cr22-action-network_connected_ppp.png Binary files differnew file mode 100644 index 0000000..6abcd43 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_connected_ppp.png diff --git a/src/knemod/pics/cr22-action-network_connected_wlan.png b/src/knemod/pics/cr22-action-network_connected_wlan.png Binary files differnew file mode 100644 index 0000000..b7395aa --- /dev/null +++ b/src/knemod/pics/cr22-action-network_connected_wlan.png diff --git a/src/knemod/pics/cr22-action-network_disconnected.png b/src/knemod/pics/cr22-action-network_disconnected.png Binary files differnew file mode 100644 index 0000000..d6ff91a --- /dev/null +++ b/src/knemod/pics/cr22-action-network_disconnected.png diff --git a/src/knemod/pics/cr22-action-network_disconnected_lan.png b/src/knemod/pics/cr22-action-network_disconnected_lan.png Binary files differnew file mode 100644 index 0000000..5aad370 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_disconnected_lan.png diff --git a/src/knemod/pics/cr22-action-network_disconnected_ppp.png b/src/knemod/pics/cr22-action-network_disconnected_ppp.png Binary files differnew file mode 100644 index 0000000..729f1f9 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_disconnected_ppp.png diff --git a/src/knemod/pics/cr22-action-network_disconnected_wlan.png b/src/knemod/pics/cr22-action-network_disconnected_wlan.png Binary files differnew file mode 100644 index 0000000..b1da123 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_disconnected_wlan.png diff --git a/src/knemod/pics/cr22-action-network_incoming.png b/src/knemod/pics/cr22-action-network_incoming.png Binary files differnew file mode 100644 index 0000000..ea4b71d --- /dev/null +++ b/src/knemod/pics/cr22-action-network_incoming.png diff --git a/src/knemod/pics/cr22-action-network_incoming_lan.png b/src/knemod/pics/cr22-action-network_incoming_lan.png Binary files differnew file mode 100644 index 0000000..222d38d --- /dev/null +++ b/src/knemod/pics/cr22-action-network_incoming_lan.png diff --git a/src/knemod/pics/cr22-action-network_incoming_ppp.png b/src/knemod/pics/cr22-action-network_incoming_ppp.png Binary files differnew file mode 100644 index 0000000..51d144d --- /dev/null +++ b/src/knemod/pics/cr22-action-network_incoming_ppp.png diff --git a/src/knemod/pics/cr22-action-network_incoming_wlan.png b/src/knemod/pics/cr22-action-network_incoming_wlan.png Binary files differnew file mode 100644 index 0000000..b471965 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_incoming_wlan.png diff --git a/src/knemod/pics/cr22-action-network_outgoing.png b/src/knemod/pics/cr22-action-network_outgoing.png Binary files differnew file mode 100644 index 0000000..e813f93 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_outgoing.png diff --git a/src/knemod/pics/cr22-action-network_outgoing_lan.png b/src/knemod/pics/cr22-action-network_outgoing_lan.png Binary files differnew file mode 100644 index 0000000..fa3b0c5 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_outgoing_lan.png diff --git a/src/knemod/pics/cr22-action-network_outgoing_ppp.png b/src/knemod/pics/cr22-action-network_outgoing_ppp.png Binary files differnew file mode 100644 index 0000000..751b788 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_outgoing_ppp.png diff --git a/src/knemod/pics/cr22-action-network_outgoing_wlan.png b/src/knemod/pics/cr22-action-network_outgoing_wlan.png Binary files differnew file mode 100644 index 0000000..7cd6ef5 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_outgoing_wlan.png diff --git a/src/knemod/pics/cr22-action-network_traffic.png b/src/knemod/pics/cr22-action-network_traffic.png Binary files differnew file mode 100644 index 0000000..0d2a4b2 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_traffic.png diff --git a/src/knemod/pics/cr22-action-network_traffic_lan.png b/src/knemod/pics/cr22-action-network_traffic_lan.png Binary files differnew file mode 100644 index 0000000..f41a05a --- /dev/null +++ b/src/knemod/pics/cr22-action-network_traffic_lan.png diff --git a/src/knemod/pics/cr22-action-network_traffic_ppp.png b/src/knemod/pics/cr22-action-network_traffic_ppp.png Binary files differnew file mode 100644 index 0000000..0dce305 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_traffic_ppp.png diff --git a/src/knemod/pics/cr22-action-network_traffic_wlan.png b/src/knemod/pics/cr22-action-network_traffic_wlan.png Binary files differnew file mode 100644 index 0000000..634b2d3 --- /dev/null +++ b/src/knemod/pics/cr22-action-network_traffic_wlan.png diff --git a/src/knemod/pics/cr32-app-knemo.png b/src/knemod/pics/cr32-app-knemo.png Binary files differnew file mode 100644 index 0000000..ac2d6dd --- /dev/null +++ b/src/knemod/pics/cr32-app-knemo.png diff --git a/src/knemod/signalplotter.cpp b/src/knemod/signalplotter.cpp new file mode 100644 index 0000000..4945a2d --- /dev/null +++ b/src/knemod/signalplotter.cpp @@ -0,0 +1,706 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation + + 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. + + KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. + Please do not commit any changes without consulting me first. Thanks! + + $Id: SignalPlotter.cc,v 1.7 2004/01/04 13:43:48 waba Exp $ +*/ + +#include <math.h> +#include <string.h> + +#include <qpainter.h> +#include <qpixmap.h> + +#include <kdebug.h> +#include <kconfig.h> + +#include "signalplotter.h" + +static inline int min( int a, int b ) +{ + return ( a < b ? a : b ); +} + +SignalPlotter::SignalPlotter( QWidget *parent, const char *name ) + : QDialog( parent, name ), + mPosInitialized( false ), + mName( name ) +{ + // Auto deletion does not work for pointer to arrays. + mBeamData.setAutoDelete( false ); + + setBackgroundMode( NoBackground ); + + mSamples = 0; + mMinValue = mMaxValue = 0.0; + mUseAutoRange = true; + + mGraphStyle = GRAPH_POLYGON; + + // Anything smaller than this does not make sense. + setMinimumSize( 16, 16 ); + setSizePolicy( QSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Expanding, false ) ); + + mShowVerticalLines = true; + mVerticalLinesColor = QColor( 0x04FB1D ); + mVerticalLinesDistance = 30; + mVerticalLinesScroll = true; + mVerticalLinesOffset = 0; + mHorizontalScale = 1; + + mShowHorizontalLines = true; + mHorizontalLinesColor = QColor( 0x04FB1D ); + mHorizontalLinesCount = 5; + + mShowLabels = true; + mShowTopBar = false; + mFontSize = 8; + + mBackgroundColor = QColor( 0x313031 ); + + // Restore window size and position. + KConfig* config = new KConfig( "knemorc", false ); + if ( config->hasGroup( "Interface_" + mName ) ) + { + config->setGroup( "Interface_" + mName ); + if ( config->hasKey( "PlotterX" ) && config->hasKey( "PlotterY" ) ) + { + mPos.setX( config->readNumEntry( "PlotterX" ) ); + mPos.setY( config->readNumEntry( "PlotterY" ) ); + mPosInitialized = true; + } + if ( config->hasKey( "PlotterWidth" ) && config->hasKey( "PlotterHeight" ) ) + resize( config->readNumEntry( "PlotterWidth" ), + config->readNumEntry( "PlotterHeight" ) ); + } + delete config; +} + +SignalPlotter::~SignalPlotter() +{ + for ( double* p = mBeamData.first(); p; p = mBeamData.next() ) + delete [] p; + + // Store window size and position. + KConfig* config = new KConfig( "knemorc", false ); + if ( config->hasGroup( "Interface_" + mName ) ) + { + config->setGroup( "Interface_" + mName ); + config->writeEntry( "PlotterX", x() ); + config->writeEntry( "PlotterY", y() ); + config->writeEntry( "PlotterWidth", width() ); + config->writeEntry( "PlotterHeight", height() ); + config->sync(); + } + delete config; +} + +void SignalPlotter::hide() +{ + mPos = pos(); + mPosInitialized = true; + QDialog::hide(); +} + +void SignalPlotter::show() +{ + QDialog::show(); + /** + * mPosInitialized should always be true, except when + * starting KNemo for the very first time. + */ + if ( mPosInitialized ) + move( mPos ); +} + +bool SignalPlotter::addBeam( const QColor &color ) +{ + double* d = new double[ mSamples ]; + memset( d, 0, sizeof(double) * mSamples ); + mBeamData.append( d ); + mBeamColor.append( color ); + + return true; +} + +void SignalPlotter::addSample( const QValueList<double>& sampleBuf ) +{ + if ( mBeamData.count() != sampleBuf.count() ) + return; + + double* d; + if ( mUseAutoRange ) { + double sum = 0; + for ( d = mBeamData.first(); d; d = mBeamData.next() ) { + sum += d[ 0 ]; + if ( sum < mMinValue ) + mMinValue = sum; + if ( sum > mMaxValue ) + mMaxValue = sum; + } + } + + /* If the vertical lines are scrolling, increment the offset + * so they move with the data. The vOffset / hScale confusion + * is because v refers to Vertical Lines, and h to the horizontal + * distance between the vertical lines. */ + if ( mVerticalLinesScroll ) { + mVerticalLinesOffset = ( mVerticalLinesOffset + mHorizontalScale) + % mVerticalLinesDistance; + } + + // Shift data buffers one sample down and insert new samples. + QValueList<double>::ConstIterator s; + for ( d = mBeamData.first(), s = sampleBuf.begin(); d; d = mBeamData.next(), ++s ) { + memmove( d, d + 1, ( mSamples - 1 ) * sizeof( double ) ); + d[ mSamples - 1 ] = *s; + } + + update(); +} + +void SignalPlotter::changeRange( int beam, double min, double max ) +{ + // Only the first beam affects range calculation. + if ( beam > 1 ) + return; + + mMinValue = min; + mMaxValue = max; +} + +QValueList<QColor> &SignalPlotter::beamColors() +{ + return mBeamColor; +} + +void SignalPlotter::removeBeam( uint pos ) +{ + mBeamColor.remove( mBeamColor.at( pos ) ); + mBeamData.remove( pos ); +} + +void SignalPlotter::setTitle( const QString &title ) +{ + mTitle = title; +} + +QString SignalPlotter::title() const +{ + return mTitle; +} + +void SignalPlotter::setUseAutoRange( bool value ) +{ + mUseAutoRange = value; +} + +bool SignalPlotter::useAutoRange() const +{ + return mUseAutoRange; +} + +void SignalPlotter::setMinValue( double min ) +{ + mMinValue = min; +} + +double SignalPlotter::minValue() const +{ + return ( mUseAutoRange ? 0 : mMinValue ); +} + +void SignalPlotter::setMaxValue( double max ) +{ + mMaxValue = max; +} + +double SignalPlotter::maxValue() const +{ + return ( mUseAutoRange ? 0 : mMaxValue ); +} + +void SignalPlotter::setGraphStyle( uint style ) +{ + mGraphStyle = style; +} + +uint SignalPlotter::graphStyle() const +{ + return mGraphStyle; +} + +void SignalPlotter::setHorizontalScale( uint scale ) +{ + if (scale == mHorizontalScale) + return; + + mHorizontalScale = scale; + if (isVisible()) + updateDataBuffers(); +} + +uint SignalPlotter::horizontalScale() const +{ + return mHorizontalScale; +} + +void SignalPlotter::setShowVerticalLines( bool value ) +{ + mShowVerticalLines = value; +} + +bool SignalPlotter::showVerticalLines() const +{ + return mShowVerticalLines; +} + +void SignalPlotter::setVerticalLinesColor( const QColor &color ) +{ + mVerticalLinesColor = color; +} + +QColor SignalPlotter::verticalLinesColor() const +{ + return mVerticalLinesColor; +} + +void SignalPlotter::setVerticalLinesDistance( int distance ) +{ + mVerticalLinesDistance = distance; +} + +int SignalPlotter::verticalLinesDistance() const +{ + return mVerticalLinesDistance; +} + +void SignalPlotter::setVerticalLinesScroll( bool value ) +{ + mVerticalLinesScroll = value; +} + +bool SignalPlotter::verticalLinesScroll() const +{ + return mVerticalLinesScroll; +} + +void SignalPlotter::setShowHorizontalLines( bool value ) +{ + mShowHorizontalLines = value; +} + +bool SignalPlotter::showHorizontalLines() const +{ + return mShowHorizontalLines; +} + +void SignalPlotter::setHorizontalLinesColor( const QColor &color ) +{ + mHorizontalLinesColor = color; +} + +QColor SignalPlotter::horizontalLinesColor() const +{ + return mHorizontalLinesColor; +} + +void SignalPlotter::setHorizontalLinesCount( int count ) +{ + mHorizontalLinesCount = count; +} + +int SignalPlotter::horizontalLinesCount() const +{ + return mHorizontalLinesCount; +} + +void SignalPlotter::setShowLabels( bool value ) +{ + mShowLabels = value; +} + +bool SignalPlotter::showLabels() const +{ + return mShowLabels; +} + +void SignalPlotter::setShowTopBar( bool value ) +{ + mShowTopBar = value; +} + +bool SignalPlotter::showTopBar() const +{ + return mShowTopBar; +} + +void SignalPlotter::setFontSize( int size ) +{ + mFontSize = size; +} + +int SignalPlotter::fontSize() const +{ + return mFontSize; +} + +void SignalPlotter::setBackgroundColor( const QColor &color ) +{ + mBackgroundColor = color; +} + +QColor SignalPlotter::backgroundColor() const +{ + return mBackgroundColor; +} + +void SignalPlotter::resizeEvent( QResizeEvent* ) +{ + Q_ASSERT( width() > 2 ); + + updateDataBuffers(); +} + +void SignalPlotter::updateDataBuffers() +{ + /* Since the data buffers for the beams are equal in size to the + * width of the widget minus 2 we have to enlarge or shrink the + * buffers accordingly when a resize occures. To have a nicer + * display we try to keep as much data as possible. Data that is + * lost due to shrinking the buffers cannot be recovered on + * enlarging though. */ + + /* Determine new number of samples first. + * +0.5 to ensure rounding up + * +2 for extra data points so there is + * 1) no wasted space and + * 2) no loss of precision when drawing the first data point. */ + uint newSampleNum = static_cast<uint>( ( ( width() - 2 ) / + mHorizontalScale ) + 2.5 ); + + // overlap between the old and the new buffers. + int overlap = min( mSamples, newSampleNum ); + + for ( uint i = 0; i < mBeamData.count(); ++i ) { + double* nd = new double[ newSampleNum ]; + + // initialize new part of the new buffer + if ( newSampleNum > (uint)overlap ) + memset( nd, 0, sizeof( double ) * ( newSampleNum - overlap ) ); + + // copy overlap from old buffer to new buffer + memcpy( nd + ( newSampleNum - overlap ), mBeamData.at( i ) + + ( mSamples - overlap ), overlap * sizeof( double ) ); + + mBeamData.remove( i ); + mBeamData.insert( i, nd ); + } + + mSamples = newSampleNum; +} + +void SignalPlotter::paintEvent( QPaintEvent* ) +{ + uint w = width(); + uint h = height(); + + /* Do not do repaints when the widget is not yet setup properly. */ + if ( w <= 2 ) + return; + + QPixmap pm( w, h ); + QPainter p; + p.begin( &pm, this ); + + pm.fill( mBackgroundColor ); + /* Draw white line along the bottom and the right side of the + * widget to create a 3D like look. */ + p.setPen( QColor( colorGroup().light() ) ); + p.drawLine( 0, h - 1, w - 1, h - 1 ); + p.drawLine( w - 1, 0, w - 1, h - 1 ); + + p.setClipRect( 1, 1, w - 2, h - 2 ); + double range = mMaxValue - mMinValue; + + /* If the range is too small we will force it to 1.0 since it + * looks a lot nicer. */ + if ( range < 0.000001 ) + range = 1.0; + + double minValue = mMinValue; + if ( mUseAutoRange ) { + if ( mMinValue != 0.0 ) { + double dim = pow( 10, floor( log10( fabs( mMinValue ) ) ) ) / 2; + if ( mMinValue < 0.0 ) + minValue = dim * floor( mMinValue / dim ); + else + minValue = dim * ceil( mMinValue / dim ); + range = mMaxValue - minValue; + if ( range < 0.000001 ) + range = 1.0; + } + // Massage the range so that the grid shows some nice values. + double step = range / mHorizontalLinesCount; + double dim = pow( 10, floor( log10( step ) ) ) / 2; + range = dim * ceil( step / dim ) * mHorizontalLinesCount; + } + double maxValue = minValue + range; + + int top = 0; + if ( mShowTopBar && h > ( mFontSize + 2 + mHorizontalLinesCount * 10 ) ) { + /* Draw horizontal bar with current sensor values at top of display. */ + p.setPen( mHorizontalLinesColor ); + int x0 = w / 2; + p.setFont( QFont( p.font().family(), mFontSize ) ); + top = p.fontMetrics().height(); + h -= top; + int h0 = top - 2; + + // JJ 2005-07-18: show numerical in/out values in the top bar ---> + double *d1 = mBeamData.first(); + double UploadSpeed = 0; + if(d1) + UploadSpeed = d1[ w - 3 ]; // read value from graph data + + double *d2 = mBeamData.next(); + double DownloadSpeed = 0; + if(d2) + DownloadSpeed = d2[ w - 3 ]; // read value from graph data + + // The left side of the top bar is now divided into three sections: + // - name of interface (original title) + // - download speed (numerically, from the value shown by the bar on the right) + // - upload speed (numerically, from the value shown by the bar on the right) + + // title + p.drawText(0, 0, x0/3, top - 2, Qt::AlignCenter, mTitle ); + + QValueList<QColor>::Iterator col_speeds; + col_speeds = mBeamColor.begin(); + QColor UploadColor = *(col_speeds++); + QColor DownloadColor = *(col_speeds); + + // download speed + QString DownloadSpeedText; + DownloadSpeedText.sprintf("in: %0.2f KB/s", DownloadSpeed); + p.setPen( DownloadColor ); + p.drawText(x0/3, 0, x0/3, top - 2, Qt::AlignCenter, DownloadSpeedText ); + + // upload speed + QString UploadSpeedText; + UploadSpeedText.sprintf("out: %0.2f KB/s", UploadSpeed); + p.setPen( UploadColor ); + p.drawText(2*x0/3, 0, x0/3, top - 2, Qt::AlignCenter, UploadSpeedText ); + + // restore correct pen color for the separator lines + p.setPen( mHorizontalLinesColor ); + // <--- JJ 2005-07-18 + + p.drawLine( x0 - 1, 1, x0 - 1, h0 ); + p.drawLine( 0, top - 1, w - 2, top - 1 ); + + double bias = -minValue; + double scaleFac = ( w - x0 - 2 ) / range; + QValueList<QColor>::Iterator col; + col = mBeamColor.begin(); + for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) { + int start = x0 + (int)( bias * scaleFac ); + int end = x0 + (int)( ( bias += d[ w - 3 ] ) * scaleFac ); + /* If the rect is wider than 2 pixels we draw only the last + * pixels with the bright color. The rest is painted with + * a 50% darker color. */ + if ( end - start > 1 ) { + p.setPen( (*col).dark( 150 ) ); + p.setBrush( (*col).dark( 150 ) ); + p.drawRect( start, 1, end - start, h0 ); + p.setPen( *col ); + p.drawLine( end, 1, end, h0 ); + } else if ( start - end > 1 ) { + p.setPen( (*col).dark( 150 ) ); + p.setBrush( (*col).dark( 150 ) ); + p.drawRect( end, 1, start - end, h0 ); + p.setPen( *col ); + p.drawLine( end, 1, end, h0 ); + } else { + p.setPen( *col ); + p.drawLine( start, 1, start, h0 ); + } + } + } + + /* Draw scope-like grid vertical lines */ + if ( mShowVerticalLines && w > 60 ) { + p.setPen( mVerticalLinesColor ); + for ( uint x = mVerticalLinesOffset; x < ( w - 2 ); x += mVerticalLinesDistance ) + p.drawLine( w - x, top, w - x, h + top - 2 ); + } + + /* In autoRange mode we determine the range and plot the values in + * one go. This is more efficiently than running through the + * buffers twice but we do react on recently discarded samples as + * well as new samples one plot too late. So the range is not + * correct if the recently discarded samples are larger or smaller + * than the current extreme values. But we can probably live with + * this. */ + if ( mUseAutoRange ) + mMinValue = mMaxValue = 0.0; + + /* Plot stacked values */ + double scaleFac = ( h - 2 ) / range; + if ( mGraphStyle == GRAPH_ORIGINAL ) { + int xPos = 0; + for ( int i = 0; i < mSamples; i++, xPos += mHorizontalScale ) { + double bias = -minValue; + QValueList<QColor>::Iterator col; + col = mBeamColor.begin(); + double sum = 0.0; + for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) { + if ( mUseAutoRange ) { + sum += d[ i ]; + if ( sum < mMinValue ) + mMinValue = sum; + if ( sum > mMaxValue ) + mMaxValue = sum; + } + int start = top + h - 2 - (int)( bias * scaleFac ); + int end = top + h - 2 - (int)( ( bias + d[ i ] ) * scaleFac ); + bias += d[ i ]; + /* If the line is longer than 2 pixels we draw only the last + * 2 pixels with the bright color. The rest is painted with + * a 50% darker color. */ + if ( end - start > 2 ) { + p.fillRect( xPos, start, mHorizontalScale, end - start - 1, (*col).dark( 150 ) ); + p.fillRect( xPos, end - 1, mHorizontalScale, 2, *col ); + } else if ( start - end > 2 ) { + p.fillRect( xPos, start, mHorizontalScale, end - start + 1, (*col).dark( 150 ) ); + p.fillRect( xPos, end + 1, mHorizontalScale, 2, *col ); + } else + p.fillRect( xPos, start, mHorizontalScale, end - start, *col ); + + } + } + } else if ( mGraphStyle == GRAPH_POLYGON ) { + int *prevVals = new int[ mBeamData.count() ]; + int hack[ 4 ] = { 0, 0, 0, 0 }; + int x1 = w - ( ( mSamples + 1 ) * mHorizontalScale ); + + for ( int i = 0; i < mSamples; i++ ) { + QValueList<QColor>::Iterator col; + col = mBeamColor.begin(); + double sum = 0.0; + int y = top + h - 2; + int oldY = top + h; + int oldPrevY = oldY; + int height = 0; + int j = 0; + int jMax = mBeamData.count() - 1; + x1 += mHorizontalScale; + int x2 = x1 + mHorizontalScale; + + for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col, j++ ) { + if ( mUseAutoRange ) { + sum += d[ i ]; + if ( sum < mMinValue ) + mMinValue = sum; + if ( sum > mMaxValue ) + mMaxValue = sum; + } + height = (int)( ( d[ i ] - minValue ) * scaleFac ); + y -= height; + + /* If the line is longer than 2 pixels we draw only the last + * 2 pixels with the bright color. The rest is painted with + * a 50% darker color. */ + QPen lastPen = QPen( p.pen() ); + p.setPen( (*col).dark( 150 ) ); + p.setBrush( (*col).dark( 150 ) ); + QPointArray pa( 4 ); + int prevY = ( i == 0 ) ? y : prevVals[ j ]; + pa.putPoints( 0, 1, x1, prevY ); + pa.putPoints( 1, 1, x2, y ); + pa.putPoints( 2, 1, x2, oldY ); + pa.putPoints( 3, 1, x1, oldPrevY ); + p.drawPolygon( pa ); + p.setPen( lastPen ); + if ( jMax == 0 ) { + // draw as normal, no deferred drawing req'd. + p.setPen( *col ); + p.drawLine( x1, prevY, x2, y ); + } else if ( j == jMax ) { + // draw previous values and current values + p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] ); + p.setPen( *col ); + p.drawLine( x1, prevY, x2, y ); + } else if ( j == 0 ) { + // save values only + hack[ 0 ] = x1; + hack[ 1 ] = prevY; + hack[ 2 ] = x2; + hack[ 3 ] = y; + p.setPen( *col ); + } else { + p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] ); + hack[ 0 ] = x1; + hack[ 1 ] = prevY; + hack[ 2 ] = x2; + hack[ 3 ] = y; + p.setPen( *col ); + } + + prevVals[ j ] = y; + oldY = y; + oldPrevY = prevY; + } + } + + delete[] prevVals; + } + + /* Draw horizontal lines and values. Lines are drawn when the + * height is greater than 10 times hCount + 1, values are shown + * when width is greater than 60 */ + if ( mShowHorizontalLines && h > ( 10 * ( mHorizontalLinesCount + 1 ) ) ) { + p.setPen( mHorizontalLinesColor ); + p.setFont( QFont( p.font().family(), mFontSize ) ); + QString val; + for ( uint y = 1; y < mHorizontalLinesCount; y++ ) { + p.drawLine( 0, top + y * ( h / mHorizontalLinesCount ), w - 2, + top + y * ( h / mHorizontalLinesCount ) ); + if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 ) + && w > 60 ) { + val = QString( "%1" ).arg( maxValue - y * ( range / mHorizontalLinesCount ) ); + p.drawText( 6, top + y * ( h / mHorizontalLinesCount ) - 1, val ); + } + } + + if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 ) + && w > 60 ) { + val = QString( "%1" ).arg( minValue ); + p.drawText( 6, top + h - 2, val ); + } + } + + p.end(); + bitBlt( this, 0, 0, &pm ); +} + +#include "signalplotter.moc" diff --git a/src/knemod/signalplotter.h b/src/knemod/signalplotter.h new file mode 100644 index 0000000..f0dabfb --- /dev/null +++ b/src/knemod/signalplotter.h @@ -0,0 +1,160 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of version 2 of the GNU General Public + License as published by the Free Software Foundation. + + 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. + + KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. + Please do not commit any changes without consulting me first. Thanks! + + $Id: SignalPlotter.h,v 1.5 2004/01/04 13:43:48 waba Exp $ +*/ + +#ifndef KSG_SIGNALPLOTTER_H +#define KSG_SIGNALPLOTTER_H + +#include <qpoint.h> +#include <qdialog.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qvaluelist.h> + +#define GRAPH_POLYGON 0 +#define GRAPH_ORIGINAL 1 + +class QColor; + +class SignalPlotter : public QDialog +{ + Q_OBJECT + + public: + SignalPlotter( QWidget *parent = 0, const char *name = 0 ); + ~SignalPlotter(); + + /** + * Implemented to store position. + */ + void hide(); + void show(); + + bool addBeam( const QColor &color ); + void addSample( const QValueList<double> &samples ); + + void removeBeam( uint pos ); + + void changeRange( int beam, double min, double max ); + + QValueList<QColor> &beamColors(); + + void setTitle( const QString &title ); + QString title() const; + + void setUseAutoRange( bool value ); + bool useAutoRange() const; + + void setMinValue( double min ); + double minValue() const; + + void setMaxValue( double max ); + double maxValue() const; + + void setGraphStyle( uint style ); + uint graphStyle() const; + + void setHorizontalScale( uint scale ); + uint horizontalScale() const; + + void setShowVerticalLines( bool value ); + bool showVerticalLines() const; + + void setVerticalLinesColor( const QColor &color ); + QColor verticalLinesColor() const; + + void setVerticalLinesDistance( int distance ); + int verticalLinesDistance() const; + + void setVerticalLinesScroll( bool value ); + bool verticalLinesScroll() const; + + void setShowHorizontalLines( bool value ); + bool showHorizontalLines() const; + + void setHorizontalLinesColor( const QColor &color ); + QColor horizontalLinesColor() const; + + void setHorizontalLinesCount( int count ); + int horizontalLinesCount() const; + + void setShowLabels( bool value ); + bool showLabels() const; + + void setShowTopBar( bool value ); + bool showTopBar() const; + + void setFontSize( int size ); + int fontSize() const; + + void setBackgroundColor( const QColor &color ); + QColor backgroundColor() const; + + protected: + void updateDataBuffers(); + + virtual void resizeEvent( QResizeEvent* ); + virtual void paintEvent( QPaintEvent* ); + + private: + QPoint mPos; + bool mPosInitialized; + + double mMinValue; + double mMaxValue; + bool mUseAutoRange; + + uint mGraphStyle; + + bool mShowVerticalLines; + QColor mVerticalLinesColor; + uint mVerticalLinesDistance; + bool mVerticalLinesScroll; + uint mVerticalLinesOffset; + uint mHorizontalScale; + + bool mShowHorizontalLines; + QColor mHorizontalLinesColor; + uint mHorizontalLinesCount; + + bool mShowLabels; + bool mShowTopBar; + uint mFontSize; + + QColor mBackgroundColor; + + QPtrList<double> mBeamData; + QValueList<QColor> mBeamColor; + + int mSamples; + + /** + * The name of the interface. + * Needed to store the geometry of the plotter in the right + * group of the config file. + */ + QString mName; + QString mTitle; +}; + +#endif |