pax_global_header00006660000000000000000000000064134575366100014524gustar00rootroot0000000000000052 comment=f9d56dd5896b4baf1e6a4a00e54bf3dbdb7d849d sigviewer-0.6.4/000077500000000000000000000000001345753661000135375ustar00rootroot00000000000000sigviewer-0.6.4/.gitignore000066400000000000000000000001521345753661000155250ustar00rootroot00000000000000.directory .DS_Store *~ external/ sigviewer.pro.user *.a *.o tmp/ bin/ .qmake.stash Makefile src/Makefile sigviewer-0.6.4/LICENSE000066400000000000000000001033041345753661000145450ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . sigviewer-0.6.4/README.md000066400000000000000000000236721345753661000150300ustar00rootroot00000000000000SigViewer ========= SigViewer is a viewing application for biosignals such as EEG or MEG time series. In addition to viewing raw data, SigViewer can also create, edit, and display event information (such as annotations or artifact selections). Download -------- - [SigViewer 0.6.2 (Windows 64bit)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/sigviewer-0.6.2-win64.exe) (Windows 7-10, 64bit) - [SigViewer 0.6.2 (Windows 32bit)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/sigviewer-0.6.2-win32.exe) (Windows 7-10, 32bit) - [SigViewer 0.6.2 (macOS 64bit)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/sigviewer-0.6.2-macos.dmg) (macOS 10.9-10.13, 64bit) (note that after you have dragged the app to your Applications folder, you might have to start it by right-clicking the app and selecting "Open" since double-clicking might not work) - [SigViewer 0.6.2 (Linux 64bit)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/sigviewer-0.6.2-linux.zip) / [SigViewer 0.6.2 (Arch Linux AUR)](https://aur.archlinux.org/packages/sigviewer/) - [SigViewer 0.6.2 (Source)](https://github.com/cbrnr/sigviewer/archive/v0.6.2.zip) Screenshots ----------- ![screenshot-1](https://github.com/cbrnr/sigviewer/raw/master/screenshot-1.png) Building SigViewer ------------------ SigViewer requires a standard-compliant C++11 build toolchain, for example recent versions of [GCC](https://gcc.gnu.org/) or [Clang](https://clang.llvm.org/). Other compilers such as [MSVC](https://en.wikipedia.org/wiki/Visual_C%2B%2B) might work, but are not tested. Furthermore, SigViewer depends on [Qt](https://www.qt.io/). Current SigViewer builds use Qt 5.9 (previous or future versions are not guaranteed to work). SigViewer depends on [libbiosig](http://biosig.sourceforge.net/) and [libxdf](https://github.com/Yida-Lin/libxdf). There are two options to get these external dependencies for your platform: 1. Build these dependencies yourself (see separate descriptions below). 2. Use our pre-built binaries. The corresponding archive contains binary versions of libbiosig and libxdf and must be extracted into SigViewer’s source folder (which we denote as `$sigviewer`). - [External dependencies (Windows)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-win64.zip) (Windows 7-10, 64bit) - [External dependencies (Windows)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-win32.zip) (Windows 7-10, 32bit) - [External dependencies (macOS)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-macos.zip) (macOS 10.9-10.13, 64bit) - [External dependencies (Linux)](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-linux.zip) (64bit) ### Windows SigViewer requires Windows 7 or Windows 10. Other versions might work, but have not been tested. First, download the offline installer for [Qt 5.9.6 for Windows](http://download.qt.io/official_releases/qt/5.9/5.9.6/qt-opensource-windows-x86-5.9.6.exe). Run the installation wizard and make sure to also select MinGW 5.3 in the Tools group. Once the installation is completed, a new folder _Qt 5.9.6_ is added to the Start menu. It contains the command prompt _Qt 5.9.6 for Desktop_, which has all required build tools (`qmake` and `mingw32-make`) added to its path. Make sure you use this command prompt if you want to build on the command line. Alternatively, you can build SigViewer with Qt Creator, which is installed along with Qt by default. Here, we describe the build process using Qt Creator. 1. Download and unzip the [SigViewer source](https://github.com/cbrnr/sigviewer/archive/v0.6.2.zip). 1. Provide all external dependencies by downloading the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-win32.zip) and extracting it inside `$sigviewer` (see below for more details and options regarding the external dependencies). 1. Open `sigviewer.pro` in Qt Creator. 1. Accept the default configuration by clicking on _Configure Project_. 1. Click on _Build Project_ (the hammer icon) to build SigViewer. 1. Click on _Run_ (the play icon) to start SigViewer. 1. To create a stand-alone version of SigViewer, open the _Qt 5.9.6 for Desktop_ command prompt, change into `$sigviewer/bin/release`, and run `windeployqt sigviewer.exe`. SigViewer now runs on any Windows machine (no previous Qt installation is required) if the contents of this directory is distributed together with `sigviewer.exe` (see `$sigviewer/deploy/windows/README.md` for details on how to create a stand-alone installer package). ### macOS Mac OS X (now renamed to macOS) 10.9 or later is required. First, install XCode from the App Store. Next, download the offline installer for [Qt 5.9.6 for macOS](http://download.qt.io/official_releases/qt/5.9/5.9.6/qt-opensource-mac-x64-5.9.6.dmg). Run the installation wizard. Make sure that `qmake` is available on the path if you want to build SigViewer on the command line. Alternatively, you can build SigViewer with Qt Creator, which is installed along with Qt by default. Here, we describe the build process using the command line, but if you want to use Qt Creator instead refer to the description for building SigViewer on Windows. 1. Download and unzip the [SigViewer source](https://github.com/cbrnr/sigviewer/archive/v0.6.2.zip). 1. Provide all external dependencies: - Either download the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-macos.zip) and extract it inside `$sigviewer`. - Or copy the necessary files from libbiosig and libxdf builds to the corresponding folders as detailed in the build descriptions for libbiosig and libxdf below. 1. In a terminal, change to `$sigviewer` and run `qmake`. 1. Run `make` (or if you want to use more cores to build in parallel, run `make -j 4` if you want to use four cores). The SigViewer binary is built in the `bin/release` folder. 1. To create a stand-alone version of SigViewer, open a terminal, change into `$sigviewer/bin/release` and run `macdeployqt sigviewer.app -dmg`. This creates a disk image with the app, which can then be dragged to the Applications folder. ### Linux Install the GNU toolchain and Qt 5 with your native package manager. You can either build on the command line or with Qt Creator (which you then need to install). 1. Download and unzip the [SigViewer source](https://github.com/cbrnr/sigviewer/archive/v0.6.2.zip). 1. Provide all external dependencies: - Either download the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-linux.zip) and extract it inside `$sigviewer`. - Or copy the necessary files from libbiosig and libxdf builds to the corresponding folders as detailed in the build descriptions for libbiosig and libxdf below. 1. In a terminal, change to `$sigviewer` and run `qmake`. 1. Run `make` (or if you want to use more cores to build in parallel, run `make -j 4` if you want to use four cores). The SigViewer binary is built in the `bin/release` folder. 1. You can directly start the executable in a terminal. If you use [Arch Linux](https://aur.archlinux.org/packages/sigviewer/) or Ubuntu/Debian Linux, we provide native packages for these distributions. Building external dependencies ------------------------------ ### Windows Building libbiosig on Windows is currently not possible. Please use our pre-built binary included in the [external archive](https://github.com/cbrnr/sigviewer/releases/download/v0.6.2/external-0.6.2-windows.zip), which we built using [MXE](http://mxe.cc/). To build libxdf from source, follow these steps: 1. Download and unzip the [libxdf source](https://github.com/Yida-Lin/libxdf/archive/v0.98.zip) (SigViewer 0.6.2 uses libxdf 0.98). 1. On the command line, run `qmake` followed by `mingw32-make` (or build the project with Qt Creator). Instead of `qmake`, you can also run `cmake .`. 2. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. ### macOS To build libbiosig from source, follow these steps: 1. Building libbiosig requires `gawk`. The easiest way to install it is via [Homebrew](http://brew.sh/) (`brew install gawk`). 1. Download and unzip [BioSig for C/C++](https://sourceforge.net/projects/biosig/files/BioSig%20for%20C_C%2B%2B/src/biosig4c%2B%2B-1.8.6.src.tar.gz) (SigViewer 0.6.2 uses libbiosig 1.8.6). 1. Change the following lines in `Makefile`: - Comment out line 201: `# DEFINES += -D=WITH_ZLIB` - Comment out line 209 to: `# DEFINES += -D=WITH_CHOLMOD` - Change `10.7` in lines 151 and 153 to `10.9` 1. In a terminal, run `make libbiosig.a`. 1. Copy `biosig.h` and `gdftime.h` to `$sigviewer/external/include` and `libbiosig.a` to `$sigviewer/external/lib`. To build libxdf from source, follow these steps: 1. Download and unzip the [libxdf source](https://github.com/Yida-Lin/libxdf/archive/v0.98.zip) (SigViewer 0.6.2 uses libxdf 0.98). 1. In a terminal, run `qmake` followed by `make`. Instead of `qmake`, you can also run `cmake .`. 1. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. ### Linux To build libbiosig from source, follow these steps: 1. Download and unzip [BioSig for C/C++](https://sourceforge.net/projects/biosig/files/BioSig%20for%20C_C%2B%2B/src/biosig4c%2B%2B-1.8.6.src.tar.gz) (SigViewer 0.6.2 uses libbiosig 1.8.6). 1. Change the following lines in `Makefile`: - Comment out line 201: `# DEFINES += -D=WITH_ZLIB` - Comment out line 209 to: `# DEFINES += -D=WITH_CHOLMOD` 1. In a terminal, run `make libbiosig.a`. 1. Copy `biosig.h` and `gdftime.h` to `$sigviewer/external/include` and `libbiosig.a` to `$sigviewer/external/lib`. To build libxdf from source, follow these steps: 1. Download and unzip the [libxdf source](https://github.com/Yida-Lin/libxdf/archive/v0.98.zip) (SigViewer 0.6.2 uses libxdf 0.98). 1. In a terminal, run `qmake` followed by `make`. Instead of `qmake`, you can also run `cmake .`. 1. Copy `xdf.h` into `$sigviewer/external/include` and `libxdf.a` to `$sigviewer/external/lib`. sigviewer-0.6.4/changelog.txt000066400000000000000000000123001345753661000162230ustar00rootroot00000000000000Version 0.6.4 (+) Re-enable import/export event from/to EVT Version 0.6.3 (B) libxdf update (improves stability) Version 0.6.2 (+) Store user-defined colors (+) Use effective sample rate in XDF files (B) Fix issues in some dialogs (B) Fix channel clipping (*) Refactoring (cleanups) Version 0.6.1 (B) Fix many XDF-related bugs (*) Several minor GUI-related improvements Version 0.6.0 (+) Add support for XDF files (B) Properly handle missing data (+) Export and import events to/from CSV files (*) Redesign view options widget (*) New icon theme (*) Switch from Qt 4 to Qt 5 (*) Many UI improvements (channel separators, grids, dialogs) Version 0.5.2 (*) Integrated patches from the BioSig project Version 0.5.1 (B) Fixed bug where signals could be distorted (*) Removed libgdf (*) Removed downsampling/decimation (*) Events are now always displayed in a separate tab (B) Fixed file drag & drop bug Version 0.5.0 (*) Optimized gdf reading (background downsampling/decimation) (*) Support for large gdf (2) files (*) Using libgdf to read gdf 2 files (http://libgdf.sourceforge.net, svn revision 57) (B) Bug fix (memory leak) Version 0.4.3 (*) switched to new libgdf (http://libgdf.sourceforge.net, svn revision 9) (*) removed dependency on boost-library (only headers are needed) (B) Bug fix (fixed chrash on Win XP when deselecting channels) Version 0.4.2 (+) Convert to GDF (using libgdf) (+) Command-line options (e.g. --convert-to-gdf, --help) (+) Improved y-grid drawing (+) Improved y-grid labels (displaying units) (+) Improved y-scaling, new dialog (*) Power-spectrum is now displayed in log10 (B) Bug fixes (instant viewport update after color changing and scaling, no chrash if signal processing leads to overflow) (*) Refactoring and code cleanups (*) switched from FFTW to FFTReal Version 0.4.1 (*) Speeded up animations (now duration is settable via the View menu) (*) Renamed "Shift Signal Mode" to "View Options Mode" (+) Animated event browsing (+) Reset event colors (+) Setting default channel color (B) fixed bugs (3021230, 3020031, 3019593, 3019592) Version 0.4.0 (*) Works on Mac OS X (again) (+) Animated zoom (+) Export to GDF (+) Export to PNG (+) Calculate power spectrum averaged over an event type (+) Calculate mean and standard deviation averaged over an event type (+) Color settings for signal channels (+) Mode-specific widgets (for editing selected events) (+) New context menu for channels (*) Improved dialogs (event table, event type selection) (B) Fixed many bugs (*) Refactoring and code clean-ups Version 0.3.0 (*) Removed all Qt3 stuff, now completely ported to Qt4 (+) Dropping files on SigViewer opens the file (+) Open files via command line parameter (+) Event toolbar (for editing selected events) (+) Calculate mean (alpha version) (+) Undo/redo for editing events (+) Insert event (Ctrl+I), creates new event over the selected event (+) Event browsing (Ctrl+Right, Ctrl+Left), go to next/previous event of same type as selected event (+) Fit view to selected event (+) Hie events of other type (+) Highlighting on x-axis when editing or creating an event (+) New context menu for events (+) Simple hiding/showing label and axis widgets (-) Scrolling during creation of events is not possible (will be added as soon as possible) (B) Fixed many bugs (*) Refactoring and code clean-ups (especially decoupling of classes) Version 0.2.6 (+) Qt Creator support (+) Added signal buffer options (whole subsampling selection, disable initial min-max search) (B) Fixed many bugs related to loading files, especially slow loading under Windows network shares is resolved (*) Cleaned up code in biosig_reader.cpp Version 0.2.5 (+) Added preferences dialog (*) Removed some Qt3 stuff, but still not everything Version 0.2.4 (+) Update biosig4c++ to support more file formats Version 0.2.3 (+) Improve support for BCI2000 1.1 data format Version 0.2.2 (B) Fixed export and import of EVT files (B) Fixed missing file name in window title (+) Added new file formats (BCI2000, MIT/Physiobank) (+) Improved handling of some file formats (EDF+, GDF1, BrainVision, AINF) Version 0.2.1 (B) Fixed CNT and VHDR errors Version 0.2.0 (+) Added support for biosig4c++, loading and saving is now done with this library. Therefore, many new formats are supported (GDF, BKR, CNT, EDF, ...) (B) Channel selection works (+) Scrolling during creation of events is now possible (*) Standard zoom setting is now auto (*) Zero level on the y-axis is now in the middle of the channel window (+) Should now compile and work on big endian machines (e.g. PPC) Version 0.1.7 (B) Fix export of EVT files with a sampling rate higher than 256Hz Version 0.1.6 (B) Fix serious bug where SigViewer crashed when opening a file (probably due to a Windows update) Version 0.1.5 (B) Remove bug where SigViewer crashed when exiting Version 0.1.4 (B) Remove bug in SignalBuffer Version 0.1.3 (+) Added y-axis (*) Removed SettingsManager and use QSettings instead Version 0.1.2 (+) Status bar with length, number of channels and number of trials (+) Export events to EVT files (B) Removed signal shift bug (B) Channel selection has no effect on scale (+) After opening a file, show all channels Version 0.1.1 (*) Use QString and Qt container instead of STL stuff (B) No line wrap in LogDialog sigviewer-0.6.4/create-src.sh000077500000000000000000000012021345753661000161210ustar00rootroot00000000000000#!/bin/sh version_major=`sed -n -e 's/^VERSION_MAJOR = \([0-9]*\)$/\1/p' sigviewer.pro` version_minor=`sed -n -e 's/^VERSION_MINOR = \([0-9]*\)$/\1/p' sigviewer.pro` version_build=`sed -n -e 's/^VERSION_BUILD = \([0-9]*\)$/\1/p' sigviewer.pro` version=$version_major.$version_minor.$version_build mkdir -p sigviewer-$version-src cp * sigviewer-$version-src cp -r deb_building_stuff sigviewer-$version-src cp -r src sigviewer-$version-src/src rm sigviewer-$version-src/*.pro.user find sigviewer-$version-src -name "Makefile*" -delete tar czvf sigviewer-$version-src.tar.gz --exclude=.* sigviewer-$version-src rm -rf sigviewer-$version-src sigviewer-0.6.4/deploy/000077500000000000000000000000001345753661000150335ustar00rootroot00000000000000sigviewer-0.6.4/deploy/debian/000077500000000000000000000000001345753661000162555ustar00rootroot00000000000000sigviewer-0.6.4/deploy/debian/build-deb.sh000077500000000000000000000030041345753661000204400ustar00rootroot00000000000000#!/bin/sh dir=/tmp/sigviewer-deb-build # create temporary build directories mkdir -p $dir/sigviewer/usr/bin mkdir -p $dir/sigviewer/usr/share mkdir -p $dir/sigviewer/usr/share/pixmaps mkdir -p $dir/sigviewer/usr/share/applications mkdir -p $dir/sigviewer/DEBIAN # copy necessary files cp ../../bin/release/sigviewer $dir/sigviewer/usr/bin/ cp sigviewer128.png $dir/sigviewer/usr/share/pixmaps/ cp sigviewer.desktop $dir/sigviewer/usr/share/applications/ # get current version of sigviewer version_major=`sed -n -e 's/^VERSION_MAJOR = \([0-9]*\)$/\1/p' ../../sigviewer.pro` version_minor=`sed -n -e 's/^VERSION_MINOR = \([0-9]*\)$/\1/p' ../../sigviewer.pro` version_build=`sed -n -e 's/^VERSION_BUILD = \([0-9]*\)$/\1/p' ../../sigviewer.pro` version=$version_major.$version_minor.$version_build # get local architecture architecture=`dpkg-architecture -l | grep DEB_BUILD_ARCH= | sed -e '/DEB_BUILD_ARCH=/s/DEB_BUILD_ARCH=//'` # get file size of the binary filesizestring=`ls -s ../../bin/release/sigviewer` set -- $filesizestring filesize=$1 # replace architecture, file size and version in the control file sed -e '/Architecture: /s//'$architecture'/' deb_control_template | sed -e '/Installed-Size: /s//'$filesize'/' | sed -e '/Version: /s//'$version'/' | sed -e '/Replaces: /s//'$version'/' > $dir/sigviewer/DEBIAN/control # build the SigViewer package dpkg -b $dir/sigviewer sigviewer-$version-$architecture.deb # delete all temporary build directories rm -r $dir sigviewer-0.6.4/deploy/debian/deb_control_template000066400000000000000000000006401345753661000223650ustar00rootroot00000000000000Package: sigviewer Version: Section: science Priority: extra Architecture: Depends: libqtcore4 (>=4.7), libqtgui4 (>=4.7), libqt4-xml (>=4.7) Replaces: sigviewer (<< ) Installed-Size: Maintainer: Clemens Brunner Homepage: https://github.com/cbrnr/sigviewer Description: SigViewer is a viewing application for biosignals. sigviewer-0.6.4/deploy/debian/sigviewer.desktop000066400000000000000000000002671345753661000216610ustar00rootroot00000000000000[Desktop Entry] Name=SigViewer Version=1.0 Comment=SigViewer is a viewing application for biosignals Exec=/usr/bin/sigviewer Icon=sigviewer128.png Type=Application Categories=Science sigviewer-0.6.4/deploy/debian/sigviewer128.png000066400000000000000000000325061345753661000212300ustar00rootroot00000000000000PNG  IHDR>abKGDC pHYs  tIME l IDATx}ixו[ի[ݒՒZ+]X`;v2&$LMY2&3;dIkl6$ 8b֬YFɛ-}tfϞtdggߐU>˲u秧C#-- ,h.++[ j E|4MΙ37$:ʆ'X(BZZ, n7v;<2N[ntǹǏFZBN\$:<fH̿), OƵieYo, aT׋H$rWzqv=Ȍ<,K7 #@`Y ߏj*//FEEbYE xP' J ^m.ҝ9Aq'ES)r>ű>Η~!ns+T= ,XV?+>窏_a3,LݚYbD5 XUh&:jp80-;tҠX~["(XiH ϡAS2@@%k Fβ,c ǀA# )[ƎM X\aHɄ@K:(ՄlQD#7`)cǂeYn~Ca1YBX*sS'vD'4eC,@kK)`@IiLd$+A8 @j\%RpY`Xf>Arpmy5BjZCUfAuE@ G2q_v}!  % 7L_`>2AT\Ѩz))z7/\ԍo \)|30,aAp>LH^N ].nV.`|Na$̘F:t{t՛ ,Ra$P=z4x fe~S.aavNv0%A3I`a3,X(ee#=M@ ݃Q05u:\:S$_`T>t$ GPiYPwY\0iT_{rlS#0,FӒ&0_YƶL×We4*k|I8& {L|ɋcqΪGQƽ2I၊,\/l+]/4z6H2N֡0崩욠I' e3 2kezllMY㴇S  叾b;ϲl6'ψď׸07$=/ma$ 2,5hdXf7_  wHfR97g%N<4ǫzP@y _YSmjߠj_| kP=CPB Јr%N=&8.$/tHX5ˡο!oP^ِj@8ߘ*qV5cA ˰HȂt<ߤ f $XlR=AGp\-`vArYu`cRGvX@gf In(0 ): (iyeVk p_,bâ -kFCw'ZB N; G!P)sr 8YȌc-a|FNN Y_nÉa1&0 |38-`DR<G,S NWGc щYHݻ3zd |ҚFF=- 0*Y EkMIͲ,_Vi4U*ըyȲ@ :y`^ I[J*f?ڜGhF,oN F}Z9quh>4 RoT3 3'gRh96Yf?`e g|qfP~\Ųi6jWwS*`&A Fpl\?Huy` <en4N e38})OTVuGŹߎ5 %,|i61B8O0 Rc4{}ٹxa/˫fѸ]al9]1 !yT/cW/-!Ջ:/#D$p$+cY}aX&VܱOrW{vblj>c4LkFq%fa`(-H?G 64tE0%G>ԺCX;ώ=þAя(qrjfʡ~|r)Wɴ%oD 1E.݅Ʈ0ɉ0~Qζ6qVuɕ9Yc <؅}:ӧ5s5#KJ $:L:6/w /j/$g|= aQ4vF;;;eF|̟LGwPЛ ?i bryHr`Y׮nLuU+g5Ə{n5X_ӁԮ("%w/4*4 t,X,*(Pda=k#[Y M?϶w5(d$ aT_ "' 23yXFW((?RfQq?`Fڸ%z{p8,hEږh3 ^<ą-GyD =,A( TdG8$ <Ez|ql9>7gϱG,_<P c>A9Fi)+b x{vsp{B`x({mmmOʆ^Os<% ڀ( D|T/g!TMVMW6&.{#u 1y~OQ 20HcʗX,-(,rj {9Qdf RHJ㻟`ی}>hIˀ@kae) J) ?N惋0.suJ hiEH˲x2_F>|4} |q~==D"qaɿUo>?bC2nh bNJyDA"[5.K|x~(;_>d!(IK0a) 2 +`䣆7Ȁa9=ݾNhGɕ'pQ$åf/ l.<,GnIW 0pt*.geW_GpE /|q ^X2&<Ѽ[f8n%2lzMq)j 0 -pNEs!b%AmIOy6|"d 8X66Cotb`r30Ku_&=%5< ,fLچp_f0R^b9nМb&w KsT\<Ђ`04dg3AkOh\@0\7JrMX<# GS<6cn 6yeXe`v-A|\7i@̀`ݾ(g/iy.)MG8F]Tl?ދBzZn|LX7ɒzYSmYh9ixbe.BX='SFdJ S,䳐iF#MYB 4-ۏyvbanV9oFSMt[ Wem(p[P`mIp@s0ZE$ 1 İh^HUd1f҉Ho?l0hyNjcC OhO(ǿ}h,&tq;"sL{Mh o6U3'zP4/1l5%JB'/C+־vP/޼v*jw/A&5:8XۇY^_/l_om2|yz:= +)\ `v|e}?ދo{0Ԏ,v YaXg?9BkJ ЎThp@}?کa)E6 2(JעA;d/j< \ٖ vr2s`r3 9xxY($V*+OqQP4Y Ã`ЄdTy /Hڅe_j- >*W.⇯4t0M+(a |گbtXEu'|?&ڈXÓgh@$h t |FO0luOJ @~I z #)Q`'{񣍍\B)~6EPh I K1X !Yfd O~6 |j0(@]Sjd@8Ep) OZm/H!ke^o@$CY: Fbɫyp)wƇtcO?~/cZ|\pڍ2FPè) (5g;/.RKqef~h l87@J2L}VF%M6biSbÁsDA`ih (nZ;]oATC?>O TyϹF(ar۝DIFݔJQ?r(/8 dye3; 1cXDy3/87Os`fg/s Nv^XjMӄ֌PmZēD h6i3{ 6oo -j&#r.`JMQV/R;N7|ZʹY*r ))A&d1A<VdꖙT rv `>̚ !Pd:ynX^gD~qgb ߉4 Y09W=3Krj'gྛs<'% Xu3w`Sz]3[ξX?1RZ+X1}P1CWpnFDc zsL`J/ eJs3z.w0"4$VRO2d>I"9I6L7AOWb# lQ4G`a`K㇏OC DLǙoLJt%z4&;.Sn_A:IDAT<4]&L3FVQGUA&j&AF@(“y)3ׁZ<1v,yF+NnRp^gZ·]:ۮlk2b,v "H/K#(|؋͇%:C7ASULz[ .$#hU"  _0 9U*@@TvP(Dz9~чmǼ)xK08òcAl:'iFZ3x4MsPj앳ba0ެE(Ȁvގ緵oBuOmCx}y]1A*2E%?/jW6GS. Յ`~N3,vcDZP/](^[xUC[ggʦjq)oF0?=Pa!# .`cwxdIzql:҇j}u4c(4E:Qw{zpSMl3_ ""f /xf9c?vcW梮u2N7Ol Z]QV|BD "QnS}+9fCϮkhy I=yE~afXk’id΁( .  z?GU$ꭣxh~YgZCX1UXsPtz a#@ɀ*G+H$(` ު7eca/?5%`ip%${SY2FP͟cR'Q$!,"~ "QoUfNB*#D¹Ў2qPˀhG u(x4WȦ5+s[[67*@VP8Ar܇,nbŞ7vbǀ/L0mv})PEbI$ŌM\q(8@,LőځJ;H Z+@yBHz!0?w{yv`Eb Ŀs-`'^$n+,&{H[Osa_rKK\iMCLa NMZ.- (’鸱|K*S4  dsȁEє5N^UVv7aY]( ue0yq~FlW/V/\l3SlR3 ,) >)9$qI|.g>_4e`#H+9:iO?d2hmm=KQ~o`6zڢilܸt$骫o>"ubGJ$Dw!9p8GkjjZ Vk͛7 >c1w~Cחu:Ԅ&l޼#<vH#jٖvn>u |Պr|>ܹ555~.hJjkk{.Ḩ( iD Qzbԩzضm~m x8@@@ƍ_h4`ssiҥx<'wo•\'}fNPG}}=jkk/Uhӌ @)6lx*770==%%%x<07b׋f|m۪op@ TJ̝;wҥKggghkg|3g4WUU Mo"\< dk jzn+))'ÕIc[ss3Ξ=]vmonnn{#O;o._csw?C8?t =F-EMðX, rop4Mj|F˯bZjϥy`nH 0uJdz6///޼y6mڸ | {A__:z8p`7ߙ xG~%UR|Vx9sdL>}MZZڗz}8Nh4{G7Q&;{Aee%qIpx{$7Gm$Cd<§[.h4~oPp:?>nҥKxWpw"77w}L&_^744'Nĉ8y$  #t fnݺL-AQcҥPX[o=5-޽O?4rrr4qAx^bC}w|@T3jbҤIa09jX ;v+V뵇BN9vZ<;cƌo~Ic* (//ǁ [nԩSq_Q ,\Ɔ;}gϞ== p<3YNsϼy򕯌| Dg*;;v >رc8~8Ν ˅~B! 1?#ͳp:hnnd2tR}iiiə㏏Y܋YٺpBEaѢEx<n뛚pbDQD"bhɲ%K ׾}V@2וxᇳ^Yvh܄/fSLjEMM Ο?p8`4ǭ|'F4̙3t:W$Aoo/233Ӎq1[VVV4VcҫGa D䲳rڊ-[ ++ .kTDގvtuu\..\(w"Hz_,"# A[L&,ZxDizmXZJKK1ydDQ@$ɤ.>zFAQV+O.V> ٽL+z ddd ^O r ! BN ߆ dbЅBn+hf3FcW@4|7]I#^00(Mh`p v88_s Gs! ~yߏf ^q"@,`pb`llfS9㱜9s8r 4555qz@h|j9EAA]Q0fD/^۳g'X>aU$Pĉ w 8X"5F,æMkGlQ/\py^ڹ 3gPUUX,]v?~ 4c L4XsΝ-++[DlMMMZ7ϲ裏PWWp8ݳgϡ{GnG0| x霷nݺO9;x/@Oŋ_}WCCE^4wOH.jB(p b'"SV\ymh4@ff&O? wwwSN{w@y|Maͼ&0)##c=sٳ1`@~~SZގ .  ۻ^{N>1I #pnpYrΜ9 L&?5 ˃3x.^W78(AU]]ţG?qD#o߻y< #\mR(Ńk7 `ҥ -Zt:'Z,8Nvvdee]SB|?6TUUutt3tO|ə~~󮚪/a"̐f& T6_ :0x&>ďمma韺Яhi=a*ȃDOD9 B1Gj1BkIz+ Ph6s O#&MB0Z Wa.>Cs].ʇ;OÏIENDB`sigviewer-0.6.4/deploy/windows/000077500000000000000000000000001345753661000165255ustar00rootroot00000000000000sigviewer-0.6.4/deploy/windows/README.md000066400000000000000000000013421345753661000200040ustar00rootroot00000000000000Install the [Qt Installer Framework](https://download.qt.io/official_releases/qt-installer-framework/) and make sure its bin folder is added to the path. The `sigviewer.exe` binary needs to be present in `$sigviewer/bin/release` - if not, build it. Open a command prompt, change into `$sigviewer/bin/release` and type: windeployqt sigviewer.exe Next, move the contents of the `$sigviewer/bin/release` folder into `$sigviewer/deploy/windows/packages/org.sigviewer.sigviewer/data`. Furthermore, copy the file `$sigviewer/src/images/sigviewer.ico` to this folder. Finally, change into `$sigviewer/deploy/windows` in the command prompt and type: binarycreator --offline-only -c config/config.xml -p packages sigviewer sigviewer-0.6.4/deploy/windows/config/000077500000000000000000000000001345753661000177725ustar00rootroot00000000000000sigviewer-0.6.4/deploy/windows/config/config.xml000077500000000000000000000006071345753661000217670ustar00rootroot00000000000000 SigViewer 0.6.4 SigViewer SigViewer Development Team SigViewer @HomeDir@/SigViewer sigviewer128.png sigviewer-0.6.4/deploy/windows/config/sigviewer128.png000077500000000000000000000325061345753661000227500ustar00rootroot00000000000000PNG  IHDR>abKGDC pHYs  tIME l IDATx}ixו[ի[ݒՒZ+]X`;v2&$LMY2&3;dIkl6$ 8b֬YFɛ-}tfϞtdggߐU>˲u秧C#-- ,h.++[ j E|4MΙ37$:ʆ'X(BZZ, n7v;<2N[ntǹǏFZBN\$:<fH̿), OƵieYo, aT׋H$rWzqv=Ȍ<,K7 #@`Y ߏj*//FEEbYE xP' J ^m.ҝ9Aq'ES)r>ű>Η~!ns+T= ,XV?+>窏_a3,LݚYbD5 XUh&:jp80-;tҠX~["(XiH ϡAS2@@%k Fβ,c ǀA# )[ƎM X\aHɄ@K:(ՄlQD#7`)cǂeYn~Ca1YBX*sS'vD'4eC,@kK)`@IiLd$+A8 @j\%RpY`Xf>Arpmy5BjZCUfAuE@ G2q_v}!  % 7L_`>2AT\Ѩz))z7/\ԍo \)|30,aAp>LH^N ].nV.`|Na$̘F:t{t՛ ,Ra$P=z4x fe~S.aavNv0%A3I`a3,X(ee#=M@ ݃Q05u:\:S$_`T>t$ GPiYPwY\0iT_{rlS#0,FӒ&0_YƶL×We4*k|I8& {L|ɋcqΪGQƽ2I၊,\/l+]/4z6H2N֡0崩욠I' e3 2kezllMY㴇S  叾b;ϲl6'ψď׸07$=/ma$ 2,5hdXf7_  wHfR97g%N<4ǫzP@y _YSmjߠj_| kP=CPB Јr%N=&8.$/tHX5ˡο!oP^ِj@8ߘ*qV5cA ˰HȂt<ߤ f $XlR=AGp\-`vArYu`cRGvX@gf In(0 ): (iyeVk p_,bâ -kFCw'ZB N; G!P)sr 8YȌc-a|FNN Y_nÉa1&0 |38-`DR<G,S NWGc щYHݻ3zd |ҚFF=- 0*Y EkMIͲ,_Vi4U*ըyȲ@ :y`^ I[J*f?ڜGhF,oN F}Z9quh>4 RoT3 3'gRh96Yf?`e g|qfP~\Ųi6jWwS*`&A Fpl\?Huy` <en4N e38})OTVuGŹߎ5 %,|i61B8O0 Rc4{}ٹxa/˫fѸ]al9]1 !yT/cW/-!Ջ:/#D$p$+cY}aX&VܱOrW{vblj>c4LkFq%fa`(-H?G 64tE0%G>ԺCX;ώ=þAя(qrjfʡ~|r)Wɴ%oD 1E.݅Ʈ0ɉ0~Qζ6qVuɕ9Yc <؅}:ӧ5s5#KJ $:L:6/w /j/$g|= aQ4vF;;;eF|̟LGwPЛ ?i bryHr`Y׮nLuU+g5Ə{n5X_ӁԮ("%w/4*4 t,X,*(Pda=k#[Y M?϶w5(d$ aT_ "' 23yXFW((?RfQq?`Fڸ%z{p8,hEږh3 ^<ą-GyD =,A( TdG8$ <Ez|ql9>7gϱG,_<P c>A9Fi)+b x{vsp{B`x({mmmOʆ^Os<% ڀ( D|T/g!TMVMW6&.{#u 1y~OQ 20HcʗX,-(,rj {9Qdf RHJ㻟`ی}>hIˀ@kae) J) ?N惋0.suJ hiEH˲x2_F>|4} |q~==D"qaɿUo>?bC2nh bNJyDA"[5.K|x~(;_>d!(IK0a) 2 +`䣆7Ȁa9=ݾNhGɕ'pQ$åf/ l.<,GnIW 0pt*.geW_GpE /|q ^X2&<Ѽ[f8n%2lzMq)j 0 -pNEs!b%AmIOy6|"d 8X66Cotb`r30Ku_&=%5< ,fLچp_f0R^b9nМb&w KsT\<Ђ`04dg3AkOh\@0\7JrMX<# GS<6cn 6yeXe`v-A|\7i@̀`ݾ(g/iy.)MG8F]Tl?ދBzZn|LX7ɒzYSmYh9ixbe.BX='SFdJ S,䳐iF#MYB 4-ۏyvbanV9oFSMt[ Wem(p[P`mIp@s0ZE$ 1 İh^HUd1f҉Ho?l0hyNjcC OhO(ǿ}h,&tq;"sL{Mh o6U3'zP4/1l5%JB'/C+־vP/޼v*jw/A&5:8XۇY^_/l_om2|yz:= +)\ `v|e}?ދo{0Ԏ,v YaXg?9BkJ ЎThp@}?کa)E6 2(JעA;d/j< \ٖ vr2s`r3 9xxY($V*+OqQP4Y Ã`ЄdTy /Hڅe_j- >*W.⇯4t0M+(a |گbtXEu'|?&ڈXÓgh@$h t |FO0luOJ @~I z #)Q`'{񣍍\B)~6EPh I K1X !Yfd O~6 |j0(@]Sjd@8Ep) OZm/H!ke^o@$CY: Fbɫyp)wƇtcO?~/cZ|\pڍ2FPè) (5g;/.RKqef~h l87@J2L}VF%M6biSbÁsDA`ih (nZ;]oATC?>O TyϹF(ar۝DIFݔJQ?r(/8 dye3; 1cXDy3/87Os`fg/s Nv^XjMӄ֌PmZēD h6i3{ 6oo -j&#r.`JMQV/R;N7|ZʹY*r ))A&d1A<VdꖙT rv `>̚ !Pd:ynX^gD~qgb ߉4 Y09W=3Krj'gྛs<'% Xu3w`Sz]3[ξX?1RZ+X1}P1CWpnFDc zsL`J/ eJs3z.w0"4$VRO2d>I"9I6L7AOWb# lQ4G`a`K㇏OC DLǙoLJt%z4&;.Sn_A:IDAT<4]&L3FVQGUA&j&AF@(“y)3ׁZ<1v,yF+NnRp^gZ·]:ۮlk2b,v "H/K#(|؋͇%:C7ASULz[ .$#hU"  _0 9U*@@TvP(Dz9~чmǼ)xK08òcAl:'iFZ3x4MsPj앳ba0ެE(Ȁvގ緵oBuOmCx}y]1A*2E%?/jW6GS. Յ`~N3,vcDZP/](^[xUC[ggʦjq)oF0?=Pa!# .`cwxdIzql:҇j}u4c(4E:Qw{zpSMl3_ ""f /xf9c?vcW梮u2N7Ol Z]QV|BD "QnS}+9fCϮkhy I=yE~afXk’id΁( .  z?GU$ꭣxh~YgZCX1UXsPtz a#@ɀ*G+H$(` ު7eca/?5%`ip%${SY2FP͟cR'Q$!,"~ "QoUfNB*#D¹Ў2qPˀhG u(x4WȦ5+s[[67*@VP8Ar܇,nbŞ7vbǀ/L0mv})PEbI$ŌM\q(8@,LőځJ;H Z+@yBHz!0?w{yv`Eb Ŀs-`'^$n+,&{H[Osa_rKK\iMCLa NMZ.- (’鸱|K*S4  dsȁEє5N^UVv7aY]( ue0yq~FlW/V/\l3SlR3 ,) >)9$qI|.g>_4e`#H+9:iO?d2hmm=KQ~o`6zڢilܸt$骫o>"ubGJ$Dw!9p8GkjjZ Vk͛7 >c1w~Cחu:Ԅ&l޼#<vH#jٖvn>u |Պr|>ܹ555~.hJjkk{.Ḩ( iD Qzbԩzضm~m x8@@@ƍ_h4`ssiҥx<'wo•\'}fNPG}}=jkk/Uhӌ @)6lx*770==%%%x<07b׋f|m۪op@ TJ̝;wҥKggghkg|3g4WUU Mo"\< dk jzn+))'ÕIc[ss3Ξ=]vmonnn{#O;o._csw?C8?t =F-EMðX, rop4Mj|F˯bZjϥy`nH 0uJdz6///޼y6mڸ | {A__:z8p`7ߙ xG~%UR|Vx9sdL>}MZZڗz}8Nh4{G7Q&;{Aee%qIpx{$7Gm$Cd<§[.h4~oPp:?>nҥKxWpw"77w}L&_^744'Nĉ8y$  #t fnݺL-AQcҥPX[o=5-޽O?4rrr4qAx^bC}w|@T3jbҤIa09jX ;v+V뵇BN9vZ<;cƌo~Ic* (//ǁ [nԩSq_Q ,\Ɔ;}gϞ== p<3YNsϼy򕯌| Dg*;;v >رc8~8Ν ˅~B! 1?#ͳp:hnnd2tR}iiiə㏏Y܋YٺpBEaѢEx<n뛚pbDQD"bhɲ%K ׾}V@2וxᇳ^Yvh܄/fSLjEMM Ο?p8`4ǭ|'F4̙3t:W$Aoo/233Ӎq1[VVV4VcҫGa D䲳rڊ-[ ++ .kTDގvtuu\..\(w"Hz_,"# A[L&,ZxDizmXZJKK1ydDQ@$ɤ.>zFAQV+O.V> ٽL+z ddd ^O r ! BN ߆ dbЅBn+hf3FcW@4|7]I#^00(Mh`p v88_s Gs! ~yߏf ^q"@,`pb`llfS9㱜9s8r 4555qz@h|j9EAA]Q0fD/^۳g'X>aU$Pĉ w 8X"5F,æMkGlQ/\py^ڹ 3gPUUX,]v?~ 4c L4XsΝ-++[DlMMMZ7ϲ裏PWWp8ݳgϡ{GnG0| x霷nݺO9;x/@Oŋ_}WCCE^4wOH.jB(p b'"SV\ymh4@ff&O? wwwSN{w@y|Maͼ&0)##c=sٳ1`@~~SZގ .  ۻ^{N>1I #pnpYrΜ9 L&?5 ˃3x.^W78(AU]]ţG?qD#o߻y< #\mR(Ńk7 `ҥ -Zt:'Z,8Nvvdee]SB|?6TUUutt3tO|ə~~󮚪/a"̐f& T6_ :0x&>ďمma韺Яhi=a*ȃDOD9 B1Gj1BkIz+ Ph6s O#&MB0Z Wa.>Cs].ʇ;OÏIENDB`sigviewer-0.6.4/deploy/windows/packages/000077500000000000000000000000001345753661000203035ustar00rootroot00000000000000sigviewer-0.6.4/deploy/windows/packages/org.sigviewer.sigviewer/000077500000000000000000000000001345753661000251005ustar00rootroot00000000000000sigviewer-0.6.4/deploy/windows/packages/org.sigviewer.sigviewer/meta/000077500000000000000000000000001345753661000260265ustar00rootroot00000000000000sigviewer-0.6.4/deploy/windows/packages/org.sigviewer.sigviewer/meta/installscript.qs000077500000000000000000000011001345753661000312610ustar00rootroot00000000000000function Component() { // default constructor var programFiles = installer.environmentVariable("ProgramFiles"); if (programFiles !== "") installer.setValue("TargetDir", programFiles + "\/SigViewer"); } Component.prototype.createOperations = function() { component.createOperations(); if (systemInfo.productType === "windows") { component.addOperation("CreateShortcut", "@TargetDir@/sigviewer.exe", "@StartMenuDir@/SigViewer.lnk", "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/sigviewer.ico"); } } sigviewer-0.6.4/deploy/windows/packages/org.sigviewer.sigviewer/meta/package.xml000077500000000000000000000005101345753661000301420ustar00rootroot00000000000000 SigViewer SigViewer is a viewing application for biosignals 0.6.4 2019-04-23 true sigviewer-0.6.4/screenshot-1.png000066400000000000000000002526141345753661000165720ustar00rootroot00000000000000PNG  IHDR|m#+_ IDATx $uygsfub43FM"̪YVc3񜎸<$*FgUª?(3FC2 3 ""ꚪ:>zNwS=*,     M{p#t@@@@(sOv)3}G@@@@$@HI_@@@@@|K=t@@@@$@HI_@@@@@|K=t@@@@$@HI_@@@@@|K=t@@@@$[TUw]zzz\}]o{eղnv+u     Qo]9g}w~ [weپ}p g= "    Dՙ{|wfW.GDkew=|'*ǫGyT~QC,{0AH @@@@LtIr-m]A4w8TO>\۱+' ~enˁ,O(9`.yDg    S@^6cX km]yurlqyI#r=}>(R?<u@@@@tuz_vn[#6YOXg6뮓g>:g;ư1T[[yǧG/KqK/!37/'|xQ^ewOvx ߙLbot&/uo]Kcs}Tґjm=mĒۦ:gtC Ng 33(mh[[:sv/-3eَ;Vgmm@@@@ q RV`r5X^7%p7w? >{{r{ʣ>&{흿A*ǫoVY2256xYV ݬ;l[mMhRlvShe\*\MSvoiBWD;u]9]Uc7vDdjKpFLaM@@@"`>" ^=np\>S:Xyw?e{ľU=T۾C>lov"8zoyw;dlYs|u'TΝՐ)dm*KccWͺ5@;9q]:.6Ć! z|z#UU6 Hřʈ ˖I;EdD‘   x h@+^O66TFWCՙsfA>=//uO,9sw9#Ν,/Iz\ ߝ;wFh[z pFF?_3Qwl_N,/u{':/b]e[}Z`џ7S(X~_O18!34*Zeg}-}X&2"ɩczWJɂ}G3_'6uިigڭbȜLɰ#8ujk!MmM1SۘVn5]SD9h_e*iǎ.s@@@n]u*]@=諁n{z^'/+_'IǮ~<{˛^t2g`_^}ChmJ; -N +dzdN*}v[\}T:/fpl˴dq\V\(-\uM[d-㚩Rݸ Õ9{K]oD-S+ {ַ s~ɪ%X_icl'53e\'kPJuq\tc8{K߮n>=zyZ%6LV߹kʛo3[X3G4ʋ st~eYuck@@@(@mbUfŸ2[M?zRjJz|pce佯8Ftr .?H>| r;erʪEzCxvtjy6mIq 60.s b(j۵oݚv@dR[j &XYi l13qmRK[0ǺnC"US뜔f6^GQ'2v鶙>OKkU*Ȍކ_gmit) +,>s^7gb}&üiDL ۜ}d`nl_%Og @#\k*oSUoyl/   r3>啢 '=U!}6\z|wg_^^eewUMTgj7 ƅӦed"4'k䫶_)~uYsR'ɶ-i 6'mkiIu֩V--[1[tPfmK?>1rnU;&G4%ðLll;lKOo暳nɬ9 R# >M0'ڥendm#CKzݹۻF X34;"kVJiܮzϿeb    P{ %mu]#Wgr#=Q\ U+*]vxLb LNH𨬭g6vHW3DL퀦:hS(ӯ An^'mQLdbӔ(D_Oh%\ @mZjmiސLV2wФTWɠq!ڧi7 s2]sWzeͺlɾm2?J6eˢơe`E`#    P8{׺hM;CW}EVD)G OxI٠އzH8?.,[M34) E@@@@CuN`Kgj)tΝ;e}<)fjJ/32# Woj-0)FdSlD@@@(@jvM7@A$w23~u}y3Wgprg3C}1ښ/@WZ 9F@@@bڂ?ru~ٱcIgw_9L^      $'߈WQ5Jgp _rͤd@@@@@ r)}@@@@@ 7!     M@@@@@tMm     @b|`@@@@@ ]zS     h)@@@@HWoԆ    $&@71Z F@@@@ 7!     M@@@@@tMm     @b|`@@@@@ ]zS     h)@@@@HWoԆ    $&8;3#==Fgjm]K5Yಶ _1VDL{z}p_fdTmZQ rGjO8H{z^7s>ُs[Jq7av0    @V=0(jor֠I]7)2H#Ӎv8+cĄ NHa9ټսԥM2?0shԖF٬2%2vfdY/S,ʸT/WX    P@OsFbЀ\PtL)u6rdTmm<'k(#swiB6MeIvȽ2v 4r_ c`:6+=V<ΡMVɀH#2!`\ 6'e sڭuC}&N\o.mƠc뭑im"p@@@@ )P֋ك>333gK'>l} dؖΆɼk"Vuhy񶥭endm#AnyۥwK=A>Ykצ5n`NL ڱou Z7.ӿ)D&:-_tgQvs>zj@@@@TB|lĖjUb͔ոNuP6D7 E4pM0y,It#mצZ MAU'͛I{ Jzel*q/CΘRv} L9    |k6j7zQReT/1Sգ&jZاM3pgڥsm]Τpш5&%Lsȇ{Oz>:>[oɬeMV>]6զ]7܃[    ) $#>qI&F[/ZX\-(౹ս2qDjksji^"o럵Ǡ62\qOQa &M0W{B&?o{m }͘]!^}kw^L >#S2`    @_H-_io}yUmfl=vHuhrQƥ"} WlY+mr/,9V{bkl s35+Ryanv,m߿T@zi|tA =WΌ&aǷAqjiHߪz*M'-⤥Aqd-ߟ5     5G^ԄMZpmgh8    P0uO:kV^RY6m@g!koVno }j_ڵ=v]׮?7{۹    .(Pf'K;mz;}sƧhq#@@@@|g I@@@@ș@*m˙ E@@@@r)@7F@@@@@&ۗoa      @LwUi,\yriuR")I@@@HZ`}b<@UQ>ܐA_N:   @nL77 K~{W6@@@@|K9t]*b@@@@| z@@@@@K%_@ TU,   ]e??) |盛C8K% p rW‚+^ 9괭]{-rWBW>O0I9@@@ 7x 0#/x m/_s\w 8Ǚ~W_-?A_Wg=Y&0V65ԃ  h{6 LLL:3',:2E?kWg98a_Z>O6aW?hٟlٲw_yի^%of: Li`Bg6Gz̟ه~u-9=5?jZhWo _WD G\{c*T\5 5gȅv>Yoz^uT*A-~~V:WIbkd``|A<Ƶ._'?1&tuf}⢜2==mH^#/ڎ/}K_d)mJc,@@!vʑҋRDҜ3kk_rylo;I]t):]4ث5=?}K_*FmiA\Ӏ]werJMAgƽhWch4гqFs2kG]ַA{wY=wKnz6٫itf}ٖנs?/o~e`..t'EBb5>G]uҙzZ{{c.wS|A 4`_i}\gz>j)Q5s5SYgj:ʢ4g=G9yӟ.vy ?D/1_5۷fvc%N(6u   @T믿mת\?@j5hH_0jjtрioooC?OO'qҟuY&ػ{~ <)&Բaو%:)2۵O;sjaA5A! Teiq_Js6rJ/ i iݾo4?umMLzu/4Iu=}^g~١#ҙ\`|/4z*?_2OS5hw63jڤL9*hYƚ>s5pO9կ~9T Jp\8Zg?%P_|ߔ&~׿~ٗ?O((=4'q%n6u   @'m,ڠh0IgsY:ۋ5mo{댧 :;T?kW3xu3t?Y 2a E),fu曎.:qԠ/WefWt6sFlmZuA7=~۫3W/Ц?5EglkeiQ\4ˋθ?Nz.?, n3HÖc_i*g<r饗6~5`ͼ~z/. ~zn<kљ_ Hk^hݮS4ܜ{l8 j E&@׋j{ur_dɯMv4^/@@@8|ī o|&(_u6ПjZi.s{ulA:0f-9әO}Sv)z ^i4 t me^tu.gAwq׾֜V;S3_9eX/Am1tf}Ѡέ^(M^ jܸEg6^E/yKLW{}};Evmr1v:  !*V\DI1qݭ,ٰ. 7HrtOgҙaRJ|gDX{-7,QA<V*O{Zf!{:KO/r?[sB34QGe'tYO/|sS[h:V  z^|C??)#֢+Gӟ{8w[7}.xӛp}>{_EEv ﷾-3÷aS_hzg-O / KM s~E mr:%=vqS   m?ꇟ/z8ͣtIb&K&LOYPk&m_IZaj\h 6kW?4^hHgzꩡ뷗u[&O۫`34PP4ն}ѱՙVmccc&@*]zIYaS4ȫ猦q{.'F} YRvm^ u|\gYv;m_YY־n)Eﶯ>񭋕EIi"n΢S699>   @ۀo$]~3e5p|3V{59F2z58pPsI ١Й`k׮5_L1ankG? ([Wr'Cz.XiaQ}뢁n}Աz&MQ3ΐ~3ۭE1ݢ3"5H}\YAʸ(9~\ٳs~ e?`oաiEtVYοcU.L};ˎz?N$ΫN#  " @\jk4[.0'l6iZG> {m-q'xOW14(7thY jI.mW4f| TOu4@AuI@'?Is.W}qנsFU_rә쵾x`iT>.ث}wkY1Ak6qnLԮMocg   @\|cZ[?GdEu<-j/~w j j#rW4aZyur)lg"CJLAME3YX _:?eӺ\mQ_LbSЃOyA׵qGЋcyZ CԈŊwߒ yN+'6h6^o}y;VۧH% J9뮻xKsڟ,:eMqS   PNN;M^|~j|;ϔ5֙3Xm:KWXhyG})_\h}~_W&u։E5 n{K$cjZs!~j>^=.jjʂȈ9bgzN+5_ Y}~IUT̗S{_ޫ؎xz/04单׭P4Ő[Y~&g_;gG@@:( _g?[N:$)NZk*k+]/_jZ?S9ƅڕ?O}S34ҟk^0.k#'Z~hwxvYzT:ךw[tom ֱ?`=Ią^h!k&֭.5;\/WZ45D;/<mjWҜzrt7:\Xs`_oozӛdʕ..j両~ z(/yKZ6{6cBo"EBoSlb}@@@0m@I{>lYjU)>zA_o~ռq|,]l@As!o.Bnd #&ՀG(k@JݴK.+h^~ aiw6-K6zA;ʵ Yu)\ʯ~m"Do~o4jN 9{E~ɡM4рB֔A=hmN/}{}Uq;nYlK3Y  t$6Q]8-KAlT\-C/ަ@  jD i]2@L 2+M  Dx2#]4x_t1Em:7`#X>~^EWd]v"96ǟ48j PWK+"x_3}5kO`>hn$}.fo)OylٲE=\HEҙz>:̹ܷEկ`~a],^>_kY&O2I"K&p@@T_}m *i3Ce'^mݺHWb{gx^8 ^3M^v .Y׼\^nA8rnf$^^ugm}V.K>e߹1[ΖW]_qPZڣA\ iK8-…4p}ǚncm )4>&\ҿ/L;U 5u/ٿx; [}>{^:Wg4g`7olysw{YsO   PZ|1V< O~w%uqќ:Kgcf.â^4qjA/Ц֮]xMя~41EYJ~J^_r"k r'7vg/|kjꍁT ^3}uk@LƢ+_| Fu9#:6ES)f>4{oE5M܋h*hi}uf) ׿nօμSC/+~ v^]@G~Æ 澮֢iMՠ׾5s?AE,)'!  @|u֓XuUΆY<?a\,+Gb9wu;\{C`ݹsh?Y=Ȇ@rP/5 U`dL*g=z|K޿}9]rNggjj z}^i^-M$8.ڦRCzAganϩ7р歷jI 3NA5ث3}L]jm`o)NYlSPOC@@r >09ZC`_g>3~.,@_|@ՙm^rᇛL5Wjrj^ ~4^٫<͵Ȓ5_^j..l~M}E?rn}):+` k.n΀L5m@>9y'rwTGLZ뱥 :[|<6 qZirq.ՙ&{z}2i40NYlScA   /_@y'^x\>`? @ע]8[ iZg,r 8h`Hg^verWtO 뢳6uxW٫'M ^gw73}=0cg F%w3h;_q|hj g-?q2_ MLL.i}[*ǜO;vE^+,xVs=UgwY֗=#E/<Ǣw۶\ξcRNYlF@@:hYZj㧟~\y&57huf{LiA_ws5:~^IsjЂ~Rn@ξ>fq_2=_Nt;kufAȇ&*m7XsW򺐛,$ ׿^~_OS3CU8C5ΌbZ=`iWёE ޱ47y<+Ls2tMvK)mZqV   zqou><asϯ6Jgq{j.I{Wu&\)}MqiIvG tv'^yp:S\_I/twY}@;x)Wdi/僓/KngW9D,C#_8/0h^2rÜ_Z^,MEՂׅ&=++m۶9c U}>N(P6s@u^_~qbe   k~S:ho ?4Hj]+WN:)33{m'A8va8ˏ~?}nY>[/J='>Qtfo`o FQϝ_~hZof̿.Du/暶 _dMiz@@@i: gVE[+pˇ/l8kܶmh־2r iNXM(jQ~iv%ȦM̌r9SX#ܬ}6egh   ]oG#QC}ŗ{G_% ?ʽWtvQ ij]*(#~ 7kJ@@@,K;O@ YCdⴜQǯvkm dW?=6 ! B %@@@Pr8e E[կh=~XKwPG@@@J)@N'p։;@@@@"@JS)     @//@@@@@Rx3Ťt8cR;0 E@@@@ng-\2!쓀m("@@@@@lm[bdNmu)1L'@@@@R09-; IDAT|?=V7KY-kSe{)t@@@@ 15)8Kי, -%#    Pve_ʒR2    eXejR:    eX | c|J+@@@@@@Av3 ]fd ߶    b$"UV22Mjnd:+c[a2Xo`;*X!Ziڱ$W@@@@ ,zV<7"kbK2h HPob1Sd]c2;="s 6ثZ{Jҧ3GeFfh߶e"_hֿ+x\ۣ@@@@',zjY70%Ã~HK2"2X <-#-IeammH#0U -`r{elVf!7\B+l[/VT*GJmԏҘ1\-|\tڙr\+~&sUs?3øYPVs    t&,~Ge\*טq 27"=; Tޕ/q16 ۾̵l!LauoSx_rמ*kκV}a#+^q\{9Ujۅ|Y8 kʻM}\%%lq9Ug.fv@@@@om5sE۩ U K)նSe|~     o3P{6ʈ ܹY ř-2%~3CX/Sn}}ok֬f_w=mr /&?k9q˻m-1н(W~,@sc @@@@X =U/6Ȧсuvնf[犈 67{[%rj[d`|m˝+:v_geC`qrKOK^e9KOΒ.AHsOo\(~DvA@@@@X|C@ՋKO#o Lώ3+zEm[\p y)ny\_E2k-wH6:*3zeuh_2:)\ {KO{3/֋*bS-U]Э') &@@@@HVgV?=rJS@M/(yq7ɪYbvn۶M;J*+ΔKGrre=GUrrouw]_ '\oEM!Fԭ% {wGOlB@@@@k~S|vTMdu6p-NCԖ*q     hwYJsNɰ3CkCt/y"i@@@@#s9 MV:鬵<-$=E@@@@ _k&*W}@@@@@Ssv"O(+@@@@@.9|t^Gv"/+R澗u7    @|֜PI7>%\2    ]     @B<@%p[vѶe{@@@@@ |s1L4@@@@h/@{      a     @{@@@@ȅ\ D@@@@ mo     @*7pCG툏@@@@@x`7J|q      3*A@@@@H@=57VA @@@@@A]+k:ۃo%A@@@@yU *~     @^]~M 6@@@@@ AvAv۝M#>     S98    8:E    ToNf#    NN#    9 Ӂ     SS     @Nth6      -?,    @VWde$h|]X    No#    |]X    No#   @=kZ7k@oN   Z AQ{`zk}VA@ p^   >}pR5^SlU!@|x@@(5= =s\m4L Pl_z  @n,k߶ P뼴39v4jS\g@ -C@@2/P`I^u?r@/W9MDsup,>Fئ{FWc[P-^n^#COpވ`ᘢ -/(oh ?t$~emy)Bbv9/웖Amo'o[{ݾ]w/KRȧ|[V{x\"q~ۖayD:G nu[TT34uymk[jg&]~G  M׻yzjc}*jzTR"+y[[҇Lfv{Lg ֐(Q)[ٹ\"P24?qG%ea] ( u1:B鵾=7I~߶E9'G\t|{bM՝t~#WqG~}e[0nC ^ PTY^TEӢlŽ}]qtΤ.k}S^|:,)lu']~g[z5&mt*Uq^G@S f8ߘYV7nZo?eW9*z)EGthGzyV GEl_q>Q~eDKu']o0nW^*{ِ @v>5Beܫ-^עƲ [{S7ͺoHclҨW{aoි.?xKʽg7ǡu'=afݷ9xk}ܭ'zvy/:sà%`T"@7 3ܲC7L" ~۲b6Qwude,֎4ƫQ ,+J"C~}s.#^l/'m[Q[_b6F=ο5,1Vwy Јl~i{>(ë}֧Qwug't~a_~Ҩïo+Orp[ez J:8&lIet_(>nWZO<-J;s}N"@7/#N=`ڬNͫ^MW9^.߫<ǨJ/^ux"GYq\cэ:<kj.uI(z>L(#L}^1#-[r{]"87 l vIu@qi'CP@(nO ŝRGcZuֱ˭irZfۂv~m>A䥝QL-Q1 x=n㯉&c cf[F '@7=T'İ כ7zݶ+IYtk|UoV,íMn"!EmAQ+39k}QKyhcԅ s@m罏>s|Apس~/nu)mӤӊ:nۺnvM^{#6Ex^+BGep;֕و r[_[ȇ./L]@J,8s[ڞqNϯ>=M^o~yOK(Doa#31[#뱐穭Ys^<be|n>Yc!@7 e[&U_߼|'ƨFigc㢴31cHS[[m޷y =Ü{'@7'cŦmgg6Kk7έ(mrL7zQF,_q˂mg}h_qR*G  4ԯ~bTh?ʋ[vF9&J|S^Y]v^x/4˅߹@^`VгKY8b3,PHOߠL,ԗ&dmTfl@70<&?&LϏ@4+-E(m}^¼Fi3Okk虜q"@]&#RVͿq |db}Ek۪"Ãֶb fzËqF"=3gGDcxǡHAx+8akw嵪;O =b|{dvrػ_dnAuV<7 VɀqD6nPV^! ^[=}cۆ-x=>ֻKҩc^PͲ8b-G¹kU9u-mX%VW_VwmM1zv M]8J-|#EǢPex}v3VxUx΋[\c,g/Sy;ת|*jKxߥ Y_cbb 2g])<͜]zZӮ xzt;< F퍲G1M @?o`_HG`/J#Ãp[j_}m+cF.R|t.]YkGf4e/rG9ߍ~SggYz]9ygG?< (;#=2?(c-Dę!CH۳ P,}Jk簶E6oaG'I ("VC}oa~߱M _`oY70' n")ZmHןnaE|=NNۏzFE\-ڈ)5,  @Xb|gȔUĞwpB+c""ӳaK/p. UNQR:Tb<t<eTfQSP@98@{]v3ÐLV}&eD܍ u +ЍQpk}>%?$T)3nUutZ^y0Ԙ9l[:Ϧ,8}kB#Po~oioL4:Ko´}Ȣ, mB e]>gLnE;W^89)xoqQ⪟r@|J2a]AV  @'^2;% YoG/D;@V oXTX@~G -ϊ@ܯ=YWpFay8y~^@ MԦ.Ko\.nć v&ubx.k͢`@ f??< Cq$${τZEN @ uB^Z++LuDFsS+KI<\V'E$N|93㙥ը}ޣhmh܎Q @|PI0aǟE窼Tv}<)M綢(AȚ߬HS7]|d*{_`g~Fv,sUG 8o[E{hjR @R|Ia@Lr  @x}vh.͖=ZǃmGVQ uY!ڇu@(vC\ D-k4UH [܅> xx=) -s^޺8Wg@ o_Lm뛫9W%y2<9Wr6FkgsAsT03 ps-885) ޘТ. r$me ~|"@aS؁c `r"Zh/̦hX4-O|F y^Ͳ\ 㹼'\o{=3*===tPՌ:leb9h-M`(ĶYk9(wfzxh\'K+P SGK1BqB{lCg7!uIV2> 2/"ђL L˜mKd~d8.RY?y5;, zu̍[mosklcruq\}Cu}Rhdi4m odB<0 鴁dzs=s>HK`F.IauzڼZm 5V n "Cd|`J6Ĩ}d<6`kN Ӈ)iMVmnŤ_ݲ @姳|@ @Rod5,>{Y< 5W[ yeEg|Ca|@uu!6ZnzzZͫj1t\W/{I, zxV=h :/15i,fPoGq^g.Ǝ*!_%5"@YxF?$)'nХgse{_U H+a@ |:r]j7(/"&{ 5#eu8[{xƃU8QJ|p؄@x`3IJ;&TzLvbR4"gmaq~^J_8͉y^gVjۛC 61E6IؖTk [mMk? * s몀k[Mr^& bt?(bhS IS&).tRW҉۱ظȳLV+꘭?mݯ*_7vn+68z,G5\[:fms4&@, 񵪌}9H 07W^f:rۆ-D1Ec,P&mzWJN}_Y]* K[ײ})c<+ysUE8'v[C(-9\\K'c@X1ձ |]Iťm2/"kZnUwy!jnM Gŵs6}.Չ٦shp+8{Ls[ y/IQgS8JSZ]Vtpppx(g& /(-.y}s@ [eyTתRY3fG!]|{Ⱥ9YЫ)Vu Z @|L8#3PX$ɗS]<^uY^xwT:,ۭ 'c*{W_镱i="ӳcқ1Uy1pXE41 YL4b@KyqM?>}yJN|s+ϗ' E4lay  M8,?\ rf 7cIe| b8{{_7R߲'!% %nl  Bq ~( F2cflgB b"c⨏Ϭy1nl ЌW/c5cu&_ru}+sY7|՟^|J~e|/u_=}\UOZ'@=Kx9 B@=" 0I~PWK~(m[-̎_'\?dA  .GGbc{@بDqj`Oa*V4h a V ;6yM"akڮaئAWre"|[ntl}E_?v _kY|^ >)嬎 :Bs賧:s{1 la csÓ{l{0C 0 ց*@PxxF=Os_E6CZ6Wm;ShuQ?x. o!wZw,CD+85q%p=BZ82@ !Pl~aYy qdbsrd8(8|UGDA`?(CFj, ^^v#zHzG]/3n<\?Lvrۮ}f}7> 4#@¿'Z'='M@탻}sP,m6\#K=N0eD %#qlC HBCz&jt 8&H4T߆zFE5,S@R$ @C ; uBaq9YdCc?epMP᐀sHsE>LU##"+YnƳ $$|CF"9&7 s2đ}ADT@ ,riq@+3iwצMMv/w44 =ȑ9Ǩ/'_d @ />'>e% a1u*v|{L@}A'a3Xχ጖b}9$\S+ ^un0ŨA{|y/dnՍd-js//lr5}aPJVٹSr{`E˓_ ma._Z$|g̈́PJÑ!P@\e_ċ*@̶#Xl[پ=,,sV'ݯk*UCuq&GeMeή.Y]oe|)J^|-OﲞʵJD1CR@%o~(}Q$|ӎwr{8 YPॻ+~X˥wJ_2ij>0gD!!{A.#eSe6e_k\Ӄ\}>"!+˭V沒/"׷sՏC2{#?eVoյj*g/8'E%Qt[\V7&ʷ(a 6ɼh쩇&A0 H_gc{h!|:^LmBXl\^3]D @`dӏs,YG&׺ׅ|Nj+a)L#Td-bPHEd~h]g~]XH]P [FkXϺq r_Fm֞{Ul^jsi:qQؽG {^|JnndyG[\(O/qO/)x0;p0ÉE{U` **:N#Am=t2p~-O[ gȼ6E.^e$v?V\޹j[1<=`JO[ٞޟ9fp~Ζ5_&\\rL3= '@s3~B9:@&&y`,X8x&WUΆ@ ,j- 0cGoxH >D@ ܞh_sE!Ѝ nܢ1!-B$uyTXPjXpe $,N,r::h~ymc~5?&& !DF =mBH <fn:C 1$| (@ 'Pm|r"@3h L%$R$~@@ HE|>EçĂ3L@TIu$+1pһUY&@5"/:)-|Nq @ ~Id"+Yn 0\Ũ4*)A]#iĿl>L#Ulyk ?!<g #4?k,vQdy)Fr>\C_(ACHl@;gCyު*nZՏ0c?zC@wi$|/HåOzQf#ݓe<ޖ/m O XQ[$C@ _+?DfExE.Å1|0:!-`JrϹGD;z1!-a)UC6V<-IȈ@t |^R>/2 oY u~'ՄKDE` alrMrW\EP/~.vf1P1Sm @K^<n_.DÃ׼>j% 14C;vx7Wcd\ ;_~r#< ,"R cձQ/0fDm8bH3R$Zb?ocsBKC@@W$|+n߻_p]oL1Q@qH#CV"^L}'rTv!"7=yoD_#x7 +^CH@͵򢶔A @\ UlO&\v+U-*:S"!|/)'ņ1?ܘ/RMp֢ q8 g%c&@CH ߡhgmZًkCc5CA$P4sCjXÆWC!+x}2"^c M)fi3om"\C?skU n n KZf+ߔWU|[$|Dc9rA!|vrL0F $7`@r=0D0H ߄. IDAT+ 13DDl!@eΦW[ܫLřyn @ )\=\,z+kK9 Џ^Q=#Z#P6iwR]RWU%3beW:cא61P벱1m' 2%862%iw;Dp>*IyH@55P1 J$cP]nƃ2n W @ Xe۲`0@ KUaWa`SΆ8 Cq@ EYyncb[0H֐ٶx*Cַ"9)h[Q,S)zMGp)I9}kޔ.+*1Zuyw=O$|#m꾵akۘƶ}N7sa΅dTU4S^NJz!"Ph۾He=nUzV-J>mɨ*-_BGA~hD ՛k_$CC1*bh(eG˼y[$8Q @|'j,;s;>7$@7͸!KO59p@ mFO|++gv>@9g9k9G?=IZ0޲DPUo!4{Pۺ2Ws?wDBw)+>. ];;zBmk&re$dZڃ@h w>C(|.#Gyu5ؕ3!t|@ })U)C@myJJnUu.mE7DpH u!QPck6 )9eNT'Sbu@@HF8̆!IT,_$$y,' )ڬeS`QXcƏ@@s$|zU1.s^ۢ;8҂XIJ'n=IyQ4@ !ikTaD:Z! F0b.0BKYK`=b @$@7z kmJ}_$;aűM|[-}E~x vC# !!:iC'5C=]{bcD #)! ͬw3NZ?|@|HV9CLLL"vSL|)Uc0 0oRAXΪUQ7p 9:lS?/i&$2Cnkj9vNJk5Q5%kJvUGUt-ObQ,v2!s%|_e2ptD&bTq Ė\-[iG]2;~B W?\'^rqS%}$H` /r?.wo27)38=N?l[6s4 HxFB1GF.KKq‚&S_)ZT4p $FU.^ʇ_'O|oOwYC u>>;Vw=!@/$/SY\>u߲6/>ȥymVd/SyHŏd9'ڋsD vR9Iq?* @@ ߍ%"ÏJֲN^:#yn_ׯ񯬭] MuSM۹ I!`G66?$Rc^^= @i^FM $𽐇W3A)v,lRܗ`^/x&5e.Q LYb'>p5G5ykc/Ƙ_Uҫ$RE:I oM`.>l--fE[M૫d @Q7wb!X#%½+rĎo@ D'|E},rsؗwnrn!F᧑3Fv|PzSPN?=8B@cݏ[\s3  $𽖧țy_{8~#$0iwN|I |.~4?\ EoX$A@ D(qpDa=Fcd@ =tLOcG7'@7aa"!'ȁ` z5?dŸ,9 (c?hr$P&sA{Gox1 4})A6;cJMKdwH]mH>4vL_SA*~M+xhB6H ߴ7Ȇ ƃLcGMlMaL638i[ wɏ&B'=B74z`C 'Ʒ|8Z㟾IVa>C5ao=! cEl .(" = @5Np蛟P7Ef,A lM XaMKM[9G`q#$C@hH _hdK pF s]P1b9&[Lj+)>_b@c ;u0.]`eRؗ@߱7 sew\&vƶ\ۏ6#Еmtvm]}R!Al*#@[$!x:8(TTt n s}g?j MI.v !wx{]Ajxyb  UuuCS/>$&?5\M`Jk@Í8C.("#Fȗ |c_9_b9+.2&P<#: Z" 2?N3 bb&;~1F2K>j u)rjC#@C@=y܏T$﹐ O~5QA >$|YNӇ6mL|lFs^grLZ|); @p}%D?\'1hb L8XHE<7N$Mc7|WjR#))GT([NJi[ԟz!I.mb Տ-oȏ ߘH)n1ڔǦM1|A' wNրG;CzD٤e(]HH>; @DgȊ6cֱYO66c."\Y\/bYTv) AܘLʽs_STT^scIy6r<% y8Ξ)]Gx|UHyJ$ެ ̟ݞ=]6kP7"ges dS_>=,>/\E <0>^U78 IzGn EI+E:}Dާ>E& 9w!`4zz3i"Mǧ&@n{ϱY>ըz.g kyz} 'WT}Q/R_FDڗ}|T_1\Ow_E_<ȫt'oy+j۸L>NvdV՝5,4ӗ֕]$;<pj8Err6@ dgU3J3n l%7WE_^ëJ8M}M$ZD}az|q(nt"Z/guʲ,~b*߇/i+"_U-b~-s]ۃbMe/,_urcȨpJ1gPb6+] ɻ־2.c#)};w@k[yHcm#xُTb|jTIVo3YX{Z1ZFD{GYnY[mLQ_kE!㸯.d-q#yA.$lǛL>-:5mk~9[[5s۹OL&2]en|]UwfB-7~ӎ6OiaJHzM3`;';rN'*>9]6sbi(-]x˜lE9ju < T'bd(y ..Y 6痈n~' x*sY ξݖ-OId9~ZnQ[ֲԝLe*{#ǯn8|YjK"5w/O${UFpv_Kkyj,:~ La E\>82q^p%114":,r!PN=Jv.O&1|i  pv ' uOkDֹ<[7l/_~Jr}G7%ӏ2;r滄|_ߞUumL8U_,߬ 6mן&R&8&1IrXZ㒦;Y>+#$ C5ph (5>, ,y*I; _]J\;mnro0n_3{ȶ|XqC{ǼΖSwYg+$|gFdI d@/;͸6#=tMm}Gs8o/Xj_vj?Ky>Zثv#ވ<=zn`U֣}Kkm?ϣ" n+\[@Gepݎ*{\6c׆'c ۪\hW~=Z{1 *EBݶ@nF= dH]EP]$|CK/ iŃ vn  M+md7],v=UzT!m!¦\?]jJj MmKݐ̕YxݯH1 R&_Xw^N]625IzlWg6Lr+?5l0uϯ  xc]x` "tFP(mUMAuZfTsm۶Zؽ'r\7Mlkuv8Ġ)1r:>GI^&Ӆ\>oeEVۻ,?Ent"vS_ɞ IDAT>=,>WSR6l43Jd6/Y27V^.ló&;bnjDS U_0TsyZb`zuNU*vum[ 0'f>$:ט9sb.˷<&T w_?~zeywL8|Z~#o+=ӵ)Z^*-K%_38=~K5^|;ՙjf)"oObq*fv?ϣLTv9ǁh{=ÜTG'C&D۶oԗl_r6D\t2_d6#5N?kU)t C>bPc)ii|;]ZLo\vW'ir4m I[mf5^|KZ~ؓf5Te/k,.U d!7apcg} GYd[$8q#6CVzR|S>藋QbnƁm &>dteʸbO6Gc J  G`5ׅN%c5ۅEMP^Kݭoo*g]bu%7 8˴hZn&:|G~׻^_,_bP|^o}qJXn[0eԮG#]E/o"#W)]Cm/Bc>P:qx=u %|}?* O=/__@HƘc̽5i ;B} ×KJo,;?13j_V ?U^]ξPV%_ b~R?f&_f,c{ .v,\/+=*Qi(vBH~P7"eYӪƑSe8^X %LlUͥucִ*~*4)#4;8d 6kI#ƚ%K÷j/8[ɷisoI]\mU<v{edn oGӏKO&2]\zuōv?䶑巕>RF t7շ$ѲiY,K_c]>9-Trv>c1WݸvLj1b}zf>˵,~5#J+}%$VTfֻ>ҧtӔFG%)}--4گ0eԧl\A(,?oZb{>?sn+K]|<՟?6'm3 XΖ_t]`wo1qTǴGΕSf![5|cm'UcԊ3hjۆt}\ * *h[Qnz0~dk|԰&%s ܱ^q9X6FUE1KCa1b^eҲvh;\i|d8)y}PEfL2ITorDkX!. CḇrL[3mt_n;ntٶC6L[]AVxƠ9fnӶNV2?/Nʯ5 ;} ԍ/4ͽ2?4Bo*<̶ik8;UY@LCٚtPꔿ>^Zrlڮʦآb3m~XY.[&.}U2bYU߲<488% ߜWh @5{B93&r]zJke(@B}7b>cFvU[?yIxɕ,7!ylw3nfyuj)AjN(&qC{oU ;]EGGuoZ2((>rsSSK)Ȃy}eZC1/N`&oׇ:..\[y.?ֆo-qAcaZS4^b(;W.c71*_58ӱ5Y3l/ɰfl뵻"6dP'"T1ĺȇXldyu#+Ybr5^eB%Y;9f)WT^ZYۓ\^+69='@GvW 2p-WM>s64@*5@PZ8\⻫>CW$ʩUuMQ'l|~u}M=n/c\X)'8\E1?L@x'[[٪g^|>lOz|׽=ʯ{zoY؋tM7x6ͶSsü pA\sa2$as`U9sj7 yM?z`|c!P\<|Zo"?V3;fPge-DdSUF{If+QxVp_=}\UN mjfܘ~w5oj%z.\}=>9>wE ]gX_NQiPqsGNW9⊯> \|-զ/?dUT>v/ke%7YbFiS^'CQ! )-lFM! %QC) G%y>dBƐ>+]Ρ@$mf׷ݶ˳lno,;?4)Akt=("O*Y M(&E^ # fP2+Je}8o863!nj{d?8aӆ}&d>O.]vίCZ;*fCί ZڮaئAWre"|[ntl}E_?v _kY|^ >)嬎 :BGI E<ДK̆~.pE.c!MФM~vm\ywSt]/|WRiƙkTO_}ʮE]'T~._^;٦11\˗ǙnԶ"2mvso~ӡ~oL:Li̫cBN}v]%n*w: 4, @ӇBul`8vwb4@ _E9ocx);6 .Hu_k'㉭sq*d#~̿{E޹!r-Ojݏ)UɺK<·B/jA}Q>?QF*a4 UkXU];"D*cg/1>M 4}^l*/vp'cO>lС;]$@w5";C Z|j } k+M1\KIk}ľ91ӽMy7>q^+!~C|~`q;$|5 C 5}9Ft#ЏbߓƄ+ȁ0\>w=Li钴kzF@탻}sP,m4%@\sJ<]?7\Dr95\>raLyN֏ħlW(1c6c0x3Z J9'8@ _~jL12W΁=.vwPu-|E2R} j N󼶣Ckbr65]܉BRr*^Ls֟bi9׸9fRg"Kҽ{< P?f0P= ߀b˅<$8Wcqo$ŭy[ZcZS;cǡ/ױi:6_cׅ1.%#y kB<6y@p_ׇL&ݿFW7,ͽ9Yd"C*Z껷ogNA^Ѯ{v -ODv1J ]fIO@Pr~@2=9r ȏ@.W F_md\9O~,c> [n}{Ym%t/Y2ǷlO_[T&?t+<o7;^~gu,*{-,>e7?z~+*]d_@%o~(}Q$|ӎo/By!B<b0s)R-aznaN+(T!8#0/_ˏ]lM>Okk0DD%Ͼ> _QmaoàC$`8(@Zg84X!?@`̱8؇nØkdlojHaHqFZC$x/*..dGHM<}<=͕8#i6ȁ"V< XMgaMc. H @2 ?aH/%r׸IQ.c#Ũ)8Ɇ]2Î#@[$C";'/?ܰc+qh1m|` ;Ghk.>|**֍V 16!ې9F@ $|ӿ tA3xa >,)r#Uqn/KmcUƍrx6fɹ ֪FkHBHX%@·/Ac/͋=<! \8$T<{qq\w {+{b |G HQF I_d Fb|H4oy7xgqޱ2$Re_ `x964x;Jbx1e0\!m|1b@C0?c_jCl3G\Kdr%ˍR&ˋQũ_M/J@*roü >31xXG:Bأy8i%|UbfeB.ne,rs3lu2>P {`v|@# X; }|#!' %|_~]ޞenFpSgqz(~m8@uSPec>䚜S0*a΅Ck@QH/#@-c# a" $FU.^ʇ_O|@QAtIzb:Hh*J<*̅N]KBLd! LQe5H$ 2'ҩȖgݜe.Y^U{}Y b[f4>zjeX.A BI-"c_$2Pjp@ a _8.^e`ں/Yܾw:[yR[8SQ?J>UZ͇Z@`XIFp$H(#Ӛ̅@yNB 9I99| PG /|;t!dS?ʶU{mk|ko`o^*% 7^p_ <n| PkIůxnkKEGET(˕@ ߚ]|Z~_iS[<> TCF!K5dEξ2)"P˼%&fHDͰAmm/l"y. iH?+ gþv{p(jJyaaHmުu8l3cCyzcs& \PwE}9ؖ&?[kyڿަʶTߙ j@@xJ./=c52'C@ !ץt rHW/uCPqt:$WB[D5cG/k>̅p$@pA -\`r+ <@^^Lh<Ǐ7ќz?4aB@@HX^2`0#<H9RW_*~9 *8b5 & 7fH4I@*ȏ^H%7pQ`M ;|E°-:TPc:jvo IDAT/ M9VH |( N1 0pDMu8a< @[: b% |n@Fƀ+|$rr#- ?줒 #!8(+E84!UJIw/<@`6 @ @ IցXݜtA]@ @ @ $|/LV7>P>S-gȏyt< @ @ Z$|csU沖o\AԒ.$2 @ @ȋ@v ߼‹C-!Y ί!lD @ @pM f)WƦ7Y\n]D PԶ飲\׮6m_>ݾ\צ?e6}tmUe+ȁ @  @d: "Mvv_.os]'^ZT2_Mf[\+.ks4e*9,k#Kӷ.m2Ms]g:T}nֻ:/AmcQ۶z|Z7=/+ruЏ6}>@ @ȇ ߈b]1|_WobgUmTm[k[mWkbWL_ղԵ>t}:Vf_綽ezжk*/*틎}\窏ye)yu[u{Uobme2mmN]ev1*Y1m/ӭl پ2) @ ~H7Ho(PR6ɢڛEe<SeEvy6][n[FSyn76>ƺ¸֦\d3&۴m"nSơ\v.Dzr]l0k6ZV}տzniWfgY1ѴL; @ @ ;D¡i@3me ̫&mJϴW-*u]湖ʴQ l-O\rM|kruuβrWk&}튎UmT-[0uYQ+Se~_]yӧ:E%L~Q @ @> I쾉JC3iV^Q*V^}qʑesEeE*U|4ȯ\X5>2LN:Zlֵa;ek]u2Lչym5eC4>:EqYwȾ/U2y\l*ӌy^[W]v?Nks"yZy}ѬSg׫>v)<&mtPu(vb @  (*eU׫JqeIvRڵ6RNl}Vnm ތy^?V?1}1UQ[eM87gдvU~4ڨ?}m>{*ym5Z&OSeSY1mNlL @ @ $$|FӲr®٨l+c"-k <;C`چٛ\Ze]W56_XG3ڏUf˔mX7[SӾS J4 @E/|PN}f벗jmQ浖3Ѵ6^iL,F1_WH(KŠIC6qU61Ru^v;3m|}}zk}? @ )_l1nM4粝2zO6ac";6W1d_]11}l*.Cܲv&%o֫sݿ^`bUf],/KsPG_Y{Umt2̾C+tA @iGҎ/A@X~.`$۴uaaګtBҴG)*2QM}lnU-ŵυcuغ26r}7er2_! @N /|_e2wR@b#˫m  reĤ>ښr]r׾k=haPm\[r@ @8Ono8}Ҙ?t]ڔ @*ğ 1V6䥙䴓v]ܪvMLyMmu:9j뺾C @~ ę𵙼-\>\5\C !85 AQ죒>7eevԼ6u"Y:Gkc^6!@ $Jf_i[so%{&|(JՍ*WϔReEm*VY,*]Zoy>E_@ B X냜o民D&zR2[ġA B@%(ST۩veQO\7򯌩s@ D ڄM{/>F޼tq)[@Ll @ :j{%dI|Vo#Ƕu>}  @@?vR;6kyn)(` @"aYT6Nf꣭g(ߴ=~e5]WŨ @@~Y@ aGU¶L߮u; @ " @lUvYgC$RM\N̾8B @ $|S">@ %D+ѫR(jWZurR@ TM%@"!`'aյYr]U]NvO̪~cSTهs@ <#x @@e$T׶/Zlkiv[Vnc~}MeVec_@@\M&2SYݕ,7fe?:U ]j^&.m,Wż̅"Eeg T80 E@%V]$&}4UN6e.(m+=e麲zS &"Ӆ\>oe|%7WKuES+!ʼ,nDY6|clY[(yU;BD7H` @H@QNZk IUrt]"uG[}m˵땽v}m ^~Jr{yQf%L>NudG|_t4\>,_X>|@fUH]SbJK͕\yq]J~giSQ%yU]sՑ19j.cK" @:E[]a&rU?IT[}m:L!@IZn*On~~V/>q!*:7AZD} _o/oF'inyҵc?YLeü|;yWy88Wż9{ۣ/#Ny$| @@w:qM5twj5r @ d%?6۹OZL&2]e?ڝ1ZJɣ,dzBV0W_uD>o|;]Z~kcR\IݵV+TOeq,O M8ɫb^UwX鯥W7~C6dH·?C$@ $LN^FQm^۶ky!@h@A^粺9$wIC]۪/aUv+~-kY1aZB=yU̫ _Kkyj,:^(gBpG+ @@DDkٗ:jenkMk9Z1qV@Hv\[Z~Ͼm"{. ~ǯmsaۉ&__#yU{E%k\9R+o}  @ )MfbV%.$/u?-KuN,}TUu?  ]a {Z۟*:XP"|S?v,ewؖagnɱyU][6Ky|{%= _@ ;ZeTk*7sl\Ǯr2ks- {~ײ{_j_zk7"ϯzk8;l/&}Kkm?HxEӃma_W1kjck߫-zh>?_Y\G[׺C D IWd7s_meTҫێuS֩un.mG@pO|{Ḣ_˩o&N#  @JD`YW'blЉW׼M3 IDATy"Q@ Ў_ @C`Dg;u{]tO?@ ·;;zB @w+ >ĬPٸ]  @_ @'MG' Δ=Mf[ܴ:|S6 @ owv @@4꒯#mW\m]ϛ$v/t\ @'@7 @\'>}&9ۦW3Ƕ>T%S^mȥ NE'Wٴ-k?[Nٵoez)Ko_ @@D$rͶC&8M]a:!@Nlr5wTrQRx#+S^fyufj)w[{8ڑ#NX @ $-o#([t]]NcW;7-몓~ ` dl߳7;ރ{Խ])/Edtq)GwAN*5*h#u[W-F XA/)u_pNZgfz"|WǕA:L·o5   C@[!M-kEšeE%a82{k@t'ڐhw;\΁8_\p2>p!#giZQL\&ҳvvm>˫IwYX}x]@d3~]"_/"O_CLp:v3ܗDAWo!  P@\r5nҪ%CIiO8ǵ6B@4b(o]M.گ 7b=lc 6\l>G\u-O]V0a\?\G~h6A2]'I C~n&ṳw1Oe 쿋~?tCAԕ~ [Cp  TC>AZfd6_K|;K2ocsE@ ^m d.o{wdA[_[;ғu2'lk<'s)NwڮVݰ|JJ9NIe+ۜw4!oj q`OHOmeѼ[%U̍O@nnQ`Zr>WHwwDK]n'pN|~Xݕw`o/ ωȤ=bc09z}'-@ﮬ^7$|>Y   G D%8NQ1DSD%1}[6>}.|aK=W1KY0/ pv.N~|~;"7qnypnb*[w> > <`*YqppSHd   H OUĦߧ1kSNk DJp̌W'}rߞߊS)Vr3?gxYxekg6[o./1sG18Xwڱ )3Yten ỔїOWtO^ &\@@ <׼k>f|Kjbknԍ+/;GnN, E-=!"&Å}yXS_r?hm3hH. N~er۸GGtEg~fsBW&m;yk e<]a=נ7"O wp>v)_q?I{@@-`JKDy>oʽ_qE>f˭pEW$P@9kOo[%7W~S_A9ai  "iĵ+/Oۨ! @unhE6C7VܻVՇ^d  DM R Oǖ'~iv}[ pi17w߬Z״U+ZAx'|ׇb喿MD%wz/@@@>YkՕ¸bIAǍ굏DY[.)KU=K0/E "m k###/  dL%)jqkI~ƻ{?nTŐe?VUu1& e ?,O/zCN+ q@@@<QK-*?ODY`1&%7\lSfc5ީ HiTlNt,[}@@*!'Y62omk'gm5EU!8 p-yEIٖܵkҝ2KZ2^u?w N;[j_JJw$|6@@@DimVWkoK.*#2.#^D t{cF9]ARwEix<۝,kx*!H[f   J|0.+.%[, D lfq &< 2lOhi7e}i[Y22ڝA4iB#  dd]&:Ȓ,)}QD;]jW׻{a[&]=hMuޣp1o~ВX݉_ڎK(ӋvKt'U}@@@<Ԥeĥ_^Ŏk;ڵ_.|.6ZFC[h>ٯx)Dzӽ"zvw"1O/m;0h4V3u 1R,"  +&5ǎ}jdmq㒳65\ֱi.%/q ΀U [7C\    XӖPWKfmgQT|캫Azj,PwX xϬ@@8@q1iO\ڽ]C0-cٳ/ =e]W/{^G/@7=@@@nDz=%ŕ6;e6mviv#_͙@@@b IĮᒒm9LZٽ])W?82+" ̤xѲa@@@$0{`:|&D1C ¹pIu pNeYScwqm(n(FB@@@>zJE1csYܤ5["7iKŖ7u %lKsk7;|1   @!5$%A #P>L n6i4*YUbF ܙꟷ4kCW&2AKeEC!J3,inHn[ǹd;l3.mq ODkJ}W{z@@@`KLI~*5U獻?WL̃s?jb(2$t:eXj5s3in]6ڛnb\-d(es\EqͤTWˠIݎ<2F/ȼ(MDG$mMt>5/~@@@,ipZWcKʚZ81>G̽%/sN<~-ÿ^7bB1tbƈ@@@KkRS%46VԔIuCﭟ/1Nc䍛 .w6# ,Otw/em "ݾx.8IړenNs83ew"郝‡=D·o5   ܴOZ2ծXYQW+/[}R5}?ُ&>OXc1N8. 4/tėu밽=ܻX_6J'd sۑZ/Us_2|oI>H?0<`;z'_}n)>}ϪjY?dA,@@@PKjKU6=v0Akq[?vVeʬ/l:]uuU9_gi2:)oq?`    p6 3[slcaO>= @8ҡo@@@(X@> *pa6өIpfW߷XPvG@  P l@@@JXR3.ks<ʹuF!/6F2@@3;o[]ٶlq    h'\$3h=szd Sw6ubؖI7bgo f@@@JQΰM a\tHKq}@6*m>z_ԆMlj{l>}KgoZ@@@@Q s̛6Gq>mi1%8 p?.3m1.Ge",bb@@@8@<Ӵh\0͚M5]Qm%t-F{}T"U T~oL~ ,_նCCvPr$v/"$$q<-5    P@dk\WѺBe0j;wm~IW{O=a"   PR7.zŐ4nT|y %p x%H͗=:2^d{@@@8N LZ5--VbkR2O:8p>$fB@@@4YYqsR5S/\N@@@j*Մ۵,?j_)+E =53!   ꥗R|\@ E-B1@@@@m0)x='\Rl猣js!SHG_@@@@`+Lt׿8};@:ΰ@@@@L 1!@[7z@@@@>ر v`[V׏r"@·*o8@@@@J$]&IG9UH* bA@@@(E@Є]u䆿/%EL=4    \Vvh{w ÷xSFD@@@B'>"$[0(UBx     P@d'4gj{ @@@@|WӒi0EY@@@@s\\R3|/     s4Z BC@@@(Gdp9zyt; @@@@[T @%[BP    yصWu`o*kB@@@@ {E#    @H&@@@@I7Y4    Qo*kB@@@@ {E#    @H&@@@@I7Y4    Qo*kB@@@@ {E#    @jI UK=48|@@@@@MwׄnW&17]jwbR    \@m&sһA     IAL#8!Mz@@@@FK.G<ިWДQa[&~Y/@@@#Ze IDAT@@.|~ugs3sd.~_nI)     P-KVh@@@@@QP#U'e mJiC5     p}wF     @ H @    pe$|n5\{   \ kxKXikK.Zv4+)   TFoe^E Eͮj?Ok f@@@@/J \{B.?|${|Yko̡֘ Ҩ$i5k\yۅY~:GvjOXnv3%^KaN@@@)@'Υ $]о}U1] 1XxKǷ,,A4?:YY_ܺ7_X>[;    P b=DKYrȮ'[Xw2m=[{.jY|iYqY Xq~>5|OYƘee%mn5sY0.   H-ju&X,qC\TKA5_KN3}Okz{7X|\!|NMϥgRiI}/8תy D@@.+LΤxC/eАF?۶YaW+#T>KAX%Zڜg\Oym雵[-o\߷ cuN]͛ΨcUfq5*,u&&$딶aSz}S*ƪeasQ3   E \UwׄnW&1JVϸ 22{tFr/ wFTB"*>MZvaY15֨rO5fic}[o:XYSg_g,m{J߼syw;, XDZ9b򸺨mxjw=Qm?|׸q6nZկCٗ@@@nO&s󞖿eޖֶSNwYm<>Si},]mM:}Kisĕ4qm,}Vg۳^S}oo}^ƈ+i>eaK>ǭ+.fkoK7V@@@J-y;a^>5}77<B/vQɇ?MhATYGT;-;쟥#˞m޷ m5lwcb4F:jYieMC\jv+,Wcal᳍}'ڝbs+1.y_2F@@@MMy~eݞxm~{#!>hrǨD kc2ٗ5,m|{WZߨ2;m,-ëUcZ`eE{ڸ\-,kHkcjs9nθrk6dWkuMju6/Ӳp9_Zy8~MicDztP   9j=j>]m#| ޟ(HK\pi>zMzmc}>P9*ehɺu>X_2n{/Ma׏gp9S c gk6S)sҷu0   @qL~ pxأ쒤?h'ՅqY!,OzN?.j̨QeQ}θˈ/n׫صǪcsX庎K=fn]G~EŮeI5ۅ붱齖z}N1}ΞU1U8@@@* \Uw/eD2h50w鹼2]E"zTľЭ+2}}p+ VjzK($xLYQm5~%5m^;nwuQk񟫨Eeq:_C>EKZGOmއkg|lqmg/5\l+|X#s!   5i1v+Y_;2^$j,ޏU}?ʣi..ֶG7l7lw$KVXQZK[gۯ/ǯڇm GV\^>׼̃  \UF,1;ٜv89Z&X6ƥ>p}g9*]5Ƹwt W2.uLR~-kRL,%ťuVoפ^u a;>1'V?9m>fi{jGΑe}Y;),_òSG>t06d]_ط$cu}쾬؎7..[Cڸqzo꭬̫'Gc*j3   p$|/֣}0bu8L<+UV쬌gW~-b])ngՓ}gkMgmaWGK,0g gz|;@@@"8ҡHPk2Y 57ږrڽѮEƲkԘ6TepnEK@@(VoMSVlQXW %VfcC}8^Za5Xx@@ 3Y3MY4IR&dP@wե}eɽŔTT(o]%m|.8IuVcNT}gs<   p[$|Kz:ê4-"\P L>${/}U4f+ӫu^}Zn}|u _T猁@@@6ҶxϬ*cc+ϝ'mq>^-GDvvj15kݱ1@@@+F{@R&0-}ʴgNKjǕW~6jccVn*תU@@@">@XK6HE8-cyi%ޮӺy|<:ر'c&ek?f\   {>kfB@`'P&0II݂bn>ye.,c`D4C@@2$|*@}P @LIIZM&GM}E%3}-2 ڶQqe<#  @8ҡ@j&p ɾ$g\Kגiش5bӮQ ˨_k?E+j}q~.@@Fz$|;cYVg!öH{'_ɸ@Kձ$>'=1kOkcpE@@ g?d0ɷfX3  )̌pBM`ZՒv C;,p"֖e촾iY   Uaw)i;u8|@(3ٚ'2HJFEºqE@@Z)ϯöL2ZF[R TK LsXvϑHs}֎+  uYw&Dz^šߤ'sy_YD;@@I\TWuJ$uIK  uUw9.PX  paV}r+D-YaWY1Y׬cj;:=  m (;=W-G]''$oj@@2- &.9\>/|۰˭o\[SYLZaSc? +0~#<.T5?ةw忢uRFhs f}I6∲*;t$|gn'tm e?o@@hbd *,$6ήa"7/ybz?  PIʮL)7;*t1|+fo ~9:tڛH8UcOޛ5-ȼ(Iuh>vuCi{\oHk@@8դde37-rK$WoΙQh  ,GTN2=1w&u2v;q22.o)&1]M~v$ꓜg׫ƽ[a[&踳8-OcTwĚt7rwғ;a B·PNC@VW1Kgc5]X:|[,v֏+ ) Z.H;^g1o5I{D9U|/\Z~\A:Ľ}?2F5j_N;drmmv7寡=(pz=W^/?\b>)T8=88>䏳D  \@ܴjTSڝ{6{B#[sc6\@x%qD#*ms}l\mh)E Zu :NDNl\a}Xi~|8D$$1`͙@)M+XKQ1lWT;@@`qnB@@ 9IsX}VgϹ8[@@3 L  POSyTtSYC\۬qƢ@@ ;|@@&0$Osj  YgYIi]!)Twca 1@C2Z~|.ylpǏ8q2#  P#<\ N?k?1' Xѐ2DrЯ/M/eАHRs«cu| @@;aۤ]j7b0{tM~3w)|4??iw{CG{syQ:e,f3+"@@@.'`a -3/nM%hXy~%}}" P۩\|-ïmG\u:)ۓoj<'s,U{7l&m0m̋wOrc.ݸ2&ee sg3gIm@@rX23KvidD3)a᳕_ZŘ. @u4v&Fm]{ubu"q-dZO]O:Kp͗?7_Y~ND&m2xƉe;_ehI9CܸNV$|k:Y   F8uT QeLQIL_ ~> sRUR̋T^`S&u7B= RwfXr35 iwkJo)ڢ 9 sAkx ߃'|, @@ȓdE?5iԹ(c.Á1@J wĺ:69vww%nQ{oL+NҶ<[rn3?g`u,^;Uݶ~?BmO^7;sx}ž$+YMEi+~  @4'wnjo ^MZlv;㒺qe )gk(2h56to2\esoS_r?hξm܉<83~6]o]n_Wd3kyW&]Wln)i߅3lw~&7J۸ 0XA@@XB*J' C|28MeQYŕ!dx"6Y_^ۭdhŻk\v6?UvQqw+Y/DEzt=׷M4$I |;|eg@@j&'6<*Oۨ! p;Uth׸w-Icxh4"XF   TF@6)K%<->[X'>}[ pi(lU,ICc Lۘl/~+qJ a{oMw;=_   PM 5b~TZYQ$Š~qmʬoӥߥ\"?o"x"#9m,wiлُP*@@ UZ{%)jqkI~ƻ{?nTŐe?VUu1& e ?,O/zCN;f|@@(W *qeQFr8z,Ƥf\돍q8{'G;^" p{?A[o4ds:o鸽1+F@@z$+ƕ)T5/># HwrGƫX:y@@@<5O#}bg雵WYYgv @}foR˫Fn"  diI, ,mX}x li?sf5K \B-Åm\_@4ts%E7%M%   p%bӒVILKdZ0ky:Qf[|9 @2zD2h.lvnW>KcCvx=h';oH Il=j9/owƯv/@@@>QQayT_T}2#.qs5S9xZoQm~wXvԖ˯i?}ڹ 7ǟN{2|I P޺}IbxyI>FR&$|nY  TXU 1)Tk^u+S9겎s o%gNM7iAm[:ғ/DdK^=fh=q泼V2N,u?w#86[&["c   W,LvoW[ndg_Mx mտ*PZM#衷21ےvmV&}ZKSmIuyg}KWK1V鎄o   ȚhmR2jz%ʈ̱ˈ1@Xq~|Q*uo8^ϭ;iv'tƚ,JoaY#   pF&ˊKi29@fG3z@wLUwJOXW'}ZY}wE,zs| O] 4!@@@,iWmN$/zJ߬sNn." t-`_:HQugvdo7_v?hIc{C/Ossm|%tWEZ% R'V^ua @@@<Ԥeĥ_^Ŏk;ڵ_.|.6ZFC[h>ٯ|)Dzӽ"zvw"1O/m;0h4V3u 1R,"  QѼc>.Yu䬍k ןul! ,|{\Ci0pHV   p%T)k1%o>ՒYYO8h#01ngRY7   P@\"3 &&S}b6.VK] a=x=w5scszo/C@@"Pe\LZvoLX>iqsYzkW˞@ {=@@@j*`M؍Iտ2SǶ{4v_};@.'@ř   paMX ؤ$fTp Iö&Qޮ攫[aWn\@ ̤x|3Vy&U~;Ć   p@=i u>CM}R~:ߎ{Ovsr1e67#!   P=@=%±DnҚ-4bK:%l2/9w{@@@dvפf=rʣX䄎jKc[Ř,6 ;S~ԗFy؝_`2zD2hi'<-GhH?R5K&Ҿq'َ7̻kf=vuZ"cb랄o'A@@(H W0i1YrӮQ&E*1|89߹lvy p\Zd ~ ݦl\QZYR&S8ܜ]r/6蘆kՒUMW4,C<ٍq iO&QYD¢z$|s8쬐j^g@@@"4Q?qI~ƍeIՅ>>6_*c̨y(C;mueV>^MԖϙqyKXDbXߘkg=fBo1ݯ _g,di?AYקm[H   ,`IVMJbjz\|{?[?_/b"7]2nR# ,Otw/em "ݾx.8IړenNs83ew"郝‡=To&f?d0ɷ{xF@@@>jTZuչ±'UڇQme:F@@S"OG|XG νuil}Ki;`xiR5%sg֛\.g7~`yv="O<]QJ2>pqMzN_[ +   @MLD>}YؽYt@oUW gZHUVm?nmI ;+yMە=}JJJV7w}c :%uX5~蹼b;w^ 9    PMJO‰ [MPcW+Qm)CE UOmI;mDĝԯvcA@@@:M$b,A4IpfW߷.Yw%cgn8%|hևYpO@   5f}3ͥ$7kt@/PL~ |x~E6pؓGs=   g$OfIfƵr?q5_:|%3 P/m2ie&r^оMz2]P)C    @F$OzZrʲ$z Cr{cƶ1"e f^ݽk5y+e}@@@BטD1^b :X1W6Sˢ|qYem7 p}I^=#   P1r#=Ob2)!?C|M3EME۸Wm]؏g~Y   W-&\a^pD𖜵oq}@Hf   TZ *YˌK m{N[wos {YfG@@@%=D楁,5%1[Oʘ1@|$|gL    Psd&\ޮeqQs2OYq0._͙@@@j,^fTJ]Ggs1)@·HMB@@@H-x='IhdoTYtoJ jB@@@+HJ^: G'z@@@@a25||D"[yӬ@@@A;qiq(Gj$|F@@@@K5nPk\;@@@@(;^C Zn?:?j2:!Px     P%q3_-E+    @n=K" `ptC@@@@d'戨(EI2    E|WӒi] #p #    P=Mo"$"„L-=RF i4mHvu}b?    Ф/w.YE~J$fJVϸ 22{tFr/b@@@@z d5*k2w*/Yy[Z&;ie߃@@@@+rf-p8Ji+tG:sXwOMM~׃p   \vx L.G<(h#     PIJ&| px(~FFD@@@@-Pr$L'i~v;p;78!    e \Uw/eD2h50w鹼^hWDuEϒ󔈲@@@@(LF:@JV㨉:2^$j<>jL@@@@@EK     yHכ@@@@@HF     yHכ@@@@@HF     yHכ@@@@@HF     yHכ@@@@@HF     yHכ@@@@@(md>YO@@@@BW`.I@@@@ ˸3+     P I@@@@ ˸3+     P I@@@@ ˸3+     P I@@@@ ˸3+     P I@@@@ ˸3+     /Vv&    Q .W $@@@@@39k$|J@@@@(Xђv _kpC7*@@@@@l=%٫q-m1>     "4|N龫&ợ@@@@%yzL$$|Q     P)^ o /!@@@@@K:s"    %-!@@@@@K:s"    %-!@@@@@K:s"    %Q˜hjݺXy׻γY=Ϻ3Y>ǹ9>,ϚE?e÷tb&@@@@@#5p^IDAT@<̂    .@·tb&@@@@@#@<̂    .@·tb&@@@@@#@7jЊ&$ 9J6VsoCM>>Kh-(څ||y:^R 5 p$|=%     *@7     uD     @ T"     !@:Q"    $|Sh    \ xOD     M%i42Ў&7,C!Oe)k-o؍Yv4F#Mi{,Zd&߯ iI9 ;iI7Vs$"7!IY1_eܥL5 pNWS. Rd)/dZIeK^v,"/$nq9>KY]~Y|fo5M>/ 5֕Ir3oy[ӭgmzTƝ[c^ o6dY@߯j/@Hfya;ie-mnO@ܵKO4}bW$K}Ho:Oz5y>G2覕X|@68#|ad P}ћn|:Z21~%aw{g,mzozsU?G7‚%&Ҿ皗y!0{[=Vё\]_/2=ۗz߯* ᛅIm ,eW=]N SG|mDz2o#<# 2IIˑ|̥cfnMy~>-.w{5g!-UGc-E!FoOmnS`0qKyi>n>p#p{?KngQz$ns<#kSt:'2lΔB FoғsGJ ۺo2:59A<حխy֍]b%sގ@xC:15V%~b>KyuQ#SvK?GJHr5퉴xpK"תbޕB^+E2XMO)8!xM^2KDHf4p]l,OmҰUg}[Z)Fr6?7QYڶ}~r]&p5>e!sE;&5|o}@,bϑ{KCō w_PzX,?ೄ p$|3FWd9tn77yiɛ[)vgF?5YMAk}tKo1 Iao4HtvË<-V5-wGW&_ԐH"vPo~FӦf?G=5 2]{[>G/'(8Hw࿑v]ǜ_e! 4WS>}tk!~@@@@@~-k%b@@@@@$|vY    ܔ ߛz,@@@@,@·o!    M b@@@@@$|vY    ܔ ߛz,@@@@,GW5nW1!    知%߲d@@@@8 33   w$i;fIds1 /0b pA6^)YӠLn'DvUUM @P @ @O, #@ @ @<@ٛIV5vA @ r5Oo÷5p)R @ @@A醼4wSPxao˒0I @ @C դ9=BjJ$|\F@ 9 @ @@Ai&^G% r7ƱGHM  @ @ nҜ HF @ @'HiN +O" 'szHo{՜ @ @ 4gr / -`9Ez)  @ @{4GHM oA˓0IA!@ @Q ѤèNE Eq dx @ @yUm#;|} @ @ p"'A @ @ _ @ @,i @ @ @C۞;p~~L= @ @Sbe-jB @ @p @ @ Lv @ @^ OO߳  @ @ @PG:) @ @O@L @ @B$|  @ @ 'E1% @ @^\w&@ @ @$|OpQM @ @) :ݬ  @ @8A \TS"@ @ @u Hu7k @ @ܔt9q iT*E{un*V}Vƙ{58n&+Pwu3Yݣ[5;,;^3 @ @ dɻʲDa9\b0 q6i|R1lQFDƛI|툯ǔsjH/G-֨֞o>e L·0J @ @l/п}7OSiMӺK7jVSQ:ڍ;Uw47^m4:7Dz;jKzܴFoKZ# N @ D\Uo: ipG"t Fd]Dxݳ+o㪴ϰQ8E;|3G 8F'>5Q6Ϳ{V-訊lfw5T>5gD,3XFqي|{5Bw??  @ @@ K\Go|4BM4f<<:]F,[}vV/[kQd뺸+iƗn%."K I"vSL೨]u:ΧFtko;~f!3t]be.:in_zXd$9C|gG|Hʸוq׶ ggy,M?LQ*vו<\tqg\ȎĘ~ek>`ۮQ6heEl|\HQD @ Rjǐ&'/]]z%O֢Lv6y|A zxfK'w~%×VNܔJsllezy]|Gǰcv6K1/ @ @e 웠\x)1jT>b7]Kڎn|,)|t-c6lEkegVd;׬ zg}ڕo @ @ CfP'8E&@19wmaaR &gueAkwшf*n(Oc_ZE59!խ/g%)GxTB:l7٫9%Җ.mK7[Ou͗;7HwƆ5`฻4s5v"@ @ pCң`+5vVo5,ً*G󇠕>jCΓ/z*ʥҨqvDtGi#JM%.!;x sϓWY^\&Y{'gr)rѬ] 5; =~6CcZ{{_ @ @PsS?'V7=U7> @ @ȏtvܞnQli\g  @ @^@TJ~AgJh>' @ @ dZ>J#Y @ @ @ dg:  @ @ @~CC @ @/[Ǿ9& %IENDB`sigviewer-0.6.4/sigviewer.pro000066400000000000000000000036351345753661000162740ustar00rootroot00000000000000TEMPLATE = app DESTDIR = bin TARGET = sigviewer VERSION_MAJOR = 0 VERSION_MINOR = 6 VERSION_BUILD = 4 DEFINES += \ "VERSION_MAJOR=$$VERSION_MAJOR" \ "VERSION_MINOR=$$VERSION_MINOR" \ "VERSION_BUILD=$$VERSION_BUILD" QT += core gui widgets xml BUILD_DIR = $$PWD/tmp TARGET_DIR = $$PWD/bin CONFIG(debug, debug|release) { DEFINES -= QT_NO_DEBUG_OUTPUT DESTDIR = $$TARGET_DIR/debug OBJECTS_DIR = $$BUILD_DIR/debug MOC_DIR = $$BUILD_DIR/debug RCC_DIR = $$BUILD_DIR/debug UI_DIR = $$BUILD_DIR/debug } CONFIG(release, debug|release) { DEFINES += QT_NO_DEBUG_OUTPUT DESTDIR = $$TARGET_DIR/release OBJECTS_DIR = $$BUILD_DIR/release MOC_DIR = $$BUILD_DIR/release RCC_DIR = $$BUILD_DIR/release UI_DIR = $$BUILD_DIR/release } CONFIG += warn_on link_prl qt thread c++11 macx { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 LIBS += -liconv } INCLUDEPATH += \ $$PWD/external/include \ $$PWD/src LIBS += \ -L$$PWD/external/lib \ -lbiosig -lxdf RESOURCES = $$PWD/src/src.qrc win32:RC_FILE = $$PWD/src/src.rc ICON = $$PWD/src/sigviewer.icns TRANSLATIONS += \ $$PWD/src/translations/sigviewer_de.ts \ $$PWD/src/translations/sigviewer_en.ts include($$PWD/src/base/base.pri) include($$PWD/src/signal_processing/signal_processing.pri) include($$PWD/src/file_handling_impl/file_handling_impl.pri) include($$PWD/src/file_handling/file_handling.pri) include($$PWD/src/gui/gui.pri) include($$PWD/src/gui_impl/gui_impl.pri) include($$PWD/src/editing_commands/editing_commands.pri) include($$PWD/src/commands/commands.pri) include($$PWD/src/tests/tests.pri) HEADERS += \ $$PWD/src/application_context_impl.h \ $$PWD/src/command_executer.h \ $$PWD/src/file_context.h \ $$PWD/src/tab_context.h SOURCES += \ $$PWD/src/main.cpp \ $$PWD/src/application_context_impl.cpp \ $$PWD/src/file_context.cpp \ $$PWD/src/tab_context.cpp QMAKE_CFLAGS += -std=c99 sigviewer-0.6.4/sigviewer.svg000066400000000000000000002122621345753661000162710ustar00rootroot00000000000000 image/svg+xml sigviewer-0.6.4/src/000077500000000000000000000000001345753661000143265ustar00rootroot00000000000000sigviewer-0.6.4/src/application_context_impl.cpp000066400000000000000000000112351345753661000221240ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "application_context_impl.h" #include "base/exception.h" #include "gui_impl/main_window_model_impl.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QSharedPointer ApplicationContextImpl::getInstance (bool cleanup) { static QSharedPointer instance (new ApplicationContextImpl); if (cleanup) instance.clear(); if (instance.isNull ()) { instance = QSharedPointer (new ApplicationContextImpl); qDebug () << "ApplicationContextImpl::getInstance() created new instance = " << instance.data(); } return instance; } //------------------------------------------------------------------------- void ApplicationContextImpl::init (std::set activated_modes) { qDebug () << "ApplicationContextImpl::init() instance = " << getInstance(); getInstance()->activated_modes_ = activated_modes; getInstance()->setState (APP_STATE_NO_FILE_OPEN); if (activated_modes.count (APPLICATION_NON_GUI_MODE) == 0) { getInstance()->color_manager_ = QSharedPointer (new ColorManager); getInstance()->main_window_model_ = QSharedPointer (new MainWindowModelImpl (getInstance())); } } //------------------------------------------------------------------------- void ApplicationContextImpl::cleanup () { qDebug () << "ApplicationContextImpl::cleanup()"; getInstance (true); } //----------------------------------------------------------------------------- ApplicationContextImpl::~ApplicationContextImpl () { qDebug () << "deleting ApplicationContextImpl"; } //------------------------------------------------------------------------- bool ApplicationContextImpl::modeActivated (ApplicationMode mode) const { return activated_modes_.count (mode) > 0; } //------------------------------------------------------------------------- QSharedPointer ApplicationContextImpl::getCurrentFileContext () { return current_file_context_; } //------------------------------------------------------------------------- void ApplicationContextImpl::setCurrentTabContext (QSharedPointer tab_context) { if (!current_tab_context_.isNull()) current_tab_context_->disconnect (this); current_tab_context_ = tab_context; if (!connect (current_tab_context_.data(), SIGNAL(selectionStateChanged(TabSelectionState)), SIGNAL(currentTabSelectionStateChanged(TabSelectionState)))) throw (Exception ("ApplicationContext::setCurrentTabContext failed to connect to selectionStateChanged")); if (!connect (current_tab_context_.data(), SIGNAL(editStateChanged(TabEditState)), SIGNAL(currentTabEditStateChanged(TabEditState)))) throw (Exception ("ApplicationContext::setCurrentTabContext failed to connect to editStateChanged")); } //------------------------------------------------------------------------- QSharedPointer ApplicationContextImpl::getCurrentCommandExecuter () { return current_tab_context_; } //------------------------------------------------------------------------- void ApplicationContextImpl::addFileContext (QSharedPointerfile_context) { current_file_context_ = file_context; if (!connect (current_file_context_.data(), SIGNAL(stateChanged(FileState)), SIGNAL(currentFileStateChanged(FileState)))) throw (Exception ("ApplicationContext::addFileContext faild to connect stateChanged(FileState)")); setState (APP_STATE_FILE_OPEN); } //------------------------------------------------------------------------- void ApplicationContextImpl::removeCurrentFileContext () { if (!current_file_context_.isNull()) current_file_context_->disconnect (); current_file_context_ = QSharedPointer (0); setState (APP_STATE_NO_FILE_OPEN); } //----------------------------------------------------------------------------- QSharedPointer ApplicationContextImpl::getMainWindowModel () { return main_window_model_; } //------------------------------------------------------------------------- QSharedPointer ApplicationContextImpl::getEventColorManager () { return color_manager_; } //----------------------------------------------------------------------------- void ApplicationContextImpl::setState (ApplicationState state) { qDebug () << "ApplicationContextImpl::setState " << state << "; this = " << this; state_ = state; emit stateChanged (state_); } } sigviewer-0.6.4/src/application_context_impl.h000066400000000000000000000060141345753661000215700ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef APPLICATION_CONTEXT_IMPL_H #define APPLICATION_CONTEXT_IMPL_H #include "base/application_states.h" #include "gui/application_context.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// ApplicationContext /// /// exists once in an application class ApplicationContextImpl : public QObject, public ApplicationContext { Q_OBJECT public: //------------------------------------------------------------------------- static QSharedPointer getInstance (bool cleanup = false); //------------------------------------------------------------------------- static void init (std::set activated_modes); //------------------------------------------------------------------------- static void cleanup (); //------------------------------------------------------------------------- ApplicationContextImpl () {} virtual ~ApplicationContextImpl (); //------------------------------------------------------------------------- virtual bool modeActivated (ApplicationMode mode) const; //------------------------------------------------------------------------- virtual QSharedPointer getCurrentFileContext (); //------------------------------------------------------------------------- virtual void setCurrentTabContext (QSharedPointer tab_context); //------------------------------------------------------------------------- virtual QSharedPointer getCurrentCommandExecuter (); //------------------------------------------------------------------------- /// NO MULTI-FILE SUPPORT IMPLEMENTED YET!!! /// THIS CALL WILL REPLACE ACTUAL FILE CONTEXT virtual void addFileContext (QSharedPointer file_context); //------------------------------------------------------------------------- virtual void removeCurrentFileContext (); //------------------------------------------------------------------------- virtual QSharedPointer getMainWindowModel (); //------------------------------------------------------------------------- virtual QSharedPointer getEventColorManager (); QSharedPointer color_manager_; signals: void stateChanged (ApplicationState state); void currentFileStateChanged (FileState state); void currentTabSelectionStateChanged (TabSelectionState state); void currentTabEditStateChanged (TabEditState state); private: void setState (ApplicationState state); std::set activated_modes_; QSharedPointer main_window_model_; QSharedPointer current_file_context_; QSharedPointer current_tab_context_; ApplicationState state_; }; } #endif // APPLICATION_CONTEXT_IMPL_H sigviewer-0.6.4/src/base/000077500000000000000000000000001345753661000152405ustar00rootroot00000000000000sigviewer-0.6.4/src/base/application_states.h000066400000000000000000000005271345753661000213030ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef APPLICATION_STATES_H #define APPLICATION_STATES_H namespace sigviewer { enum ApplicationState { APP_STATE_NO_FILE_OPEN, APP_STATE_FILE_OPEN }; } #endif // APPLICATION_STATES_H sigviewer-0.6.4/src/base/base.pri000066400000000000000000000007341345753661000166720ustar00rootroot00000000000000HEADERS += \ $$PWD/application_states.h \ $$PWD/data_block.h \ $$PWD/exception.h \ $$PWD/file_states.h \ $$PWD/fixed_data_block.h \ $$PWD/math_utils.h \ $$PWD/signal_channel.h \ $$PWD/signal_event.h \ $$PWD/sigviewer_user_types.h \ $$PWD/tab_states.h SOURCES += \ $$PWD/data_block.cpp \ $$PWD/exception.cpp \ $$PWD/fixed_data_block.cpp \ $$PWD/math_utils.cpp \ $$PWD/signal_channel.cpp \ $$PWD/signal_event.cpp sigviewer-0.6.4/src/base/data_block.cpp000066400000000000000000000044101345753661000200260ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "data_block.h" #include "signal_processing/FFTReal.h" #include #include #include namespace sigviewer { size_t DataBlock::instance_count_ = 0; //----------------------------------------------------------------------------- DataBlock::DataBlock (size_t length, float64 sample_rate_per_unit) : length_ (length), sample_rate_per_unit_ (sample_rate_per_unit) { instance_count_++; } //----------------------------------------------------------------------------- DataBlock::DataBlock (DataBlock const& src, size_t new_length) : length_ (new_length), sample_rate_per_unit_ (src.sample_rate_per_unit_), label_ (src.label_) { } //------------------------------------------------------------------------- DataBlock::~DataBlock () { instance_count_--; // qDebug () << "DataBlock::instance_count_ = " << instance_count_ << " deleting"; } //----------------------------------------------------------------------------- size_t DataBlock::size () const { return length_; } //------------------------------------------------------------------------- std::string DataBlock::getLabel () const { return label_; } //------------------------------------------------------------------------- void DataBlock::setLabel (std::string const &label) { label_ = label; } //------------------------------------------------------------------------- void DataBlock::setXUnitLabel (std::string const &unit_label) { x_unit_label_ = unit_label; } //------------------------------------------------------------------------- std::string DataBlock::getXUnitLabel () const { return x_unit_label_; } //------------------------------------------------------------------------- void DataBlock::setYUnitLabel (std::string const &unit_label) { y_unit_label_ = unit_label; } //------------------------------------------------------------------------- std::string DataBlock::getYUnitLabel () const { return y_unit_label_; } //------------------------------------------------------------------------- float64 DataBlock::getSampleRatePerUnit () const { return sample_rate_per_unit_; } } sigviewer-0.6.4/src/base/data_block.h000066400000000000000000000051161345753661000174770ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef DATA_BLOCK_H #define DATA_BLOCK_H #include "sigviewer_user_types.h" #include #include namespace sigviewer { //------------------------------------------------------------------------- /// DataBlock /// /// basic class to store channel data and sections of it class DataBlock { public: //------------------------------------------------------------------------- virtual ~DataBlock (); //------------------------------------------------------------------------- virtual QSharedPointer createSubBlock(size_t start, size_t length) const = 0; //------------------------------------------------------------------------- virtual float32 const& operator[] (size_t index) const = 0; //------------------------------------------------------------------------- virtual float32 getMin () const = 0; //------------------------------------------------------------------------- virtual float32 getMax () const = 0; //------------------------------------------------------------------------- /// length of the block size_t size () const; //------------------------------------------------------------------------- std::string getLabel () const; //------------------------------------------------------------------------- void setLabel (std::string const &label); //------------------------------------------------------------------------- /// sets the x-unit label (e.g. "hz" or "s") void setXUnitLabel (std::string const &unit_label); //------------------------------------------------------------------------- std::string getXUnitLabel () const; //------------------------------------------------------------------------- /// sets the y-unit label (e.g. "hz" or "s") void setYUnitLabel (std::string const &unit_label); //------------------------------------------------------------------------- std::string getYUnitLabel () const; //------------------------------------------------------------------------- float64 getSampleRatePerUnit () const; protected: // protected constructors here: DataBlock (size_t length, float64 sample_rate_per_unit); DataBlock (DataBlock const& src, size_t new_length); private: size_t length_; float64 sample_rate_per_unit_; std::string label_; std::string x_unit_label_; std::string y_unit_label_; static size_t instance_count_; }; } #endif // DATA_BLOCK_H sigviewer-0.6.4/src/base/exception.cpp000066400000000000000000000010351345753661000177410ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "exception.h" namespace sigviewer { //----------------------------------------------------------------------------- Exception::Exception (std::string const& what) throw () : what_ (what) { // nothing to do here } //----------------------------------------------------------------------------- const char* Exception::what() const throw() { return what_.c_str (); } } sigviewer-0.6.4/src/base/exception.h000066400000000000000000000007611345753661000174130ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EXCEPTION_H #define EXCEPTION_H #include #include namespace sigviewer { class Exception : public std::exception { public: Exception (std::string const& what) throw (); virtual ~Exception () throw () {} virtual const char* what() const throw(); private: std::string what_; }; } #endif // EXCEPTION_H sigviewer-0.6.4/src/base/file_states.h000066400000000000000000000004351345753661000177150ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_STATES_H #define FILE_STATES_H enum FileState { FILE_STATE_UNCHANGED, FILE_STATE_CHANGED }; #endif // FILE_STATES_H sigviewer-0.6.4/src/base/fixed_data_block.cpp000066400000000000000000000166651345753661000212240ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "fixed_data_block.h" #include "signal_processing/FFTReal.h" #include #include namespace sigviewer { //------------------------------------------------------------------------------------------------- FixedDataBlock::FixedDataBlock (QSharedPointer > data, float64 sample_rate_per_unit) : DataBlock (data->size(), sample_rate_per_unit), data_ (data), start_index_ (0) { // nothing to do here } //--------------------------------------------------------------------------------------------- FixedDataBlock::FixedDataBlock (FixedDataBlock const& base, size_t new_start, size_t new_length) : DataBlock (base, new_length), data_ (base.data_), start_index_ (new_start) { // nothing to do here } //------------------------------------------------------------------------- QSharedPointer FixedDataBlock::createSubBlock (size_t start, size_t length) const { return QSharedPointer (new FixedDataBlock (*this, start, length)); } //------------------------------------------------------------------------------------------------- float32 const& FixedDataBlock::operator[] (size_t index) const { return data_->at(start_index_ + index); } //------------------------------------------------------------------------------------------------- //! Get the minimal value in a data block, excluding any NANs float32 FixedDataBlock::getMin () const { float32 min = 0; for (auto const elem : *data_) { if (!std::isnan(elem)) { min = elem; break; } } for (auto const elem : *data_) { if (!std::isnan(elem)) { if (elem < min) min = elem; } } return min; } //------------------------------------------------------------------------------------------------- //! Get the maximal value in a data block, excluding any NANs float32 FixedDataBlock::getMax () const { float32 max = 0; for (auto const elem : *data_) { if (!std::isnan(elem)) { max = elem; break; } } for (auto const elem : *data_) { if (!std::isnan(elem)) { if (elem > max) max = elem; } } return max; } //----------------------------------------------------------------------------- QSharedPointer FixedDataBlock::createPowerSpectrum (QSharedPointer data_block) { size_t num_samples = data_block->size(); unsigned fft_samples = 1; while (fft_samples < num_samples) fft_samples *= 2; FFTReal::flt_t* in = new FFTReal::flt_t [fft_samples]; FFTReal::flt_t* out = new FFTReal::flt_t [fft_samples]; double factor = 0; for (size_t x = 0; x < fft_samples; x++) { if (((x < ((fft_samples - num_samples)) / 2) || (x > (fft_samples - (((fft_samples - num_samples) / 2)))))) in[x] = 0; else { if (x * 2 < fft_samples) factor += (2.0 / num_samples); else factor -= (2.0 / num_samples); in[x] = (*data_block)[x-((fft_samples - num_samples) / 2)] * factor; } } FFTReal fft_object (fft_samples); fft_object.do_fft(out, in); fft_object.rescale (out); QSharedPointer > spectrum_data (new QVector); for (size_t index = 0; index < (fft_samples / 2) ; index++) { spectrum_data->push_back (log10(pow(out[index], 2) + pow(out[(fft_samples/2)+index], 2))); } delete[] in; delete[] out; return QSharedPointer (new FixedDataBlock (spectrum_data, static_cast(fft_samples) / data_block->getSampleRatePerUnit())); /* double* data_in = new double[num_samples * 2]; for (unsigned x = 0; x < num_samples; x++) data_in[x] = data_->at(start_index_ + x); unsigned out_length = (num_samples / 2); Complex* data_out = fftwpp::FFTWComplex(out_length * 4); fftwpp::rcfft1d forward (num_samples, data_in, data_out); forward.fft0Normalized (data_in, data_out); QSharedPointer > spectrum_data (new std::vector); for (unsigned index = 1; index < out_length + 1; index++) { spectrum_data->push_back (log10(pow(data_out[index].real(),2) + pow(data_out[index].imag(), 2))); } return QSharedPointer (new DataBlock (spectrum_data, static_cast(num_samples) / sample_rate_per_unit_));*/ } //----------------------------------------------------------------------------- QSharedPointer FixedDataBlock::calculateMean (std::list > const &data_blocks) { if (data_blocks.size() == 0) return QSharedPointer (0); std::list >::const_iterator it = data_blocks.begin(); QSharedPointer > mean (new QVector); float64 sample_rate = (*it)->getSampleRatePerUnit (); float64 tmp_mean = 0; for (size_t index = 0; index < (*(data_blocks.begin()))->size(); index++) { it = data_blocks.begin(); tmp_mean = 0; while (it != data_blocks.end()) { tmp_mean += (**it)[index]; ++it; } mean->push_back(tmp_mean / data_blocks.size()); } return QSharedPointer (new FixedDataBlock (mean, sample_rate)); } //------------------------------------------------------------------------- QSharedPointer FixedDataBlock::calculateStandardDeviation (std::list > const &data_blocks) { return calculateStandardDeviationImpl (data_blocks, calculateMean(data_blocks)); } //------------------------------------------------------------------------- QSharedPointer FixedDataBlock::calculateStandardDeviation (std::list > const &data_blocks, QSharedPointer means) { return calculateStandardDeviationImpl (data_blocks, means); } //------------------------------------------------------------------------- QSharedPointer FixedDataBlock::calculateStandardDeviationImpl (std::list > const & data_blocks, QSharedPointer means) { QSharedPointer > stddev (new QVector); if (data_blocks.size() == 0) return QSharedPointer(0); std::list >::const_iterator it = data_blocks.begin(); float64 sample_rate = (*it)->getSampleRatePerUnit (); float64 tmp_stddev = 0; for (size_t index = 0; index < (*(data_blocks.begin()))->size(); index++) { it = data_blocks.begin(); tmp_stddev = 0; float64 mean = (*means)[index]; while (it != data_blocks.end()) { tmp_stddev += pow(((**it)[index] - mean), 2); ++it; } stddev->push_back(sqrt(tmp_stddev / (data_blocks.size()))); } QSharedPointer stddev_block (new FixedDataBlock (stddev, sample_rate)); return stddev_block; } } sigviewer-0.6.4/src/base/fixed_data_block.h000066400000000000000000000063071345753661000206610ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FIXED_DATA_BLOCK_H #define FIXED_DATA_BLOCK_H #include "data_block.h" #include #include #include #include namespace sigviewer { //------------------------------------------------------------------------- /// FixedDataBlock /// /// basic class to store data class FixedDataBlock : public DataBlock { public: //------------------------------------------------------------------------- /// @param sample_rate_per_unit as a data_block must not represent data which /// is associated to time, the sample_rate is given /// in "per unit" (e.g. "s" or "hz", etc.) FixedDataBlock (QSharedPointer > data, float64 sample_rate_per_unit); //------------------------------------------------------------------------- virtual ~FixedDataBlock () {} //------------------------------------------------------------------------- virtual QSharedPointer createSubBlock (size_t start, size_t length) const; //------------------------------------------------------------------------- virtual float32 const& operator[] (size_t index) const; //------------------------------------------------------------------------- virtual float32 getMin () const; //------------------------------------------------------------------------- virtual float32 getMax () const; //--------------------------------------------------------------------------------------------- static QSharedPointer createPowerSpectrum (QSharedPointer data_block); //--------------------------------------------------------------------------------------------- static QSharedPointer calculateMean (std::list > const &data_blocks); //--------------------------------------------------------------------------------------------- static QSharedPointer calculateStandardDeviation (std::list > const &data_blocks); //--------------------------------------------------------------------------------------------- static QSharedPointer calculateStandardDeviation (std::list > const &data_blocks, QSharedPointer means); private: Q_DISABLE_COPY (FixedDataBlock); //--------------------------------------------------------------------------------------------- FixedDataBlock (FixedDataBlock const& base, size_t new_start, size_t new_length); //--------------------------------------------------------------------------------------------- static QSharedPointer calculateStandardDeviationImpl (std::list > const &data_blocks, QSharedPointer means); QSharedPointer > data_; size_t start_index_; static size_t instance_count_; }; } #endif // FIXED_DATA_BLOCK_H sigviewer-0.6.4/src/base/math_utils.cpp000066400000000000000000000017471345753661000201260ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "math_utils.h" #include #include namespace sigviewer { namespace MathUtils_ { //----------------------------------------------------------------------------- float64 round125(float64 value) { float64 sign = value < 0 ? -1 : 1; value = value * sign; float64 tmp = pow (10.0, floor (log10(value))); if (tmp < value) tmp *= 2.0; if (tmp < value) tmp *= 1.5; if (tmp < value) tmp *= (4.0 / 3.0); if (tmp < value) tmp *= (5.0 / 4.0); if (tmp < value) tmp *= (7.5 / 5.0); return sign * tmp; } //----------------------------------------------------------------------------- int sampleRateToDecimalPrecision (float64 sample_rate) { int precision = 0; for (; sample_rate > 10; sample_rate /= 10) precision++; return precision; } } } sigviewer-0.6.4/src/base/math_utils.h000066400000000000000000000010471345753661000175640ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MATH_UTILS_H #define MATH_UTILS_H #include "sigviewer_user_types.h" namespace sigviewer { namespace MathUtils_ { // round to 1, 2 or 5 float64 round125(float64 value); //----------------------------------------------------------------------------- /// @return number of decimals needed to display time intervals correctly int sampleRateToDecimalPrecision (float64 sample_rate); } } #endif sigviewer-0.6.4/src/base/signal_channel.cpp000066400000000000000000000112011345753661000207040ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_channel.h" #include "file_handling_impl/xdf_reader.h" namespace sigviewer { //!Constructor for libbiosig--------------------------------------------------- SignalChannel::SignalChannel(unsigned ch, const HDRTYPE* hdr) : label_ (QString(hdr->CHANNEL[ch].Label).trimmed()), physical_maximum_(hdr->CHANNEL[ch].PhysMax), digital_maximum_(hdr->CHANNEL[ch].DigMax), physical_minimum_(hdr->CHANNEL[ch].PhysMin), digital_minimum_(hdr->CHANNEL[ch].DigMin), data_type_(hdr->CHANNEL[ch].GDFTYP), lowpass_(hdr->CHANNEL[ch].LowPass), highpass_(hdr->CHANNEL[ch].HighPass), notch_(hdr->CHANNEL[ch].Notch) { #if (BIOSIG_VERSION < 10400) char tmpstr[30]; PhysDim(hdr->CHANNEL[ch].PhysDimCode, tmpstr); #else const char *tmpstr = PhysDim3(hdr->CHANNEL[ch].PhysDimCode); #endif phys_y_dimension_label_ = QString(tmpstr); samplerate_ = hdr->SampleRate * hdr->CHANNEL[ch].SPR / hdr->SPR; } //!Constructor for XDF format--------------------------------------------------- SignalChannel::SignalChannel(unsigned ch, QString file_format) : label_ (QString::fromStdString(XDFdata->labels[ch]).trimmed()) { //easy extension for potential other formats in the future if (file_format.compare("xdf", Qt::CaseInsensitive)) { phys_y_dimension_label_ = QString::number(ch); samplerate_ = XDFdata->majSR; } } //SignalChannel::SignalChannel(unsigned number, CHANNEL_TYPE C) : // /* obsolete */ // label_ (QString(C.Label).trimmed()), // physical_maximum_(C.PhysMax), // digital_maximum_(C.DigMax), // physical_minimum_(C.PhysMin), // digital_minimum_(C.DigMin), // data_type_(C.GDFTYP), // lowpass_(C.LowPass), // highpass_(C.HighPass), // notch_(C.Notch) //{ //#if (BIOSIG_VERSION < 10400) // char tmpstr[30]; // PhysDim(C.PhysDimCode), tmpstr); //#else // const char *tmpstr = PhysDim3(C.PhysDimCode); //#endif // phys_y_dimension_label_ = QString(tmpstr); // samplerate_ = -1.0; //} //----------------------------------------------------------------------------- float64 SignalChannel::getSampleRate() const { return samplerate_; } //----------------------------------------------------------------------------- const QString& SignalChannel::getLabel() const { return label_; } //----------------------------------------------------------------------------- float64 SignalChannel::getLowpass() const { return lowpass_; } //----------------------------------------------------------------------------- float64 SignalChannel::getHighpass() const { return highpass_; } //----------------------------------------------------------------------------- bool SignalChannel::getNotch() const { return notch_; } //----------------------------------------------------------------------------- const QString& SignalChannel::getPhysicalDim() const { return phys_y_dimension_label_; } //----------------------------------------------------------------------------- float64 SignalChannel::getPhysicalMaximum() const { return physical_maximum_; } //----------------------------------------------------------------------------- float64 SignalChannel::getDigitalMaximum() const { return digital_maximum_; } //----------------------------------------------------------------------------- float64 SignalChannel::getPhysicalMinimum() const { return physical_minimum_; } //----------------------------------------------------------------------------- float64 SignalChannel::getDigitalMinimum() const { return digital_minimum_; } //----------------------------------------------------------------------------- QString SignalChannel::typeString() const { if (data_type_ > UBITN) { return QString("ubit%1").arg(data_type_ - UBITN); } if (data_type_ > BITN) { return QString("bit%1").arg(data_type_ - BITN); } switch (data_type_) { case CHAR: return "char"; case INT8: return "int8"; case UINT8: return "uint8"; case INT16: return "int16"; case UINT16: return "uint16"; case INT32: return "int32"; case UINT32: return "uint32"; case INT64: return "int64"; case UINT64: return "uint64"; case FLOAT32: return "float32"; case FLOAT64: return "float64"; case FLOAT128: return "float128"; default: return "?"; } return "?"; } } sigviewer-0.6.4/src/base/signal_channel.h000066400000000000000000000036741345753661000203700ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_CHANNEL_H #define SIGNAL_CHANNEL_H #include "sigviewer_user_types.h" #include "biosig.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// @class SignalChannel /// @brief data about a signal channel class SignalChannel { public: //------------------------------------------------------------------------- SignalChannel(unsigned ch, const HDRTYPE* hdr); SignalChannel(unsigned ch, QString file_format); // SignalChannel(unsigned number, CHANNEL_TYPE C); /* obsolete, deprecated */ //------------------------------------------------------------------------- QString typeString() const; const QString& getLabel() const; float64 getLowpass() const; float64 getHighpass() const; bool getNotch() const; const QString& getPhysicalDim() const; float64 getPhysicalMaximum() const; float64 getDigitalMaximum() const; float64 getPhysicalMinimum() const; float64 getDigitalMinimum() const; float64 getSampleRate() const; private: // from GDF format enum Type { CHAR = 0, INT8 = 1, UINT8 = 2, INT16 = 3, UINT16 = 4, INT32 = 5, UINT32 = 6, INT64 = 7, UINT64 = 8, FLOAT32 = 16, FLOAT64 = 17, FLOAT128 = 18, // add N to code BITN = 255, UBITN = 511 }; mutable QMutex mutex_; //uint32 number_; QString label_; QString phys_y_dimension_label_; float64 physical_maximum_; float64 digital_maximum_; float64 physical_minimum_; float64 digital_minimum_; uint16_t data_type_; float64 lowpass_; float64 highpass_; float64 samplerate_; bool notch_; }; } #endif sigviewer-0.6.4/src/base/signal_event.cpp000066400000000000000000000073021345753661000204240ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_event.h" namespace sigviewer { // constructor SignalEvent::SignalEvent() : id_(UNDEFINED_EVENT_ID), position_(0xFFFFFFFF), sample_rate_ (1), type_(0xFFFF), channel_(UNDEFINED_CHANNEL), duration_(UNDEFINED_DURATION), stream_(-1) { // nothing } // constructor SignalEvent::SignalEvent(size_t position, EventType type, float64 sample_rate, int streamNumber, ChannelID channel, size_t duration, int32 id) : id_(id), position_(position), sample_rate_ (sample_rate), type_(type), channel_(channel), duration_(duration), stream_(streamNumber) { // nothing } // constructor SignalEvent::SignalEvent(const SignalEvent& src, int32 id) : id_(id), position_(src.position_), sample_rate_ (src.sample_rate_), type_(src.type_), channel_(src.channel_), duration_(src.duration_), stream_(src.stream_) { // nothing } // copy-constructor SignalEvent::SignalEvent(const SignalEvent& src) : id_(src.id_), position_(src.position_), sample_rate_ (src.sample_rate_), type_(src.type_), channel_(src.channel_), duration_(src.duration_), stream_(src.stream_) { // nothing } SignalEvent& SignalEvent::operator= (const SignalEvent& src) { id_ = src.id_; position_ = src.position_; sample_rate_ = src.sample_rate_; type_ = src.type_; channel_ = src.channel_; duration_ = src.duration_; stream_ = src.stream_; return *this; } // get id int32 SignalEvent::getId() const { return id_; } // get position size_t SignalEvent::getPosition() const { return position_; } //----------------------------------------------------------------------------- float64 SignalEvent::getPositionInSec() const { return static_cast(position_) / sample_rate_; } // get type uint16 SignalEvent::getType() const { return type_; } // get channel ChannelID SignalEvent::getChannel() const { return channel_; } // get duration size_t SignalEvent::getDuration() const { return duration_; } //----------------------------------------------------------------------------- float64 SignalEvent::getDurationInSec() const { return static_cast(duration_) / sample_rate_; } //----------------------------------------------------------------------------- float64 SignalEvent::getEndInSec () const { return (static_cast(duration_ + position_)) / sample_rate_; } //----------------------------------------------------------------------------- float64 SignalEvent::getSampleRate () const { return sample_rate_; } int SignalEvent::getStream() const { return stream_; } //----------------------------------------------------------------------------- void SignalEvent::setId (EventID id) { id_ = id; } // set position void SignalEvent::setPosition(size_t position) { position_ = position; } // set type void SignalEvent::setType(EventType type) { type_ = type; } // set channel void SignalEvent::setChannel(ChannelID channel) { channel_ = channel; } // set duration void SignalEvent::setDuration(size_t duration) { duration_ = duration; } //----------------------------------------------------------------------------- bool SignalEvent::equals (SignalEvent const& event) const { if (duration_ != event.duration_) return false; if (type_ != event.type_) return false; if (position_ != event.position_) return false; if (sample_rate_ != event.sample_rate_) return false; if (channel_ != event.channel_) return false; if (stream_ != event.stream_) return false; return true; } } sigviewer-0.6.4/src/base/signal_event.h000066400000000000000000000026741345753661000201000ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_EVENT_H #define SIGNAL_EVENT_H #include "sigviewer_user_types.h" namespace sigviewer { // SignalEvent class SignalEvent { public: SignalEvent(); SignalEvent(size_t position, EventType type, float64 sample_rate, int streamNumber, ChannelID channel = UNDEFINED_CHANNEL, size_t duration = 0, EventID id = UNDEFINED_EVENT_ID); SignalEvent(const SignalEvent& src, int32 id); SignalEvent(const SignalEvent& src); SignalEvent& operator= (const SignalEvent& src); int32 getId() const; size_t getPosition() const; float64 getPositionInSec() const; uint16 getType() const; ChannelID getChannel() const; size_t getDuration() const; float64 getDurationInSec() const; float64 getEndInSec () const; float64 getSampleRate () const; int getStream() const; void setId (EventID id); void setPosition(size_t position); void setType(EventType type); void setChannel(ChannelID channel); void setDuration(size_t duration); bool equals (SignalEvent const& event) const; private: static const int32 UNDEFINED_DURATION = 0; EventID id_; size_t position_; float64 sample_rate_; EventType type_; ChannelID channel_; size_t duration_; int stream_; }; } #endif sigviewer-0.6.4/src/base/sigviewer_user_types.h000066400000000000000000000022511345753661000216770ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGVIEWER_USER_TYPES_H #define SIGVIEWER_USER_TYPES_H #include namespace sigviewer { enum ScaleMode { MAX_TO_MAX, MIN_TO_MAX }; // standard types // compiler specific types #ifdef _MSC_VER typedef signed char int8_t; typedef unsigned char uint8_t; typedef short int16_t; typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned int uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #endif } #ifdef __GNUG__ #include #endif namespace sigviewer { typedef int8_t int8; typedef uint8_t uint8; typedef int16_t int16; typedef uint16_t uint16; typedef int32_t int32; typedef uint32_t uint32; typedef float float32; typedef double float64; typedef int64_t int64; typedef uint64_t uint64; typedef int32 EventID; typedef uint16 EventType; typedef int ChannelID; const ChannelID UNDEFINED_CHANNEL = -1; const EventID UNDEFINED_EVENT_ID = -1; const EventType UNDEFINED_EVENT_TYPE = -1; const int UNDEFINED_STREAM_ID= -1; } #endif // SIGVIEWER_USER_TYPES_H sigviewer-0.6.4/src/base/tab_states.h000066400000000000000000000010641345753661000175430ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef TAB_STATES_H #define TAB_STATES_H namespace sigviewer { enum TabSelectionState { NO_TAB_SELECTION_STATE, TAB_STATE_NO_EVENT_SELECTED, TAB_STATE_EVENT_SELECTED_ONE_CHANNEL, TAB_STATE_EVENT_SELECTED_ALL_CHANNELS }; enum TabEditState { NO_TAB_EDIT_STATE, TAB_STATE_NO_REDO, TAB_STATE_NO_UNDO, TAB_STATE_NO_REDO_NO_UNDO, TAB_STATE_CAN_REDO_UNDO }; } #endif // TAB_STATES_H sigviewer-0.6.4/src/color_settings.xml000066400000000000000000000013101345753661000201010ustar00rootroot00000000000000 sigviewer-0.6.4/src/command_executer.h000066400000000000000000000007321345753661000200230ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef COMMAND_EXECUTER_H #define COMMAND_EXECUTER_H #include namespace sigviewer { class CommandExecuter { public: virtual ~CommandExecuter () {} virtual void executeCommand (QUndoCommand* command) = 0; virtual void undo () = 0; virtual void redo () = 0; }; } #endif // COMMAND_EXECUTER_H sigviewer-0.6.4/src/commands/000077500000000000000000000000001345753661000161275ustar00rootroot00000000000000sigviewer-0.6.4/src/commands/commands.pri000066400000000000000000000002411345753661000204410ustar00rootroot00000000000000HEADERS += \ $$PWD/convert_file_command.h \ $$PWD/open_file_command.h SOURCES += \ $$PWD/convert_file_command.cpp \ $$PWD/open_file_command.cpp sigviewer-0.6.4/src/commands/convert_file_command.cpp000066400000000000000000000024621345753661000230140ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "convert_file_command.h" #include "open_file_command.h" #include "file_handling/file_signal_writer_factory.h" #include "gui/progress_bar.h" namespace sigviewer { //----------------------------------------------------------------------------- QString ConvertFileCommand::execute () { if (destination_file_path_.size() == 0) return "Error: no output-file defined"; OpenFileCommand open_file_command (application_context_, source_file_path_); QString open_error = open_file_command.execute (); if (open_error.size ()) return open_error; QSharedPointer writer (FileSignalWriterFactory::getInstance()->getHandler (destination_file_path_)); ProgressBar::instance().initAndShow (application_context_->getCurrentFileContext()->getChannelManager().getNumberSamples() + application_context_->getCurrentFileContext()->getEventManager()->getNumberOfEvents(), "Converting", application_context_); QString result = writer->save (application_context_->getCurrentFileContext()); ProgressBar::instance().close (); return result; } } sigviewer-0.6.4/src/commands/convert_file_command.h000066400000000000000000000015711345753661000224610ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CONVERT_FILE_COMMAND_H #define CONVERT_FILE_COMMAND_H #include "gui/application_context.h" #include namespace sigviewer { class ConvertFileCommand { public: ConvertFileCommand (QSharedPointer application_context, QString const& source_file_path, QString const& destination_file_path) : application_context_ (application_context), source_file_path_ (source_file_path), destination_file_path_ (destination_file_path) {} QString execute (); private: QSharedPointer application_context_; QString source_file_path_; QString destination_file_path_; }; } #endif // CONVERT_FILE_COMMAND_H sigviewer-0.6.4/src/commands/open_file_command.cpp000066400000000000000000000022741345753661000222760ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "open_file_command.h" #include "file_handling/file_signal_reader_factory.h" #include "file_handling_impl/channel_manager_impl.h" #include "file_handling_impl/event_manager_impl.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QString OpenFileCommand::execute () { QString file_path = QDir::toNativeSeparators (filename_and_path_); FileSignalReader* file_signal_reader (FileSignalReaderFactory::getInstance()->getHandler (file_path)); if (file_signal_reader == 0) return QString ("Can't open file ") + file_path; ChannelManager* channel_manager (new ChannelManagerImpl (file_signal_reader)); QSharedPointer event_manager (new EventManagerImpl (*file_signal_reader)); QSharedPointer file_context (new FileContext (file_path, event_manager, channel_manager, file_signal_reader->getBasicHeader())); application_context_->addFileContext (file_context); return ""; } } sigviewer-0.6.4/src/commands/open_file_command.h000066400000000000000000000014601345753661000217370ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef OPEN_FILE_COMMAND_H #define OPEN_FILE_COMMAND_H #include "gui/application_context.h" namespace sigviewer { class OpenFileCommand { public: OpenFileCommand (QSharedPointer application_context, QString const& filename_and_path) : application_context_ (application_context), filename_and_path_ (filename_and_path), non_gui_mode_ (true) {} QString execute (); private: void openFileInNonGuiMode (); QSharedPointer application_context_; QString filename_and_path_; bool instantly_; bool non_gui_mode_; }; } #endif // OPEN_FILE_COMMAND_H sigviewer-0.6.4/src/editing_commands/000077500000000000000000000000001345753661000176325ustar00rootroot00000000000000sigviewer-0.6.4/src/editing_commands/change_channel_undo_command.cpp000066400000000000000000000030661345753661000260030ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "change_channel_undo_command.h" #include "file_handling/event_manager.h" namespace sigviewer { //----------------------------------------------------------------------------- ChangeChannelUndoCommand::ChangeChannelUndoCommand (QSharedPointer event_manager, EventID event_id, ChannelID new_channel) : event_manager_ (event_manager), event_id_ (event_id), new_channel_ (new_channel) { // nothing to do here } //----------------------------------------------------------------------------- ChangeChannelUndoCommand::~ChangeChannelUndoCommand () { // nothing to do here } //----------------------------------------------------------------------------- void ChangeChannelUndoCommand::undo () { QSharedPointer signal_event_ = event_manager_->getAndLockEventForEditing (event_id_); signal_event_->setChannel (old_channel_); event_manager_->updateAndUnlockEvent (signal_event_->getId()); } //----------------------------------------------------------------------------- void ChangeChannelUndoCommand::redo () { QSharedPointer signal_event_ = event_manager_->getAndLockEventForEditing (event_id_); old_channel_ = signal_event_->getChannel(); signal_event_->setChannel (new_channel_); event_manager_->updateAndUnlockEvent (signal_event_->getId()); } } sigviewer-0.6.4/src/editing_commands/change_channel_undo_command.h000066400000000000000000000031571345753661000254510ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CHANGE_CHANNEL_UNDO_COMMAND_H #define CHANGE_CHANNEL_UNDO_COMMAND_H #include "base/signal_event.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { class ChangeChannelUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- ChangeChannelUndoCommand (QSharedPointer event_manager, EventID event_id, ChannelID new_channel); //------------------------------------------------------------------------- virtual ~ChangeChannelUndoCommand(); //------------------------------------------------------------------------- /// recreates the deleted event virtual void undo (); //------------------------------------------------------------------------- /// deletes the event virtual void redo (); private: //------------------------------------------------------------------------- /// copy-constructor disabled ChangeChannelUndoCommand (ChangeChannelUndoCommand const &); //------------------------------------------------------------------------- /// assignment-operator disabled ChangeChannelUndoCommand& operator= (ChangeChannelUndoCommand const &); QSharedPointer event_manager_; EventID event_id_; ChannelID new_channel_; ChannelID old_channel_; }; } #endif // CHANGE_CHANNEL_UNDO_COMMAND_H sigviewer-0.6.4/src/editing_commands/change_type_undo_command.cpp000066400000000000000000000025651345753661000253570ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "change_type_undo_command.h" #include "file_handling/event_manager.h" namespace sigviewer { //----------------------------------------------------------------------------- ChangeTypeUndoCommand::ChangeTypeUndoCommand (QSharedPointer event_manager, EventID event_id, EventType new_type) : event_id_ (event_id), event_manager_ (event_manager), new_type_ (new_type) { // nothing to do here } //----------------------------------------------------------------------------- ChangeTypeUndoCommand::~ChangeTypeUndoCommand () { // nothing to do here } //----------------------------------------------------------------------------- void ChangeTypeUndoCommand::undo () { signal_event_->setType(old_type_); event_manager_->updateAndUnlockEvent (signal_event_->getId()); } //----------------------------------------------------------------------------- void ChangeTypeUndoCommand::redo () { signal_event_ = event_manager_->getAndLockEventForEditing (event_id_); old_type_ = signal_event_->getType(); signal_event_->setType(new_type_); event_manager_->updateAndUnlockEvent (signal_event_->getId()); } } sigviewer-0.6.4/src/editing_commands/change_type_undo_command.h000066400000000000000000000032031345753661000250120ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CHANGE_TYPE_UNDO_COMMAND_H #define CHANGE_TYPE_UNDO_COMMAND_H #include "base/signal_event.h" #include "file_handling/event_manager.h" #include #include #include namespace sigviewer { class ChangeTypeUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- ChangeTypeUndoCommand (QSharedPointer event_manager, EventID event_id, EventType new_type); //------------------------------------------------------------------------- virtual ~ChangeTypeUndoCommand(); //------------------------------------------------------------------------- /// recreates the deleted event virtual void undo (); //------------------------------------------------------------------------- /// deletes the event virtual void redo (); private: //------------------------------------------------------------------------- /// copy-constructor disabled ChangeTypeUndoCommand (ChangeTypeUndoCommand const &); //------------------------------------------------------------------------- /// assignment-operator disabled ChangeTypeUndoCommand& operator= (ChangeTypeUndoCommand const &); EventID event_id_; QSharedPointer event_manager_; EventType new_type_; EventType old_type_; QSharedPointer signal_event_; }; } #endif // CHANGE_TYPE_UNDO_COMMAND_H sigviewer-0.6.4/src/editing_commands/delete_event_undo_command.cpp000066400000000000000000000025301345753661000255240ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "delete_event_undo_command.h" #include "file_handling/event_manager.h" namespace sigviewer { //----------------------------------------------------------------------------- DeleteEventUndoCommand::DeleteEventUndoCommand (QSharedPointer event_manager, EventID event_id) : event_manager_ (event_manager), deleted_event_ (event_manager->getEvent (event_id)) { // nothing to do here } //----------------------------------------------------------------------------- DeleteEventUndoCommand::~DeleteEventUndoCommand () { // nothing to do here } //----------------------------------------------------------------------------- void DeleteEventUndoCommand::undo () { event_manager_->createEvent ( deleted_event_->getChannel (), deleted_event_->getPosition (), deleted_event_->getDuration (), deleted_event_->getType (), deleted_event_->getStream(), deleted_event_->getId ()); } //----------------------------------------------------------------------------- void DeleteEventUndoCommand::redo () { event_manager_->removeEvent (deleted_event_->getId ()); } } sigviewer-0.6.4/src/editing_commands/delete_event_undo_command.h000066400000000000000000000031141345753661000251700ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef DELETE_EVENT_UNDO_COMMAND_H #define DELETE_EVENT_UNDO_COMMAND_H #include "base/signal_event.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { class DeleteEventUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- /// constructor DeleteEventUndoCommand (QSharedPointer event_manager, EventID event_id); //------------------------------------------------------------------------- /// destructor virtual ~DeleteEventUndoCommand (); //------------------------------------------------------------------------- /// recreates the deleted event virtual void undo (); //------------------------------------------------------------------------- /// deletes the event virtual void redo (); private: QSharedPointer event_manager_; EventID event_id_; QSharedPointer deleted_event_; //------------------------------------------------------------------------- /// copy-constructor disabled DeleteEventUndoCommand (DeleteEventUndoCommand const &); //------------------------------------------------------------------------- /// assignment-operator disabled DeleteEventUndoCommand& operator= (DeleteEventUndoCommand const &); }; } #endif // DELETE_EVENT_UNDO_COMMAND_H sigviewer-0.6.4/src/editing_commands/editing_commands.pri000066400000000000000000000007611345753661000236560ustar00rootroot00000000000000HEADERS += \ $$PWD/change_channel_undo_command.h \ $$PWD/change_type_undo_command.h \ $$PWD/delete_event_undo_command.h \ $$PWD/macro_undo_command.h \ $$PWD/new_event_undo_command.h \ $$PWD/resize_event_undo_command.h SOURCES += \ $$PWD/change_channel_undo_command.cpp \ $$PWD/change_type_undo_command.cpp \ $$PWD/delete_event_undo_command.cpp \ $$PWD/macro_undo_command.cpp \ $$PWD/new_event_undo_command.cpp \ $$PWD/resize_event_undo_command.cpp sigviewer-0.6.4/src/editing_commands/macro_undo_command.cpp000066400000000000000000000015371345753661000241700ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "macro_undo_command.h" namespace sigviewer { //----------------------------------------------------------------------------- MacroUndoCommand::MacroUndoCommand (QList > const& commands) : commands_ (commands) { // nothing to do here } //----------------------------------------------------------------------------- void MacroUndoCommand::undo () { for (int index = commands_.length () - 1; index > -1; index--) commands_[index]->undo (); } //----------------------------------------------------------------------------- void MacroUndoCommand::redo () { for (int index = 0; index < commands_.length (); index++) commands_[index]->redo (); } } sigviewer-0.6.4/src/editing_commands/macro_undo_command.h000066400000000000000000000025231345753661000236310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MACRO_UNDO_COMMAND_H #define MACRO_UNDO_COMMAND_H #include #include namespace sigviewer { class MacroUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- /// constructor MacroUndoCommand (QList > const& commands); //------------------------------------------------------------------------- /// destructor virtual ~MacroUndoCommand () {} //------------------------------------------------------------------------- /// undos the all commands virtual void undo (); //------------------------------------------------------------------------- /// executes the macro virtual void redo (); private: QList > commands_; //------------------------------------------------------------------------- /// copy-constructor disabled MacroUndoCommand (MacroUndoCommand const &); //------------------------------------------------------------------------- /// assignment-operator disabled MacroUndoCommand& operator= (MacroUndoCommand const &); }; } #endif // MACRO_UNDO_COMMAND_H sigviewer-0.6.4/src/editing_commands/new_event_undo_command.cpp000066400000000000000000000041061345753661000250540ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "new_event_undo_command.h" #include "file_handling_impl/xdf_reader.h" namespace sigviewer { //----------------------------------------------------------------------------- NewEventUndoCommand::NewEventUndoCommand (QSharedPointer event_manager, QSharedPointer signal_event, float scene_to_signal_factor) : event_manager_ (event_manager), raw_signal_event_ (new SignalEvent (*signal_event)) { raw_signal_event_->setPosition (scene_to_signal_factor * raw_signal_event_->getPosition()); raw_signal_event_->setDuration (scene_to_signal_factor * raw_signal_event_->getDuration()); } //----------------------------------------------------------------------------- NewEventUndoCommand::~NewEventUndoCommand () { // nothing to do here } //----------------------------------------------------------------------------- void NewEventUndoCommand::undo () { event_manager_->removeEvent (created_signal_event_->getId ()); //If XDF file, also pop back the event added to the XDFdata object earlier if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { XDFdata->userCreatedEvents.pop_back(); if (XDFdata->userCreatedEvents.empty()) { XDFdata->streams.pop_back(); XDFdata->userAddedStream = 0; } } } //----------------------------------------------------------------------------- void NewEventUndoCommand::redo () { EventID id = UNDEFINED_EVENT_ID; if (!created_signal_event_.isNull()) id = created_signal_event_->getId (); created_signal_event_ = event_manager_->createEvent ( raw_signal_event_->getChannel(), raw_signal_event_->getPosition(), raw_signal_event_->getDuration(), raw_signal_event_->getType(), raw_signal_event_->getStream(), id); } } sigviewer-0.6.4/src/editing_commands/new_event_undo_command.h000066400000000000000000000034461345753661000245270ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef NEW_EVENT_UNDO_COMMAND_H #define NEW_EVENT_UNDO_COMMAND_H #include "base/signal_event.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { class NewEventUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- NewEventUndoCommand (QSharedPointer event_manager, QSharedPointer signal_event, float scene_to_signal_factor = 1); //------------------------------------------------------------------------- virtual ~NewEventUndoCommand (); //------------------------------------------------------------------------- /// recreates the deleted event virtual void undo (); //------------------------------------------------------------------------- /// deletes the event virtual void redo (); //------------------------------------------------------------------------- EventID getIDOfNewlyCreatedEvent () const {return created_signal_event_->getId();} private: QSharedPointer event_manager_; QSharedPointer raw_signal_event_; QSharedPointer created_signal_event_; //------------------------------------------------------------------------- /// copy-constructor disabled NewEventUndoCommand (NewEventUndoCommand const &); //------------------------------------------------------------------------- /// assignment-operator disabled NewEventUndoCommand& operator= (NewEventUndoCommand const &); }; } #endif // NEW_EVENT_UNDO_COMMAND_H sigviewer-0.6.4/src/editing_commands/resize_event_undo_command.cpp000066400000000000000000000031001345753661000255550ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "resize_event_undo_command.h" #include "file_handling/event_manager.h" namespace sigviewer { //----------------------------------------------------------------------------- ResizeEventUndoCommand::ResizeEventUndoCommand (QSharedPointer event_manager, EventID id, uint32 new_start_position, uint32 new_duration) : event_manager_ (event_manager), event_id_ (id), new_start_position_ (new_start_position), new_duration_ (new_duration) { // nothing to do here } //----------------------------------------------------------------------------- void ResizeEventUndoCommand::undo () { QSharedPointer event = event_manager_->getAndLockEventForEditing (event_id_); event->setDuration (old_duration_); event->setPosition (old_start_position_); event_manager_->updateAndUnlockEvent (event->getId()); } //----------------------------------------------------------------------------- void ResizeEventUndoCommand::redo () { QSharedPointer event = event_manager_->getAndLockEventForEditing (event_id_); old_duration_ = event->getDuration(); old_start_position_ = event->getPosition(); event->setDuration (new_duration_); event->setPosition (new_start_position_); event_manager_->updateAndUnlockEvent (event->getId()); } } sigviewer-0.6.4/src/editing_commands/resize_event_undo_command.h000066400000000000000000000025321345753661000252320ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef RESIZE_EVENT_UNDO_COMMAND_H #define RESIZE_EVENT_UNDO_COMMAND_H #include "base/signal_event.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { class ResizeEventUndoCommand : public QUndoCommand { public: //------------------------------------------------------------------------- /// constructor ResizeEventUndoCommand (QSharedPointer event_manager, EventID id, uint32 new_start_position, uint32 new_duration); //------------------------------------------------------------------------- /// destructor virtual ~ResizeEventUndoCommand () {} //------------------------------------------------------------------------- /// undos the resizing virtual void undo (); //------------------------------------------------------------------------- /// resizes the event virtual void redo (); private: QSharedPointer event_manager_; EventID event_id_; uint32 new_start_position_; uint32 new_duration_; uint32 old_start_position_; uint32 old_duration_; }; } #endif // RESIZE_EVENT_UNDO_COMMAND_H sigviewer-0.6.4/src/file_context.cpp000066400000000000000000000067641345753661000175320ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "file_context.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- FileContext::FileContext (QString const& file_path_and_name, QSharedPointer event_manager, ChannelManager* channel_manager, QSharedPointer header) : state_ (FILE_STATE_UNCHANGED), file_path_and_name_ (file_path_and_name), event_manager_ (event_manager), channel_manager_ (channel_manager), basic_header_ (header) { connect (event_manager_.data(), SIGNAL(changed()), SLOT(setAsChanged())); } //----------------------------------------------------------------------------- FileContext::~FileContext () { qDebug () << "deleting FileContext"; delete channel_manager_; } //------------------------------------------------------------------------- void FileContext::resetFilePathAndName (QString const& new_file_path_and_name) { file_path_and_name_ = new_file_path_and_name; emit fileNameChanged (file_path_and_name_.section (QDir::separator(), -1)); } //------------------------------------------------------------------------- QString FileContext::getFilePath () const { QString file_name = getFileName (); return file_path_and_name_.left (file_path_and_name_.length() - file_name.length()); } //----------------------------------------------------------------------------- QString const& FileContext::getFilePathAndName () const { return file_path_and_name_; } //----------------------------------------------------------------------------- QString FileContext::getFileName () const { return file_path_and_name_.section (QDir::separator(), -1); } //------------------------------------------------------------------------- QSharedPointer FileContext::getMainVisualisationModel () { return main_signal_vis_model_; } //------------------------------------------------------------------------- void FileContext::setMainVisualisationModel (QSharedPointer signal_vis_model) { main_signal_vis_model_ = signal_vis_model; } //----------------------------------------------------------------------------- QSharedPointer FileContext::getEventManager () const { return event_manager_; } //----------------------------------------------------------------------------- QSharedPointer FileContext::getEventManager () { return event_manager_; } //----------------------------------------------------------------------------- ChannelManager const& FileContext::getChannelManager () const { return *channel_manager_; } //----------------------------------------------------------------------------- ChannelManager& FileContext::getChannelManager () { return *channel_manager_; } //------------------------------------------------------------------------- FileState FileContext::getState () const { return state_; } //----------------------------------------------------------------------------- void FileContext::setState (FileState state) { state_ = state; emit stateChanged (state_); } //----------------------------------------------------------------------------- void FileContext::setAsChanged () { state_ = FILE_STATE_CHANGED; emit stateChanged (state_); } } sigviewer-0.6.4/src/file_context.h000066400000000000000000000075361345753661000171750ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_CONTEXT_H #define FILE_CONTEXT_H #include "file_handling/event_manager.h" #include "file_handling/basic_header.h" #include "file_handling/channel_manager.h" #include "gui/signal_visualisation_model.h" #include "base/file_states.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// /// FileContext /// /// exists once per opened file... /// class FileContext : public QObject { Q_OBJECT public: //------------------------------------------------------------------------- /// /// @param channel_manager the FileContext takes ownership of the given /// ChannelManager and destroys it if the FileContext /// is deleted FileContext (QString const & file_path_and_name, QSharedPointer event_manager, ChannelManager* channel_manager, QSharedPointer header); //------------------------------------------------------------------------- ~FileContext (); //------------------------------------------------------------------------- void resetFilePathAndName (QString const& new_file_path_and_name); //------------------------------------------------------------------------- QString getFilePath () const; //------------------------------------------------------------------------- QString const& getFilePathAndName () const; //------------------------------------------------------------------------- QString getFileName () const; //------------------------------------------------------------------------- QSharedPointer getMainVisualisationModel (); //------------------------------------------------------------------------- void setMainVisualisationModel (QSharedPointer signal_vis_model); //------------------------------------------------------------------------- QSharedPointer getEventManager () const; //------------------------------------------------------------------------- QSharedPointer getEventManager (); //------------------------------------------------------------------------- ChannelManager const & getChannelManager () const; //------------------------------------------------------------------------- ChannelManager& getChannelManager (); //------------------------------------------------------------------------- QSharedPointer getHeader () {return basic_header_;} //------------------------------------------------------------------------- FileState getState () const; signals: //------------------------------------------------------------------------- void stateChanged (FileState state); //------------------------------------------------------------------------- void fileNameChanged (QString const& file_path_and_name); public slots: //------------------------------------------------------------------------- void setState (FileState state); //------------------------------------------------------------------------- void setAsChanged (); private: //------------------------------------------------------------------------- // disabled FileContext (FileContext const&); FileContext& operator= (FileContext const&); FileState state_; QString file_path_and_name_; QSharedPointer event_manager_; ChannelManager* channel_manager_; QSharedPointer basic_header_; QSharedPointer main_signal_vis_model_; }; } #endif // FILE_CONTEXT_H sigviewer-0.6.4/src/file_handling/000077500000000000000000000000001345753661000171115ustar00rootroot00000000000000sigviewer-0.6.4/src/file_handling/basic_header.cpp000066400000000000000000000036611345753661000222140ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "basic_header.h" namespace sigviewer { //----------------------------------------------------------------------------- QString BasicHeader::getFileTypeString() const { return file_type_string_; } //----------------------------------------------------------------------------- float64 BasicHeader::getSampleRate() const { return sample_rate_; } //----------------------------------------------------------------------------- uint32 BasicHeader::getNumberEvents() const { return number_events_; } void BasicHeader::setNumberEvents(uint32 number_events) { number_events_ = number_events; } // get event samplerate double BasicHeader::getEventSamplerate() const { return sample_rate_; } void BasicHeader::setEventSamplerate(double event_sample_rate) { event_sample_rate_ = event_sample_rate; } //------------------------------------------------------------------------- QSharedPointer BasicHeader::getChannel(ChannelID id) const { if (channels_.contains(id)) return channels_[id]; return QSharedPointer (0); } //------------------------------------------------------------------------- unsigned BasicHeader::getNumberChannels() const { return channels_.size(); } //------------------------------------------------------------------------- void BasicHeader::setFileTypeString(QString const& file_type_string) { file_type_string_ = file_type_string; } //------------------------------------------------------------------------- void BasicHeader::setSampleRate(float64 sample_rate) { sample_rate_ = sample_rate; } //------------------------------------------------------------------------- void BasicHeader::addChannel(ChannelID id, QSharedPointer channel) { channels_[id] = channel; } } sigviewer-0.6.4/src/file_handling/basic_header.h000066400000000000000000000070441345753661000216600ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BASIC_HEADER_H #define BASIC_HEADER_H #include "base/signal_channel.h" #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// @class BasicHeader (common for all file formats) /// @brief base class for any biosignal file header class BasicHeader { public: //------------------------------------------------------------------------- virtual ~BasicHeader() {} //------------------------------------------------------------------------- QString getFileTypeString () const; //------------------------------------------------------------------------- QString getFilePath () const {return file_path_;} //------------------------------------------------------------------------- virtual QMap getPatientInfo () const {return patient_info_;} //------------------------------------------------------------------------- /// may include recording time, triggered, etc. virtual QMap getRecordingInfo () const {return recording_info_;} //------------------------------------------------------------------------- float64 getSampleRate () const; //------------------------------------------------------------------------- QSharedPointer getChannel (ChannelID id) const; //------------------------------------------------------------------------- unsigned getNumberChannels() const; //------------------------------------------------------------------------- virtual size_t getNumberOfSamples () const = 0; //------------------------------------------------------------------------- virtual QMap getNamesOfUserSpecificEvents () const {return QMap();} uint32 getNumberEvents() const; void setNumberEvents (uint32 number_events); double getEventSamplerate() const; void setEventSamplerate (double event_sample_rate); protected: //------------------------------------------------------------------------- BasicHeader (QString const& file_path) : file_path_ (file_path) {} // events uint32 number_events_; double event_sample_rate_; //------------------------------------------------------------------------- /// optional void setFileTypeString (QString const& file_type_string); //------------------------------------------------------------------------- /// required void setSampleRate (float64 sample_rate); //------------------------------------------------------------------------- /// required void addChannel (ChannelID id, QSharedPointer channel); //------------------------------------------------------------------------- /// optional void addRecordingInfo (QString const& info_label, QString const& value) {recording_info_[info_label] = value;} //------------------------------------------------------------------------- /// optional void addPatientInfo (QString const& info_label, QString const& value) {patient_info_[info_label] = value;} private: QString const file_path_; QString file_type_string_; float64 sample_rate_; QMap > channels_; QMap recording_info_; QMap patient_info_; }; } #endif sigviewer-0.6.4/src/file_handling/channel_manager.cpp000066400000000000000000000074271345753661000227310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "channel_manager.h" #include "gui/progress_bar.h" #include namespace sigviewer { ////------------------------------------------------------------------------- //QString ChannelManager::getChannelLabel(ChannelID id, int streamNumber) const //{ //} void ChannelManager::addDownsampledMinMaxVersion (ChannelID id, QSharedPointer min, QSharedPointer max, unsigned factor) { downsampled_max_map_[id][factor] = max; downsampled_min_map_[id][factor] = min; } //------------------------------------------------------------------------- unsigned ChannelManager::getNearestDownsamplingFactor (ChannelID id, unsigned factor) const { if (!downsampled_min_map_.contains (id)) return 0; unsigned nearest_factor = 1; bool search = true; for (nearest_factor = factor + 1; search && (nearest_factor > 1); --nearest_factor) if (downsampled_min_map_[id].contains (nearest_factor - 1)) search = false; return nearest_factor; } //------------------------------------------------------------------------- QSharedPointer ChannelManager::getDownsampledMin (ChannelID id, unsigned factor) const { return downsampled_min_map_[id][factor]; } //------------------------------------------------------------------------- QSharedPointer ChannelManager::getDownsampledMax (ChannelID id, unsigned factor) const { return downsampled_max_map_[id][factor]; } //------------------------------------------------------------------------- float64 ChannelManager::getValueRange (std::set const& channels) const { return getMaxValue (channels) - getMinValue (channels); } //------------------------------------------------------------------------- float64 ChannelManager::getMinValue (std::set const& channels) const { if (!min_max_initialized_) initMinMax(); float64 min = std::numeric_limits::max(); foreach (ChannelID channel, channels) min = std::min (min, min_values_[channel]); return min; } //------------------------------------------------------------------------- float64 ChannelManager::getMaxValue (std::set const& channels) const { if (!min_max_initialized_) initMinMax(); float64 max = std::numeric_limits::min(); foreach (ChannelID channel, channels) max = std::max (max, max_values_[channel]); return max; } //------------------------------------------------------------------------- float64 ChannelManager::getMinValue (ChannelID channel_id) const { if (!min_max_initialized_) initMinMax(); if (min_values_.count (channel_id)) return min_values_[channel_id]; else return std::numeric_limits::min(); } //------------------------------------------------------------------------- float64 ChannelManager::getMaxValue (ChannelID channel_id) const { if (!min_max_initialized_) initMinMax(); if (max_values_.count (channel_id)) return max_values_[channel_id]; else return std::numeric_limits::max(); } //------------------------------------------------------------------------- void ChannelManager::initMinMax () const { if (min_max_initialized_) return; foreach (ChannelID id, getChannels()) { QSharedPointer data = getData (id, 0, getNumberSamples ()); max_values_[id] = data->getMax (); min_values_[id] = data->getMin (); ProgressBar::instance().increaseValue (1, QObject::tr("Searching for Min-Max")); } min_max_initialized_ = true; } } sigviewer-0.6.4/src/file_handling/channel_manager.h000066400000000000000000000112101345753661000223570ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CHANNEL_MANAGER_INTERFACE_H #define CHANNEL_MANAGER_INTERFACE_H #include "base/data_block.h" #include namespace sigviewer { //----------------------------------------------------------------------------- /// ChannelManager /// /// abstract base class for any channel handling class ChannelManager { public: //------------------------------------------------------------------------- /// destructor virtual ~ChannelManager () {} //------------------------------------------------------------------------- virtual std::set getChannels () const = 0; //------------------------------------------------------------------------- virtual uint32 getNumberChannels () const = 0; //------------------------------------------------------------------------- virtual QString getChannelLabel (ChannelID id) const = 0; //------------------------------------------------------------------------- virtual QString getChannelLabel (ChannelID id, int streamNumber) const = 0; //streamNumber is for XDF only //------------------------------------------------------------------------- virtual QString getChannelYUnitString (ChannelID id) const = 0; //------------------------------------------------------------------------- /// @param channel_id the id of the channel /// @param start_pos starting sample /// @param length length given in samples virtual QSharedPointer getData (ChannelID id, unsigned start_pos, unsigned length) const = 0; //------------------------------------------------------------------------- virtual float64 getDurationInSec () const = 0; //------------------------------------------------------------------------- virtual size_t getNumberSamples () const = 0; //------------------------------------------------------------------------- virtual float64 getSampleRate () const = 0; //------------------------------------------------------------------------- void addDownsampledMinMaxVersion (ChannelID id, QSharedPointer min, QSharedPointer max, unsigned factor); //------------------------------------------------------------------------- unsigned getNearestDownsamplingFactor (ChannelID id, unsigned factor) const; //------------------------------------------------------------------------- QSharedPointer getDownsampledMin (ChannelID id, unsigned factor) const; //------------------------------------------------------------------------- QSharedPointer getDownsampledMax (ChannelID id, unsigned factor) const; //------------------------------------------------------------------------- float64 getValueRange (std::set const& channels) const; //------------------------------------------------------------------------- float64 getMinValue (std::set const& channels) const; //------------------------------------------------------------------------- float64 getMaxValue (std::set const& channels) const; //------------------------------------------------------------------------- float64 getMinValue (ChannelID channel_id) const; //------------------------------------------------------------------------- float64 getMaxValue (ChannelID channel_id) const; //------------------------------------------------------------------------- void setXAxisUnitLabel (QString const& label) {x_axis_unit_label_ = label;} //------------------------------------------------------------------------- QString getXAxisUnitLabel () const {return x_axis_unit_label_;} protected: ChannelManager () : min_max_initialized_ (false) {} private: //------------------------------------------------------------------------- void initMinMax () const; mutable bool min_max_initialized_; mutable std::map max_values_; mutable std::map min_values_; mutable std::map offsets_; QString x_axis_unit_label_; QMap > > downsampled_max_map_; // [channel][factor] -> maximum downsampled_data QMap > > downsampled_min_map_; // [channel][factor] -> minimum downsampled_data }; } #endif // CHANNEL_MANAGER_INTERFACE_H sigviewer-0.6.4/src/file_handling/event_manager.h000066400000000000000000000111411345753661000220730ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_MANAGER_H #define EVENT_MANAGER_H #include "base/sigviewer_user_types.h" #include "base/signal_event.h" #include #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// EventManager /// /// interface (abstract base class) for the the central /// access point for any event manipulation class EventManager : public QObject { Q_OBJECT public: //------------------------------------------------------------------------- /// virtual destructor virtual ~EventManager () {} //------------------------------------------------------------------------- virtual QSharedPointer getEvent (EventID id) const = 0; //------------------------------------------------------------------------- /// returns the event for editing and locks the event virtual QSharedPointer getAndLockEventForEditing (EventID id) = 0; //------------------------------------------------------------------------- /// changes the type of the event of the given type /// and emits the signal eventChanged (id) virtual void updateAndUnlockEvent (EventID id) = 0; //------------------------------------------------------------------------- /// /// @return const pointer to the newly created event virtual QSharedPointer createEvent (ChannelID channel_id, unsigned pos, unsigned length, EventType type, int stream_id, EventID id = UNDEFINED_EVENT_ID) = 0; //------------------------------------------------------------------------- /// removes the event with the given id virtual void removeEvent (EventID id) = 0; //------------------------------------------------------------------------- /// /// @return set of event_id of events at the given position virtual std::set getEventsAt (unsigned pos, ChannelID channel_id) const = 0; //------------------------------------------------------------------------- /// @return sample rate of events virtual double getSampleRate () const = 0; //------------------------------------------------------------------------- virtual unsigned getMaxEventPosition () const = 0; //------------------------------------------------------------------------- /// @return the name of the given event type virtual QString getNameOfEventType (EventType type) const = 0; //------------------------------------------------------------------------- /// @return the name of the given event virtual QString getNameOfEvent (EventID event) const = 0; //------------------------------------------------------------------------- /// @return list of event_id of all events virtual QList getAllEvents () const = 0; //------------------------------------------------------------------------- /// @return amount of events virtual unsigned getNumberOfEvents () const = 0; //------------------------------------------------------------------------- virtual std::set getEventTypes () const {return getEventTypes ("");} //------------------------------------------------------------------------- virtual std::set getEventTypes (QString group_id) const = 0; //------------------------------------------------------------------------- virtual std::set getEventTypeGroupIDs () const = 0; //------------------------------------------------------------------------- /// @return set of event_ids of events of the given type virtual QList getEvents (EventType type) const = 0; //------------------------------------------------------------------------- virtual EventID getNextEventOfSameType (EventID id) const = 0; //------------------------------------------------------------------------- virtual EventID getPreviousEventOfSameType (EventID id) const = 0; //------------------------------------------------------------------------- virtual QString getFileType () const = 0; //------------------------------------------------------------------------- virtual void setEventName (EventType event_type_id, QString const& name) = 0; signals: void eventChanged (EventID id); void eventCreated (QSharedPointer event); void eventRemoved (EventID id); void changed (); }; } #endif // EVENT_MANAGER_INTERFACE_H sigviewer-0.6.4/src/file_handling/file_handler_factory.h000066400000000000000000000102671345753661000234330ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_HANDLER_FACTORY_H #define FILE_HANDLER_FACTORY_H #include "base/exception.h" #include #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// FileHandlerFactory /// generic file handler factory for storing readers or writers or whatever :) template class FileHandlerFactory { public: //------------------------------------------------------------------------- bool registerHandler (QString const& file_ending, QSharedPointer file_handler); //------------------------------------------------------------------------- void registerDefaultHandler (QSharedPointer file_handler); //------------------------------------------------------------------------- FileHandlerType* getHandler (QString const& file_path); //------------------------------------------------------------------------- QStringList getAllFileEndingsWithWildcards () const; protected : FileHandlerFactory () {} virtual ~FileHandlerFactory () {} private: // not allowed FileHandlerFactory (const FileHandlerFactory& src); const FileHandlerFactory& operator=(const FileHandlerFactory& src); std::map > handler_map_; QSharedPointer default_handler_; QStringList wildcard_file_endings_; }; //------------------------------------------------------------------------- template bool FileHandlerFactory::registerHandler (QString const& file_ending, QSharedPointer file_handler) { if (handler_map_.count (file_ending)) return false; handler_map_[file_ending] = file_handler; qDebug () << "FileHandlerFactory::registerHandler: file_ending = " << file_ending; wildcard_file_endings_ << QString("*.") + file_ending; return true; } //------------------------------------------------------------------------- template void FileHandlerFactory::registerDefaultHandler (QSharedPointer file_handler) { qDebug () << "FileHandlerFactory::registerDefaultHandler"; default_handler_ = file_handler; } //------------------------------------------------------------------------- template FileHandlerType* FileHandlerFactory::getHandler (QString const& file_path) { QString file_ending = file_path.section('.', -1); qDebug () << "FACTORY " << file_ending; if (handler_map_.count(file_ending)) { QPair handler = handler_map_[file_ending]->createInstance (file_path); if (handler.first) return handler.first; else if (handler.second.compare("Cancelled", Qt::CaseInsensitive) == 0) return 0; else if (handler.second.compare("non-exist", Qt::CaseInsensitive) == 0) return 0; else { handler = default_handler_->createInstance (file_path); if (handler.first) return handler.first; else { QMessageBox::information (0, QObject::tr("File Opening"), handler.second); return 0; } } } else if (!default_handler_.isNull()) { QPair handler = default_handler_->createInstance (file_path); if (handler.second.size()) QMessageBox::information (0, QObject::tr("File Opening"), handler.second); return handler.first; } else return 0; } //------------------------------------------------------------------------- template QStringList FileHandlerFactory::getAllFileEndingsWithWildcards () const { return wildcard_file_endings_; } } #endif sigviewer-0.6.4/src/file_handling/file_handling.pri000066400000000000000000000007311345753661000224110ustar00rootroot00000000000000HEADERS += \ $$PWD/basic_header.h \ $$PWD/channel_manager.h \ $$PWD/event_manager.h \ $$PWD/file_handler_factory.h \ $$PWD/file_signal_reader.h \ $$PWD/file_signal_reader_factory.h \ $$PWD/file_signal_writer.h \ $$PWD/file_signal_writer_factory.h SOURCES += \ $$PWD/basic_header.cpp \ $$PWD/channel_manager.cpp \ $$PWD/file_signal_reader_factory.cpp \ $$PWD/file_signal_writer_factory.cpp \ $$PWD/file_signal_reader.cpp sigviewer-0.6.4/src/file_handling/file_signal_reader.cpp000066400000000000000000000051731345753661000234210ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "file_signal_reader.h" #include namespace sigviewer { int FileSignalReader::setEventTypeColors() { // Display each event type in a distinct color QSharedPointer colorPicker = ApplicationContextImpl::getInstance()->color_manager_; //set event colors srand (time(NULL)); /* initialize random seed: */ QVector eventColorList = {"#0055ff", "#00aa00", "#aa00ff", "#ff0000", "#00557f", "#5555ff", "#ff55ff", "#00aaff", "#00aa7f", "#ff5500"}; int colorChoice = 5; //Set the first event color to be pink QSettings settings; settings.beginGroup("ColorManager"); int size = settings.beginReadArray("event"); for (int type = 0; type < 254; type++) { QColor color; if (type < size) { settings.setArrayIndex(type); color = settings.value("color").toString(); color.setAlpha(settings.value("alpha").toInt()); } /* if the user has specified color setting for the current event type previously * in QSettings, we want to use it. * If the color setting is #0000ff (default), we assume the user * hasn't specified color for the current event type yet. Below is our algorithm * to pick some good colors for event types. */ if (color.name().compare("#0000ff", Qt::CaseInsensitive) == 0) { // generate random number first: int red = rand() % 41 + (-20); int green = rand() % 41 + (-20); int blue = rand() % 41 + (-20); colorChoice++; if (colorChoice == 10) //we only have 10 basic colors colorChoice = 0; color = eventColorList[colorChoice]; red += color.red(); green += color.green(); blue += color.blue(); if (red < 0) red = 0; if (red > 255) red = 255; if (green < 0) green = 0; if (green > 255) green = 255; if (blue < 0) blue = 0; if (blue > 255) blue = 255; color.setRgb(red, green, blue); color.setAlpha(120); } colorPicker->setEventColor(type, color); //QColor(0, 85, 255, 80) eventColorList[colorChoice] = color; } settings.endArray(); settings.endGroup(); colorPicker->saveSettings(); return 0; } } sigviewer-0.6.4/src/file_handling/file_signal_reader.h000066400000000000000000000027241345753661000230650ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_SIGNAL_READER_H #define FILE_SIGNAL_READER_H #include "basic_header.h" #include "base/signal_event.h" #include "base/data_block.h" #include "application_context_impl.h" #include #include #include #include #include class QString; namespace sigviewer { //----------------------------------------------------------------------------- /// FileSignalReader /// /// abstract base class for reading signals from a file class FileSignalReader { public: typedef QVector SignalEventVector; virtual ~FileSignalReader() {} virtual QPair createInstance (QString const& file_path) = 0; virtual QSharedPointer getSignalData (ChannelID channel_id, size_t start_sample, size_t length) const = 0; virtual QList > getEvents () const = 0; virtual QSharedPointer getBasicHeader () = 0; virtual QSharedPointer getBasicHeader () const = 0; int setEventTypeColors(); /*!< Set a distinct color for each event type. */ protected: FileSignalReader () {} private: Q_DISABLE_COPY(FileSignalReader) }; } #endif sigviewer-0.6.4/src/file_handling/file_signal_reader_factory.cpp000066400000000000000000000010521345753661000251400ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "file_signal_reader_factory.h" namespace sigviewer { //------------------------------------------------------------------------- FileSignalReaderFactory* FileSignalReaderFactory::getInstance () { //auto_ptr is deprecated static std::unique_ptr instance; if (!instance.get()) instance.reset(new FileSignalReaderFactory); return instance.get(); } } sigviewer-0.6.4/src/file_handling/file_signal_reader_factory.h000066400000000000000000000012331345753661000246060ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl // file_signal_reader_factory.h #ifndef FILE_SIGNAL_READER_FACTORY_H #define FILE_SIGNAL_READER_FACTORY_H #include "file_handler_factory.h" #include "file_signal_reader.h" #include #include #include namespace sigviewer { //------------------------------------------------------------------------- // file signal reader Factory as singleton class FileSignalReaderFactory : public FileHandlerFactory { public: static FileSignalReaderFactory* getInstance (); }; } #endif sigviewer-0.6.4/src/file_handling/file_signal_writer.h000066400000000000000000000034061345753661000231350ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_SIGNAL_WRITER_H #define FILE_SIGNAL_WRITER_H #include "file_signal_reader.h" #include "file_context.h" #include "event_manager.h" #include "channel_manager.h" #include "base/signal_event.h" namespace sigviewer { // abstract signal writer class FileSignalWriter { public: virtual ~FileSignalWriter() {} //------------------------------------------------------------------------- virtual QPair createInstance (QString const& file_path) = 0; //------------------------------------------------------------------------- virtual bool supportsSavingEvents () const {return false;} //------------------------------------------------------------------------- virtual QString saveEventsToSignalFile (QSharedPointer, std::set const& types) = 0; //------------------------------------------------------------------------- virtual QString save (QSharedPointer file_context) { QSharedPointer event_manager = file_context->getEventManager(); if (event_manager.isNull()) return save (file_context, std::set ()); else return save (file_context, event_manager->getEventTypes ("")); } //------------------------------------------------------------------------- virtual QString save (QSharedPointer file_context, std::set const& types) = 0; protected: FileSignalWriter () {} private: Q_DISABLE_COPY(FileSignalWriter) }; } #endif sigviewer-0.6.4/src/file_handling/file_signal_writer_factory.cpp000066400000000000000000000007551345753661000252230ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "file_signal_writer_factory.h" namespace sigviewer { // get instance FileSignalWriterFactory* FileSignalWriterFactory::getInstance() { //auto_ptr is deprecated static std::unique_ptr instance; if (!instance.get()) instance.reset(new FileSignalWriterFactory); return instance.get(); } } sigviewer-0.6.4/src/file_handling/file_signal_writer_factory.h000066400000000000000000000010141345753661000246550ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_SIGNAL_WRITER_FACTORY_H #define FILE_SIGNAL_WRITER_FACTORY_H #include "file_signal_writer.h" #include "file_handler_factory.h" #include namespace sigviewer { // file signal reader Factory as singleton class FileSignalWriterFactory : public FileHandlerFactory { public: static FileSignalWriterFactory* getInstance(); }; } #endif sigviewer-0.6.4/src/file_handling_impl/000077500000000000000000000000001345753661000201325ustar00rootroot00000000000000sigviewer-0.6.4/src/file_handling_impl/biosig_basic_header.cpp000066400000000000000000000121271345753661000245660ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "biosig_basic_header.h" #include "xdf_reader.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- BiosigBasicHeader::BiosigBasicHeader (HDRTYPE* raw_header, QString const& file_path) : BasicHeader (file_path), number_samples_ (raw_header->NRec * raw_header->SPR) { if (raw_header->EVENT.CodeDesc) { for (unsigned index = 0; index < raw_header->EVENT.LenCodeDesc; index++) { if (raw_header->EVENT.CodeDesc[index]) user_defined_event_map_[index] = QString(raw_header->EVENT.CodeDesc[index]); } } setFileTypeString (QString (GetFileTypeString(raw_header->TYPE)).append(" v").append(QString::number(raw_header->VERSION))); float64 sampling_rate = raw_header->SampleRate; setSampleRate (sampling_rate); readChannelsInfo (raw_header); readPatientInfo (raw_header); readRecordingInfo (raw_header); } //!alternative for XDF--------------------------------------------------------- BiosigBasicHeader::BiosigBasicHeader (QString file_format, QString const& file_path) : BasicHeader (file_path), number_samples_ (XDFdata->totalLen) { if (XDFdata->dictionary.size()) { for (unsigned index = 0; index < XDFdata->dictionary.size(); index++) { //below we use index+1 because in SigViewer, 0 is reserved for a special event type. //thus we count from 1 user_defined_event_map_[index + 1] = QString::fromStdString(XDFdata->dictionary[index]); } } QString fileType = "XDF v" + QString::number(XDFdata->version, 'f', 1); setFileTypeString (fileType); float64 sampling_rate = XDFdata->majSR; setSampleRate (sampling_rate); readChannelsInfo (file_format); } //----------------------------------------------------------------------------- size_t BiosigBasicHeader::getNumberOfSamples () const { return ceil(static_cast(number_samples_)); } //----------------------------------------------------------------------------- QMap BiosigBasicHeader::getNamesOfUserSpecificEvents () const { return user_defined_event_map_; } //----------------------------------------------------------------------------- void BiosigBasicHeader::readChannelsInfo (HDRTYPE const* raw_header) { unsigned ch = 0; for (unsigned channel_index = 0; channel_index < raw_header->NS; channel_index++) if (raw_header->CHANNEL[channel_index].OnOff) { QSharedPointer channel(new SignalChannel(channel_index, raw_header)); addChannel(ch++, channel); } } //------------------------------------------------------------------------- void BiosigBasicHeader::readChannelsInfo (QString file_format) { unsigned ch = 0; for (unsigned channel_index = 0; channel_index < XDFdata->totalCh; channel_index++) { QSharedPointer channel(new SignalChannel(channel_index, file_format)); addChannel(ch++, channel); } } //------------------------------------------------------------------------- void BiosigBasicHeader::readPatientInfo (HDRTYPE const* raw_header) { switch (raw_header->Patient.Handedness) { case 1: addPatientInfo ("Handedness", "Right"); break; case 2: addPatientInfo ("Handedness", "Left"); break; case 3: addPatientInfo ("Handedness", "Equal"); break; } switch (raw_header->Patient.Sex) { case 1: addPatientInfo ("Sex", "Male"); break; case 2: addPatientInfo ("Sex", "Female"); break; } switch (raw_header->Patient.Smoking) { case 1: addPatientInfo ("Smoking", "No"); break; case 2: addPatientInfo ("Smoking", "Yes"); break; } switch (raw_header->Patient.Smoking) { case 1: addPatientInfo ("Smoking", "No"); break; case 2: addPatientInfo ("Smoking", "Yes"); break; } QString patient_id; for (unsigned i = 0; i < MAX_LENGTH_PID && raw_header->Patient.Id[i]; i++) patient_id.append (raw_header->Patient.Id[i]); addPatientInfo ("Id", patient_id.trimmed()); if (raw_header->Patient.Birthday) { time_t birthday_t = mktime(gdf_time2tm_time (raw_header->Patient.Birthday)); addPatientInfo ("Birthday", QString (ctime(&birthday_t)).trimmed()); } if (raw_header->Patient.Weight) addPatientInfo ("Weight", QString::number(raw_header->Patient.Weight).append("kg")); if (raw_header->Patient.Height) addPatientInfo ("Height", QString::number(raw_header->Patient.Height).append("cm")); } //------------------------------------------------------------------------- void BiosigBasicHeader::readRecordingInfo (HDRTYPE const* raw_header) { if (raw_header->T0) { time_t recording_t = mktime(gdf_time2tm_time (raw_header->T0)); addRecordingInfo("Recording Time", QString (ctime(&recording_t)).trimmed()); } } } sigviewer-0.6.4/src/file_handling_impl/biosig_basic_header.h000066400000000000000000000032051345753661000242300ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BIOSIG_BASIC_HEADER_H #define BIOSIG_BASIC_HEADER_H #include "file_handling/basic_header.h" #include "biosig.h" namespace sigviewer { class BiosigBasicHeader : public BasicHeader { public: //------------------------------------------------------------------------- BiosigBasicHeader (HDRTYPE* raw_header, QString const& file_path); //!Alternative constructor for XDF----------------------------------------- BiosigBasicHeader (QString file_format, QString const& file_path); //------------------------------------------------------------------------- virtual size_t getNumberOfSamples () const; //------------------------------------------------------------------------- virtual QMap getNamesOfUserSpecificEvents () const; private: //------------------------------------------------------------------------- void readChannelsInfo (HDRTYPE const* raw_header); //!alternative functions for XDF------------------------------------------- void readChannelsInfo (QString file_format); //------------------------------------------------------------------------- void readPatientInfo (HDRTYPE const* raw_header); //------------------------------------------------------------------------- void readRecordingInfo (HDRTYPE const* raw_header); unsigned number_samples_; QMap user_defined_event_map_; QMap > channels_; }; } #endif // BIOSIG_BASIC_HEADER_H sigviewer-0.6.4/src/file_handling_impl/biosig_reader.cpp000066400000000000000000000214561345753661000234440ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "biosig_reader.h" #include "biosig_basic_header.h" #include "file_handler_factory_registrator.h" #include "gui/progress_bar.h" #include "base/fixed_data_block.h" #include using namespace std; namespace sigviewer { //----------------------------------------------------------------------------- FILE_SIGNAL_READER_REGISTRATION(gdf, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(edf, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(bdf, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(dat, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(cnt, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(vhdr, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(bkr, BioSigReader); FILE_SIGNAL_READER_REGISTRATION(evt, BioSigReader); FILE_SIGNAL_READER_DEFAULT_REGISTRATION(BioSigReader); //----------------------------------------------------------------------------- BioSigReader::BioSigReader() : basic_header_ (0), biosig_header_ (0), buffered_all_channels_ (false), buffered_all_events_ (false) { qDebug () << "Constructed BioSigReader"; // nothing to do here } //----------------------------------------------------------------------------- BioSigReader::~BioSigReader() { doClose(); } //----------------------------------------------------------------------------- QPair BioSigReader::createInstance (QString const& file_path) { BioSigReader* reader (new BioSigReader); if (file_path.section('.', -1) == "evt") reader->buffered_all_channels_ = true; QString error = reader->open (file_path); if (error.size() > 0) { qDebug () << error; return QPair (0, error); } else return QPair (reader, ""); } //----------------------------------------------------------------------------- void BioSigReader::doClose () const { if (biosig_header_) destructHDR (biosig_header_); biosig_header_ = NULL; } //----------------------------------------------------------------------------- QSharedPointer BioSigReader::getSignalData (ChannelID channel_id, size_t start_sample, size_t length) const { QMutexLocker lock (&mutex_); if (!buffered_all_channels_) bufferAllChannels(); if (!channel_map_.contains(channel_id)) return QSharedPointer (0); if (length == basic_header_->getNumberOfSamples() && start_sample == 0) return channel_map_[channel_id]; else return channel_map_[channel_id]->createSubBlock (start_sample, length); } //----------------------------------------------------------------------------- QList > BioSigReader::getEvents () const { QMutexLocker lock (&mutex_); QList > empty_list; if (!biosig_header_) return empty_list; if (!buffered_all_events_) bufferAllEvents(); return events_; } //----------------------------------------------------------------------------- QString BioSigReader::open (QString const& file_name) { QMutexLocker lock (&mutex_); return loadFixedHeader (file_name); } //----------------------------------------------------------------------------- QString BioSigReader::loadFixedHeader(const QString& file_name) { QMutexLocker locker (&biosig_access_lock_); char *c_file_name = new char[file_name.length() + 1]; strcpy (c_file_name, file_name.toLocal8Bit ().data()); c_file_name[file_name.length()] = '\0'; tzset(); if(biosig_header_==NULL) { biosig_header_ = constructHDR (0,0); biosig_header_->FLAG.UCAL = 0; biosig_header_->FLAG.OVERFLOWDETECTION = 1; } biosig_header_ = sopen(c_file_name, "r", biosig_header_ ); basic_header_ = QSharedPointer (new BiosigBasicHeader (biosig_header_, file_name)); if (!QFile::exists(file_name)) { sclose (biosig_header_); destructHDR(biosig_header_); biosig_header_ = NULL; delete[] c_file_name; qDebug() << "File doesn't exist."; QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setText("File does not exist."); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); return "non-exist"; } #if (BIOSIG_VERSION < 10400) if (biosig_header_ == NULL || serror(biosig_header_)) #else if (biosig_header_ == NULL || serror2(biosig_header_)) #endif { sclose (biosig_header_); destructHDR(biosig_header_); biosig_header_ = NULL; delete[] c_file_name; return "file not supported"; } convert2to4_eventtable(biosig_header_); delete[] c_file_name; c_file_name = NULL; basic_header_->setNumberEvents(biosig_header_->EVENT.N); if (biosig_header_->EVENT.SampleRate) basic_header_->setEventSamplerate(biosig_header_->EVENT.SampleRate); else basic_header_->setEventSamplerate(biosig_header_->SampleRate); setChannelColors(); setEventTypeColors(); return ""; } //----------------------------------------------------------------------------- QSharedPointer BioSigReader::getBasicHeader () { //QMutexLocker lock (&mutex_); return basic_header_; } //----------------------------------------------------------------------------- int BioSigReader::setChannelColors() { QSharedPointer colorPicker = ApplicationContextImpl::getInstance()->color_manager_; for (size_t i = 0; i < basic_header_->getNumberChannels(); i++) colorPicker->setChannelColor(i, colorPicker->getDefaultChannelColor()); colorPicker->saveSettings(); return 0; } //----------------------------------------------------------------------------- void BioSigReader::bufferAllChannels () const { size_t numberOfSamples = biosig_header_->NRec * biosig_header_->SPR; biosig_data_type* read_data = new biosig_data_type[numberOfSamples * basic_header_->getNumberChannels()]; biosig_header_->FLAG.ROW_BASED_CHANNELS = 0; QString progress_name = QObject::tr("Loading data..."); sread(read_data, 0, biosig_header_->NRec, biosig_header_); for (unsigned channel_id = 0; channel_id < basic_header_->getNumberChannels(); ++channel_id) { ProgressBar::instance().increaseValue (1, progress_name); QSharedPointer > raw_data(new QVector (numberOfSamples, NAN)); for (size_t data_index = 0; data_index < numberOfSamples; data_index++) raw_data->operator [](data_index) = read_data[data_index + channel_id * numberOfSamples]; QSharedPointer data_block(new FixedDataBlock(raw_data, basic_header_->getSampleRate())); channel_map_[channel_id] = data_block; } buffered_all_channels_ = true; if (buffered_all_events_) doClose(); delete[] read_data; } //------------------------------------------------------------------------- void BioSigReader::bufferAllEvents () const { unsigned number_events = biosig_header_->EVENT.N; // Hack Hack: Transforming Events to have the same sample rate as the signals double rate_transition; if ( ( biosig_header_->EVENT.SampleRate <= 0.0) || ( biosig_header_->EVENT.SampleRate != biosig_header_->EVENT.SampleRate)) rate_transition = 1; else rate_transition = basic_header_->getEventSamplerate() / biosig_header_->EVENT.SampleRate; for (unsigned index = 0; index < number_events; index++) { QSharedPointer event (new SignalEvent (biosig_header_->EVENT.POS[index] * rate_transition, biosig_header_->EVENT.TYP[index], biosig_header_->EVENT.SampleRate * rate_transition, -1)); if (biosig_header_->EVENT.CHN) { if (biosig_header_->EVENT.CHN[index] == 0) event->setChannel (UNDEFINED_CHANNEL); else event->setChannel (biosig_header_->EVENT.CHN[index] - 1); if (biosig_header_->EVENT.TYP[index] != 0x7fff) event->setDuration (biosig_header_->EVENT.DUR[index] * rate_transition); else // sparse samples (Typ=0x7fff) do not have a duration, but the duration field is used to store the sample value event->setDuration(0); } else { event->setChannel(UNDEFINED_CHANNEL); event->setDuration (1); } events_.append (event); } buffered_all_events_ = true; if (buffered_all_channels_) doClose(); } } sigviewer-0.6.4/src/file_handling_impl/biosig_reader.h000066400000000000000000000047011345753661000231030ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BIOSIG_READER_H_ #define BIOSIG_READER_H_ #include "file_handling/file_signal_reader.h" namespace sigviewer { class BioSigReader : public FileSignalReader { public: BioSigReader (); virtual ~BioSigReader(); //------------------------------------------------------------------------- QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual QSharedPointer getSignalData (ChannelID channel_id, size_t start_sample, size_t length) const; //------------------------------------------------------------------------- virtual QList > getEvents () const; //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader (); //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader () const {return basic_header_;} //------------------------------------------------------------------------- int setChannelColors(); /*!< Set colors for all channels. */ private: //------------------------------------------------------------------------- QString open (QString const& file_name); //------------------------------------------------------------------------- void bufferAllChannels () const; //------------------------------------------------------------------------- void applyFilters (double* &in, double* &out, int length) const; //------------------------------------------------------------------------- void bufferAllEvents () const; Q_DISABLE_COPY(BioSigReader) QString loadFixedHeader(const QString& file_name); void doClose () const; QSharedPointer basic_header_; mutable QMutex mutex_; mutable QMutex biosig_access_lock_; mutable HDRTYPE* biosig_header_; mutable bool buffered_all_channels_; mutable bool buffered_all_events_; mutable QMap > channel_map_; mutable QList > events_; }; } #endif sigviewer-0.6.4/src/file_handling_impl/biosig_writer.cpp000066400000000000000000000111541345753661000235100ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "biosig_writer.h" #include "file_handler_factory_registrator.h" namespace sigviewer { FILE_SIGNAL_WRITER_REGISTRATION(gdf, BioSigWriter); //----------------------------------------------------------------------------- BioSigWriter::BioSigWriter () : target_type_ (GDF) { file_formats_support_event_saving_.insert(GDF1); file_formats_support_event_saving_.insert(GDF); } //----------------------------------------------------------------------------- BioSigWriter::BioSigWriter (FileFormat target_type, QString new_file_path) : target_type_ (target_type), new_file_path_ (new_file_path) { // nothing to do here } //------------------------------------------------------------------------- QPair BioSigWriter::createInstance (QString const& file_path) { BioSigWriter* writer (new BioSigWriter); writer->new_file_path_ = file_path; return QPair (writer, ""); } //----------------------------------------------------------------------------- bool BioSigWriter::supportsSavingEvents () const { return file_formats_support_event_saving_.count(target_type_) > 0; } //----------------------------------------------------------------------------- QString BioSigWriter::saveEventsToSignalFile (QSharedPointer event_manager, std::set const& types) { if (file_formats_support_event_saving_.count(target_type_) == 0) return QObject::tr("Cannot write events to this file type!"); QList events; foreach (EventType type, types) events.append(event_manager->getEvents(type)); unsigned number_events = events.size(); qDebug () << "number_events = " <getNumberOfEvents() = " << event_manager->getNumberOfEvents(); HDRTYPE* header = constructHDR (0, number_events); qDebug () << "BioSigWriter::saveEventsToSignalFile to " << new_file_path_; header = sopen (new_file_path_.toStdString().c_str(), "r", header); header->EVENT.SampleRate = event_manager->getSampleRate(); header->EVENT.N = number_events; header->EVENT.TYP = (decltype(header->EVENT.TYP)) realloc(header->EVENT.TYP,number_events * sizeof(decltype(*header->EVENT.TYP))); header->EVENT.POS = (decltype(header->EVENT.POS)) realloc(header->EVENT.POS,number_events * sizeof(decltype(*header->EVENT.POS))); header->EVENT.CHN = (decltype(header->EVENT.CHN)) realloc(header->EVENT.CHN,number_events * sizeof(decltype(*header->EVENT.CHN))); header->EVENT.DUR = (decltype(header->EVENT.DUR)) realloc(header->EVENT.DUR,number_events * sizeof(decltype(*header->EVENT.DUR))); for (unsigned index = 0; index < number_events; index++) { QSharedPointer event = event_manager->getEvent(events[index]); if (event->getChannel() == UNDEFINED_CHANNEL) header->EVENT.CHN[index] = 0; else header->EVENT.CHN[index] = event->getChannel() + 1; header->EVENT.TYP[index] = event->getType (); header->EVENT.POS[index] = event->getPosition(); header->EVENT.DUR[index] = event->getDuration(); } int error = sflush_gdf_event_table (header); if (error) QMessageBox::critical(0, "Events not saved!!!", QString::number(error)); destructHDR (header); return ""; } //----------------------------------------------------------------------------- QString BioSigWriter::save (QSharedPointer file_context, std::set const& types) { QString source_file_path = file_context->getFilePathAndName(); HDRTYPE* read_header = sopen (source_file_path.toStdString().c_str(), "r", NULL); uint32 read_data_size = read_header->NS * read_header->NRec * read_header->SPR; biosig_data_type* read_data = new biosig_data_type[read_data_size]; sread (read_data, 0, read_data_size, read_header); read_header->TYPE = target_type_; if (target_type_ == GDF) read_header->VERSION = 2; HDRTYPE* write_header = sopen (new_file_path_.toStdString().c_str(), "w", read_header); qDebug() << "write NELEM = " << swrite (read_data, read_header->NRec, write_header); delete[] read_data; sclose(write_header); sclose(read_header); destructHDR (write_header); if (file_formats_support_event_saving_.count(target_type_)) saveEventsToSignalFile (file_context->getEventManager (), types); return ""; } } sigviewer-0.6.4/src/file_handling_impl/biosig_writer.h000066400000000000000000000032501345753661000231530ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BIOIGWRITER_H_ #define BIOIGWRITER_H_ #include "file_handling/file_signal_writer.h" #include "biosig.h" namespace sigviewer { //----------------------------------------------------------------------------- class BioSigWriter : public FileSignalWriter { public: //------------------------------------------------------------------------- BioSigWriter (); //------------------------------------------------------------------------- virtual QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual ~BioSigWriter() {} //------------------------------------------------------------------------- virtual bool supportsSavingEvents () const; //------------------------------------------------------------------------- virtual QString saveEventsToSignalFile (QSharedPointer, std::set const& types); //------------------------------------------------------------------------- virtual QString save (QSharedPointer file_context, std::set const& types); private: //------------------------------------------------------------------------- BioSigWriter (FileFormat target_type, QString new_file_path); FileFormat target_type_; QString new_file_path_; std::set file_formats_support_event_saving_; mutable QMutex mutex_; }; } #endif sigviewer-0.6.4/src/file_handling_impl/channel_manager_impl.cpp000066400000000000000000000067071345753661000247730ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "channel_manager_impl.h" namespace sigviewer { //----------------------------------------------------------------------------- ChannelManagerImpl::ChannelManagerImpl (FileSignalReader* file_signal_reader) : reader_ (file_signal_reader) { setXAxisUnitLabel ("s"); } //----------------------------------------------------------------------------- ChannelManagerImpl::~ChannelManagerImpl () { delete reader_; } //------------------------------------------------------------------------- std::set ChannelManagerImpl::getChannels () const { std::set channels; for (ChannelID id = 0; id < static_cast(reader_->getBasicHeader()->getNumberChannels()); ++id) channels.insert(id); return channels; } //----------------------------------------------------------------------------- uint32 ChannelManagerImpl::getNumberChannels () const { return reader_->getBasicHeader()->getNumberChannels(); } //------------------------------------------------------------------------- QString ChannelManagerImpl::getChannelLabel (ChannelID id) const { if (id == UNDEFINED_CHANNEL) return QObject::tr("All Channels"); else if (!reader_->getBasicHeader()->getChannel (id).isNull()) return reader_->getBasicHeader()->getChannel (id)->getLabel(); else return QObject::tr("Invalid Channel"); } //------------------------------------------------------------------------- QString ChannelManagerImpl::getChannelLabel (ChannelID id, int streamNumber) const { if (id == UNDEFINED_CHANNEL) { if (streamNumber == -1) return QObject::tr("All Channels"); else return QObject::tr("Stream ").append(QString::number(streamNumber+1));//+1 for user's convenience (1 based instead 0 based) } else if (!reader_->getBasicHeader()->getChannel (id).isNull()) return reader_->getBasicHeader()->getChannel (id)->getLabel(); else return QObject::tr("Invalid Channel"); } //------------------------------------------------------------------------- QString ChannelManagerImpl::getChannelYUnitString (ChannelID id) const { if (id != UNDEFINED_CHANNEL) return reader_->getBasicHeader()->getChannel(id)->getPhysicalDim(); else return ""; // reader_->getBasicHeader()->get } //----------------------------------------------------------------------------- QSharedPointer ChannelManagerImpl::getData (ChannelID id, unsigned start_pos, unsigned length) const { if (((start_pos + length) > getNumberSamples()) || length == 0) return QSharedPointer (0); else return reader_->getSignalData (id, start_pos, length); } //----------------------------------------------------------------------------- float64 ChannelManagerImpl::getDurationInSec () const { return reader_->getBasicHeader()->getNumberOfSamples() / reader_->getBasicHeader()->getSampleRate(); } //----------------------------------------------------------------------------- size_t ChannelManagerImpl::getNumberSamples () const { return reader_->getBasicHeader()->getNumberOfSamples(); } //----------------------------------------------------------------------------- float64 ChannelManagerImpl::getSampleRate () const { return reader_->getBasicHeader()->getSampleRate(); } } sigviewer-0.6.4/src/file_handling_impl/channel_manager_impl.h000066400000000000000000000046301345753661000244310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CHANNEL_MANAGER_IMPL_H #define CHANNEL_MANAGER_IMPL_H #include "file_handling/channel_manager.h" #include "file_handling/file_signal_reader.h" namespace sigviewer { //----------------------------------------------------------------------------- /// ChannelManagerImpl /// /// implementation of ChannelManager /// class ChannelManagerImpl : public ChannelManager { public: //--------------------------------------------------------------------------------------------- /// @param file_signal_reader the ChannelManagerImpl takes ownership of the given FileSignalReader /// and destroys it if the ChannelManagerImpl is destructed ChannelManagerImpl (FileSignalReader* file_signal_reader); //--------------------------------------------------------------------------------------------- virtual ~ChannelManagerImpl (); //------------------------------------------------------------------------- virtual std::set getChannels () const; //------------------------------------------------------------------------- virtual uint32 getNumberChannels () const; //------------------------------------------------------------------------- virtual QString getChannelLabel (ChannelID id) const; //------------------------------------------------------------------------- virtual QString getChannelLabel (ChannelID id, int streamNumber) const; //------------------------------------------------------------------------- virtual QString getChannelYUnitString (ChannelID id) const; //------------------------------------------------------------------------- virtual QSharedPointer getData (ChannelID id, unsigned start_pos, unsigned length) const; //------------------------------------------------------------------------- virtual float64 getDurationInSec() const; //------------------------------------------------------------------------- virtual size_t getNumberSamples() const; //------------------------------------------------------------------------- virtual float64 getSampleRate() const; private: FileSignalReader* reader_; }; } #endif sigviewer-0.6.4/src/file_handling_impl/down_sampling_thread.cpp000066400000000000000000000163011345753661000250270ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "down_sampling_thread.h" #include #include "signal_processing/SPUC/butterworth.h" #include "base/fixed_data_block.h" #include "gui/background_processes.h" #include #include #include namespace SigViewer_ { QString DownSamplingThread::PROCESS_NAME_ ("Downsampling..."); //----------------------------------------------------------------------------- DownSamplingThread::DownSamplingThread (QList > data, unsigned downsampling_step, unsigned downsampling_max) : basis_data_ (data), data_ (data), downsampling_step_ (downsampling_step), downsampling_max_ (downsampling_max) { } //----------------------------------------------------------------------------- DownSamplingThread::DownSamplingThread (QSharedPointer channel_manager, unsigned downsampling_step, unsigned downsampling_max) : channel_manager_ (channel_manager), downsampling_step_ (downsampling_step), downsampling_max_ (downsampling_max) { } //----------------------------------------------------------------------------- DownSamplingThread::~DownSamplingThread () { BackgroundProcesses::instance().removeProcess (PROCESS_NAME_); } //----------------------------------------------------------------------------- void DownSamplingThread::run () { running_ = true; qDebug () << "DownSamplingThread::run started downsampling; QThread::currentThread = " << QThread::currentThread(); if (!channel_manager_.isNull()) minMaxDownsampling (); else downsampleAllOnBasisData (); //downsampleOnDownsampledData (); qDebug () << "DownSamplingThread::run FINISHED!"; running_ = false; } //------------------------------------------------------------------------- void DownSamplingThread::minMaxDownsampling () { } //------------------------------------------------------------------------- void DownSamplingThread::downsampleAllOnBasisData () { QMap > > > raw_downsampled_data; QMap > > > low_pass_filters; QMap > sample_rates; unsigned max_channel_length = 0; for (unsigned downsampling_factor = downsampling_step_; downsampling_factor < downsampling_max_; downsampling_factor *= downsampling_step_) { for (int channel = 0; channel < data_.size(); channel++) { max_channel_length = std::max (max_channel_length, basis_data_[channel]->size()); sample_rates[downsampling_factor].append (basis_data_[channel]->getSampleRatePerUnit() / downsampling_factor); QSharedPointer > raw_data_vector (new QVector (static_cast(basis_data_[channel]->size () / downsampling_factor) + 1)); QSharedPointer downsampled_data (new FixedDataBlock (raw_data_vector, sample_rates[downsampling_factor][channel])); basis_data_[channel]->addDownSampledVersion (downsampled_data, downsampling_factor); raw_downsampled_data[downsampling_factor].append (raw_data_vector); low_pass_filters[downsampling_factor].append (QSharedPointer > (new SPUC::butterworth (0.5 / downsampling_factor, 4, 3))); } } BackgroundProcesses::instance().addProcess (PROCESS_NAME_, max_channel_length); for (unsigned sample_index = 0; sample_index < max_channel_length; sample_index++) { for (int channel = 0; channel < basis_data_.size(); channel++) { if (basis_data_[channel]->size() > sample_index) { foreach (unsigned downsampling_factor, low_pass_filters.keys()) { float32 value = low_pass_filters[downsampling_factor][channel]->clock (basis_data_[channel]->operator [](sample_index)); if ((sample_index + 1) % downsampling_factor == 0) raw_downsampled_data[downsampling_factor][channel]->operator []((sample_index + 1) / downsampling_factor) = value; } } } if (sample_index % 100 == 0) BackgroundProcesses::instance().setProcessState (PROCESS_NAME_, sample_index); } BackgroundProcesses::instance().removeProcess (PROCESS_NAME_); } //------------------------------------------------------------------------- void DownSamplingThread::downsampleOnDownsampledData () { for (unsigned downsampling_factor = downsampling_step_; downsampling_factor < downsampling_max_; downsampling_factor *= downsampling_step_) { unsigned max_channel_length = 0; QVector > > raw_downsampled_data; QVector > > low_pass_filters; QVector sample_rates_; for (int channel = 0; channel < data_.size(); channel++) { max_channel_length = std::max (max_channel_length, data_[channel]->size()); raw_downsampled_data.append (QSharedPointer > (new QVector (static_cast(data_[channel]->size () / downsampling_step_) + 1))); low_pass_filters.append (QSharedPointer > (new SPUC::butterworth (0.9 / downsampling_step_, 4, 3))); sample_rates_.append (data_[channel]->getSampleRatePerUnit() / downsampling_step_); } for (unsigned sample_index = 0; sample_index < max_channel_length; sample_index++) { for (int channel = 0; channel < data_.size(); channel++) { if (data_[channel]->size() > sample_index) { float32 value = low_pass_filters[channel]->clock (data_[channel]->operator [](sample_index)); if ((sample_index + 1) % downsampling_step_ == 0) raw_downsampled_data[channel]->operator []((sample_index + 1) / downsampling_step_) = value; } } } data_.clear (); low_pass_filters.clear(); for (int channel = 0; channel < raw_downsampled_data.size(); channel++) { QSharedPointer downsampled_data (new FixedDataBlock (raw_downsampled_data[channel], sample_rates_[channel])); basis_data_[channel]->addDownSampledVersion (downsampled_data, downsampling_factor); data_.append (downsampled_data); } } } } sigviewer-0.6.4/src/file_handling_impl/down_sampling_thread.h000066400000000000000000000052511345753661000244760ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef DOWN_SAMPLING_THREAD_H #define DOWN_SAMPLING_THREAD_H #include "base/data_block.h" #include "file_handling/channel_manager.h" #include #include #include #include #include namespace SigViewer_ { class DownSamplingThread : public QThread { Q_OBJECT public: //------------------------------------------------------------------------- DownSamplingThread (QList > data, unsigned downsampling_step, unsigned downsampling_max); //------------------------------------------------------------------------- DownSamplingThread (QSharedPointer channel_manager, unsigned downsampling_step, unsigned downsampling_max); //------------------------------------------------------------------------- virtual ~DownSamplingThread (); signals: //------------------------------------------------------------------------- void downsamplingDataFinished (QSharedPointer data, ChannelID channel, unsigned factor); private: //------------------------------------------------------------------------- virtual void run (); //------------------------------------------------------------------------- void minMaxDownsampling (); //------------------------------------------------------------------------- void downsampleAllOnBasisData (); //------------------------------------------------------------------------- void downsampleOnDownsampledData (); //------------------------------------------------------------------------- QSharedPointer channel_manager_; QList > basis_data_; QList > data_; QList > new_data_; unsigned downsampling_step_; unsigned downsampling_max_; bool running_; static QString PROCESS_NAME_; }; } #endif // DOWN_SAMPLING_THREAD_H sigviewer-0.6.4/src/file_handling_impl/event_manager_impl.cpp000066400000000000000000000240211345753661000244710ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_manager_impl.h" #include namespace sigviewer { //----------------------------------------------------------------------------- EventManagerImpl::EventManagerImpl (FileSignalReader const& reader) : max_event_position_ (reader.getBasicHeader()->getNumberOfSamples()), caller_mutex_ (new QMutex) { file_type_ = reader.getBasicHeader()->getFileTypeString(); QList > signal_events = reader.getEvents (); next_free_id_ = 0; for (int index = 0; index < signal_events.size(); index++) { event_map_.insert (next_free_id_, QSharedPointer ( new SignalEvent(*(signal_events[index]), next_free_id_))); mutex_map_.insert (next_free_id_, QSharedPointer ( new QMutex)); position_event_map_.insertMulti (signal_events[index]->getPosition (), next_free_id_); if (!event_table_reader_.entryExists (signal_events[index]->getType())) event_table_reader_.addEntry (signal_events[index]->getType()); next_free_id_++; } sample_rate_ = reader.getBasicHeader()->getEventSamplerate(); QMap event_names = reader.getBasicHeader()->getNamesOfUserSpecificEvents(); for (QMap::iterator name_iter = event_names.begin(); name_iter != event_names.end(); ++name_iter) event_table_reader_.setEventName (name_iter.key(), name_iter.value()); } //----------------------------------------------------------------------------- EventManagerImpl::~EventManagerImpl () { event_table_reader_.restoreEventNames (); delete caller_mutex_; } //----------------------------------------------------------------------------- QSharedPointer EventManagerImpl::getEvent (EventID id) const { QMutexLocker locker (caller_mutex_); EventMap::ConstIterator event_it = event_map_.find (id); if (event_it == event_map_.end()) return QSharedPointer (0); else return event_it.value(); } //----------------------------------------------------------------------------- QSharedPointer EventManagerImpl::getAndLockEventForEditing (EventID id) { QMutexLocker locker (caller_mutex_); EventMap::Iterator event_it = event_map_.find (id); if (event_it == event_map_.end()) return QSharedPointer (0); else { temp_event_position_map_.insert (id, event_it.value()->getPosition ()); mutex_map_[id]->lock (); return event_it.value(); } } //----------------------------------------------------------------------------- void EventManagerImpl::updateAndUnlockEvent (EventID id) { if (!mutex_map_.contains (id)) return; position_event_map_.remove (temp_event_position_map_[id], id); temp_event_position_map_.remove (id); position_event_map_.insertMulti (event_map_[id]->getPosition (), id); mutex_map_[id]->unlock (); emit eventChanged (id); emit changed (); } //----------------------------------------------------------------------------- QSharedPointer EventManagerImpl::createEvent ( ChannelID channel_id, unsigned pos, unsigned duration, EventType type, int stream_id, EventID id) { if (id == UNDEFINED_EVENT_ID) { id = next_free_id_; next_free_id_++; } else if (event_map_.contains(id)) return QSharedPointer(0); QSharedPointer new_event ( new SignalEvent(pos, type, sample_rate_, stream_id, channel_id, duration, id)); event_map_[id] = new_event; mutex_map_[id] = QSharedPointer (new QMutex); position_event_map_.insertMulti (pos, id); emit eventCreated (new_event); emit changed (); return new_event; } //----------------------------------------------------------------------------- void EventManagerImpl::removeEvent (EventID id) { qDebug () << "EventManagerImpl::removeEvent " << id; EventMap::iterator event_iter = event_map_.find (id); if (event_iter == event_map_.end()) return; position_event_map_.remove (event_map_[id]->getPosition(), id); event_map_.remove (id); mutex_map_.remove (id); qDebug () << "EventManagerImpl::removeEvent " << id << " emitting"; emit eventRemoved (id); emit changed (); qDebug () << "EventManagerImpl::removeEvent " << id << " finished"; } //----------------------------------------------------------------------------- std::set EventManagerImpl::getEventsAt (unsigned pos, ChannelID channel_id) const { QMutexLocker locker (caller_mutex_); std::set events; QSharedPointer event_ptr; foreach (uint32 position, position_event_map_.keys()) { foreach (EventID event, position_event_map_.values (position)) { event_ptr = event_map_[event]; if (event_ptr->getPosition() <= pos && event_ptr->getPosition () + event_ptr->getDuration() >= pos && (event_ptr->getChannel() == channel_id || event_ptr->getChannel() == UNDEFINED_CHANNEL)) events.insert (event); } } return events; } //----------------------------------------------------------------------------- double EventManagerImpl::getSampleRate () const { QMutexLocker locker (caller_mutex_); return sample_rate_; } //------------------------------------------------------------------------- unsigned EventManagerImpl::getMaxEventPosition () const { return max_event_position_; } //----------------------------------------------------------------------------- QString EventManagerImpl::getNameOfEventType (EventType type) const { QMutexLocker locker (caller_mutex_); return event_table_reader_.getEventName (type); } //------------------------------------------------------------------------- QString EventManagerImpl::getNameOfEvent (EventID event) const { if (event_map_.contains (event)) return event_table_reader_.getEventName (event_map_[event]->getType ()); else return ""; } //----------------------------------------------------------------------------- QList EventManagerImpl::getAllEvents () const { QMutexLocker locker (caller_mutex_); return event_map_.keys (); } //----------------------------------------------------------------------------- unsigned EventManagerImpl::getNumberOfEvents () const { QMutexLocker locker (caller_mutex_); return event_map_.size (); } //----------------------------------------------------------------------------- std::set EventManagerImpl::getEventTypes (QString group_id) const { QMutexLocker locker (caller_mutex_); if (group_id.size ()) return event_table_reader_.getEventsOfGroup (group_id); else return event_table_reader_.getAllEventTypes (); } //------------------------------------------------------------------------- std::set EventManagerImpl::getEventTypeGroupIDs () const { std::set groups; for (EventTableFileReader::StringIterator group = event_table_reader_.getGroupIdBegin(); group != event_table_reader_.getGroupIdEnd(); ++group) groups.insert (*group); return groups; } //----------------------------------------------------------------------------- QList EventManagerImpl::getEvents (EventType type) const { QMutexLocker locker (caller_mutex_); QList events; for (EventMap::ConstIterator event_iter = event_map_.begin (); event_iter != event_map_.end (); ++event_iter) if (event_iter.value ()->getType () == type) { events.push_back (event_iter.key ()); } return events; } //------------------------------------------------------------------------- EventID EventManagerImpl::getNextEventOfSameType (EventID id) const { QMutexLocker locker (caller_mutex_); if (!event_map_.contains(id)) return UNDEFINED_EVENT_ID; EventType type = event_map_[id]->getType (); PositionMap::const_iterator iter = position_event_map_.find (event_map_[id]->getPosition ()); ++iter; while (iter != position_event_map_.end ()) { foreach (EventID next_event_id, position_event_map_.values (iter.key())) if (event_map_[next_event_id]->getType () == type && next_event_id != id) return next_event_id; ++iter; } return UNDEFINED_EVENT_ID; } //------------------------------------------------------------------------- EventID EventManagerImpl::getPreviousEventOfSameType (EventID id) const { QMutexLocker locker (caller_mutex_); if (!event_map_.contains(id)) return UNDEFINED_EVENT_ID; EventType type = event_map_[id]->getType (); PositionMap::const_iterator iter = position_event_map_.find (event_map_[id]->getPosition ()); if (iter == position_event_map_.begin ()) return UNDEFINED_EVENT_ID; --iter; while (iter != position_event_map_.begin ()) { foreach (EventID previous_event_id, position_event_map_.values (iter.key())) if (event_map_[previous_event_id]->getType () == type && previous_event_id != id) return previous_event_id; --iter; } foreach (EventID previous_event_id, position_event_map_.values (iter.key())) if (event_map_[previous_event_id]->getType () == type && previous_event_id != id) return previous_event_id; return UNDEFINED_EVENT_ID; } QString EventManagerImpl::getFileType() const { return file_type_; } void EventManagerImpl::setEventName(EventType event_type_id, const QString &name) { event_table_reader_.setEventName(event_type_id, name); } } sigviewer-0.6.4/src/file_handling_impl/event_manager_impl.h000066400000000000000000000106271345753661000241450ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_MANAGER_IMPL_H #define EVENT_MANAGER_IMPL_H #include "file_handling/event_manager.h" #include "file_handling/file_signal_reader.h" #include "event_table_file_reader.h" #include #include #include namespace sigviewer { class EventManagerImpl : public EventManager { public: EventManagerImpl (FileSignalReader const& reader); virtual ~EventManagerImpl (); //------------------------------------------------------------------------- /// see base class virtual QSharedPointer getEvent (EventID id) const; //------------------------------------------------------------------------- /// see base class virtual QSharedPointer getAndLockEventForEditing (EventID id); //------------------------------------------------------------------------- /// see base class virtual void updateAndUnlockEvent (EventID id); //------------------------------------------------------------------------- /// see base class virtual QSharedPointer createEvent (ChannelID channel_id, unsigned pos, unsigned length, EventType type, int stream_id, EventID id = UNDEFINED_EVENT_ID); //------------------------------------------------------------------------- /// see base class virtual void removeEvent (EventID id); //------------------------------------------------------------------------- /// see base class virtual std::set getEventsAt (unsigned pos, ChannelID channel_id) const; //------------------------------------------------------------------------- /// see base class virtual double getSampleRate () const; //------------------------------------------------------------------------- virtual unsigned getMaxEventPosition () const; //------------------------------------------------------------------------- /// see base class virtual QString getNameOfEventType (EventType type) const; //------------------------------------------------------------------------- /// see base class virtual QString getNameOfEvent (EventID event) const; //------------------------------------------------------------------------- /// see base class virtual QList getAllEvents () const; //------------------------------------------------------------------------- /// see base class virtual unsigned getNumberOfEvents () const; //------------------------------------------------------------------------- /// see base class virtual std::set getEventTypes (QString group_id = "") const; //------------------------------------------------------------------------- virtual std::set getEventTypeGroupIDs () const; //------------------------------------------------------------------------- /// see base class virtual QList getEvents (EventType type) const; //------------------------------------------------------------------------- virtual EventID getNextEventOfSameType (EventID id) const; //------------------------------------------------------------------------- virtual EventID getPreviousEventOfSameType (EventID id) const; //------------------------------------------------------------------------- virtual QString getFileType () const; //------------------------------------------------------------------------- virtual void setEventName (EventType event_type_id, QString const& name); private: EventTableFileReader event_table_reader_; unsigned const max_event_position_; double sample_rate_; QMutex* caller_mutex_; typedef QMap > EventMap; typedef QMap > MutexMap; typedef QMultiMap PositionMap; EventMap event_map_; MutexMap mutex_map_; EventID next_free_id_; PositionMap position_event_map_; QMap temp_event_position_map_; QString file_type_; }; } #endif sigviewer-0.6.4/src/file_handling_impl/event_table_file_reader.cpp000066400000000000000000000114041345753661000254470ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_table_file_reader.h" namespace sigviewer { //------------------------------------------------------------------------------------------------- QString const EventTableFileReader::UNKNOWN_GROUP_ID = "Unknown Group"; //------------------------------------------------------------------------------------------------- EventTableFileReader::EventTableFileReader() { load(); event_group_ids_.append (UNKNOWN_GROUP_ID); group_id2name_[UNKNOWN_GROUP_ID] = UNKNOWN_GROUP_ID; } // destructor EventTableFileReader::~EventTableFileReader() { // nothing } // load bool EventTableFileReader::load() { char g[10]; uint16_t k; for (k = 0; EventCodeGroups[k].groupid < 0xffff; k++) { sprintf(g, "0x%04x", EventCodeGroups[k].groupid); QString group_id = QString(g); group_id2name_[group_id] = QString(EventCodeGroups[k].GroupDescription); event_group_ids_ << group_id; } EventItem item; for (k = 0; ETD[k].typ ; k++) { sprintf(g, "0x%04x", ETD[k].groupid); QString group_id = QString(g); item.name = QString(ETD[k].desc); item.group_id = group_id; event_type2name_[ETD[k].typ] = item; event_types_ << ETD[k].typ; } return true; } // get group id begin EventTableFileReader::StringIterator EventTableFileReader::getGroupIdBegin() const { return event_group_ids_.begin(); } // get group id end EventTableFileReader::StringIterator EventTableFileReader::getGroupIdEnd() const { return event_group_ids_.end(); } // get event types begin EventTableFileReader::IntIterator EventTableFileReader::eventTypesBegin() { return event_types_.begin(); } // get event types end EventTableFileReader::IntIterator EventTableFileReader::eventTypesEnd() { return event_types_.end(); } // get event name QString EventTableFileReader::getEventName(uint16 event_type_id) const { Int2EventItemMap::const_iterator it = event_type2name_.find(event_type_id); return it != event_type2name_.end() ? it.value().name : "NO SUCH EVENT TYPE"; } //----------------------------------------------------------------------------- void EventTableFileReader::setEventName (EventType event_type_id, QString const& name) { event_type2name_[event_type_id].name = name; } //----------------------------------------------------------------------------- void EventTableFileReader::restoreEventNames () { load(); } //----------------------------------------------------------------------------- std::set EventTableFileReader::getEventsOfGroup (QString const& group_id) const { std::set group_types; foreach (EventType event_type, event_types_) if (event_type2name_[event_type].group_id == group_id) group_types.insert (event_type); return group_types; } // get event group id QString EventTableFileReader::getEventGroupId(uint16 event_type_id) const { Int2EventItemMap::const_iterator it = event_type2name_.find(event_type_id); return it != event_type2name_.end() ? it.value().group_id : ""; } //------------------------------------------------------------------------------------------------- bool EventTableFileReader::entryExists (EventType type) const { return event_types_.contains (type); } //------------------------------------------------------------------------------------------------- void EventTableFileReader::addEntry (EventType type, QString const& name, QString group_id) { if (event_types_.contains (type)) return; event_types_.append (type); if (!event_group_ids_.contains (group_id)) group_id = UNKNOWN_GROUP_ID; EventItem item; item.group_id = group_id; if (name.size()) item.name = name; else { item.name = QString::number (type, 16); while (item.name.size() < 4) item.name.prepend ("0"); item.name.prepend("0x"); } event_type2name_[type] = item; } //------------------------------------------------------------------- std::set EventTableFileReader::getAllEventTypes () const { std::set type_set; for (IntIterator it = event_types_.begin(); it != event_types_.end(); ++it) { type_set.insert (*it); } return type_set; } // get event group name QString EventTableFileReader::getEventGroupName(const QString& group_id) const { String2StringMap::const_iterator it = group_id2name_.find(group_id); return it != group_id2name_.end() ? it.value() : ""; } } sigviewer-0.6.4/src/file_handling_impl/event_table_file_reader.h000066400000000000000000000043011345753661000251120ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TABLE_FILE_READER #define EVENT_TABLE_FILE_READER #include "base/sigviewer_user_types.h" #include "biosig.h" #include #include #include #include class QTextStream; namespace sigviewer { //----------------------------------------------------------------------------- /// /// EventTableFileReader /// /// responsible for mapping of EventType to String (name of event) class EventTableFileReader { public: typedef QList::const_iterator IntIterator; typedef QStringList::const_iterator StringIterator; EventTableFileReader(); ~EventTableFileReader(); StringIterator getGroupIdBegin() const; StringIterator getGroupIdEnd() const; QString getEventGroupName(const QString& group_id) const; IntIterator eventTypesBegin(); IntIterator eventTypesEnd(); QString getEventName (EventType event_type_id) const; void setEventName (EventType event_type_id, QString const& name); void restoreEventNames (); std::set getEventsOfGroup (QString const& group_id) const; QString getEventGroupId (EventType event_type_id) const; //--------------------------------------------------------------------------------------------- /// @return true if an the eventtablefilereader has an entry of this type; /// false if not bool entryExists (EventType type) const; //--------------------------------------------------------------------------------------------- void addEntry (EventType type, QString const& name = "", QString group_id = ""); std::set getAllEventTypes () const; private: bool load(); static QString const UNKNOWN_GROUP_ID; struct EventItem { QString name; QString group_id; }; typedef QMap Int2EventItemMap; typedef QMap String2StringMap; Q_DISABLE_COPY(EventTableFileReader) QList event_types_; QStringList event_group_ids_; Int2EventItemMap event_type2name_; String2StringMap group_id2name_; }; } #endif sigviewer-0.6.4/src/file_handling_impl/evt_writer.cpp000066400000000000000000000064101345753661000230310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "evt_writer.h" #include "file_handling/file_signal_writer_factory.h" #include "biosig.h" namespace sigviewer { //----------------------------------------------------------------------------- EVTWriter EVTWriter::prototype_instance_ (true); //----------------------------------------------------------------------------- EVTWriter::EVTWriter() { // nothing to do here } //----------------------------------------------------------------------------- EVTWriter::EVTWriter (bool) { FileSignalWriterFactory::getInstance()->registerHandler("evt", QSharedPointer(new EVTWriter)); } //----------------------------------------------------------------------------- EVTWriter::EVTWriter (QString const& new_file_path) : new_file_path_ (new_file_path) { // nothing to do here } //----------------------------------------------------------------------------- EVTWriter::~EVTWriter() { // nothing to do here } //------------------------------------------------------------------------- QPair EVTWriter::createInstance (QString const& new_file_path) { return QPair (new EVTWriter (new_file_path), ""); } //----------------------------------------------------------------------------- QString EVTWriter::save(QSharedPointer file_context, std::set const& types) { QSharedPointer event_manager = file_context->getEventManager(); QList events; foreach (EventType type, types) events.append(event_manager->getEvents(type)); unsigned number_events = events.size(); HDRTYPE* header = constructHDR (0, number_events); header->TYPE = GDF; header->VERSION = 2.0; header->SampleRate = event_manager->getSampleRate(); header->EVENT.SampleRate = event_manager->getSampleRate(); header->EVENT.N = number_events; header->EVENT.TYP = (decltype(header->EVENT.TYP)) realloc(header->EVENT.TYP,number_events * sizeof(decltype(*header->EVENT.TYP))); header->EVENT.POS = (decltype(header->EVENT.POS)) realloc(header->EVENT.POS,number_events * sizeof(decltype(*header->EVENT.POS))); header->EVENT.CHN = (decltype(header->EVENT.CHN)) realloc(header->EVENT.CHN,number_events * sizeof(decltype(*header->EVENT.CHN))); header->EVENT.DUR = (decltype(header->EVENT.DUR)) realloc(header->EVENT.DUR,number_events * sizeof(decltype(*header->EVENT.DUR))); for (unsigned index = 0; index < number_events; index++) { QSharedPointer event = event_manager->getEvent(events[index]); if (event->getChannel() == UNDEFINED_CHANNEL) header->EVENT.CHN[index] = 0; else header->EVENT.CHN[index] = event->getChannel() + 1; header->EVENT.TYP[index] = event->getType (); header->EVENT.POS[index] = event->getPosition(); header->EVENT.DUR[index] = event->getDuration(); } qDebug () << "write events to " << new_file_path_; HDRTYPE *new_header = sopen (new_file_path_.toLocal8Bit().data(), "w", header); sclose (new_header); destructHDR (new_header); return ""; } } sigviewer-0.6.4/src/file_handling_impl/evt_writer.h000066400000000000000000000030651345753661000225010ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVT_WRITER_H #define EVT_WRITER_H #include "file_handling/file_signal_writer.h" #include namespace sigviewer { // EVT writer class EVTWriter : public FileSignalWriter { public: //------------------------------------------------------------------------- EVTWriter (); //------------------------------------------------------------------------- EVTWriter (bool prototype_instance); //------------------------------------------------------------------------- virtual QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual ~EVTWriter(); //------------------------------------------------------------------------- virtual QString saveEventsToSignalFile (QSharedPointer, std::set const&) {return "not implemented!";} //------------------------------------------------------------------------- virtual QString save (QSharedPointer file_context, std::set const& types); private: //------------------------------------------------------------------------- EVTWriter (QString const& new_file_path); static EVTWriter prototype_instance_; QString new_file_path_; // not allowed Q_DISABLE_COPY(EVTWriter) }; } #endif sigviewer-0.6.4/src/file_handling_impl/file_handler_factory_registrator.h000066400000000000000000000040351345753661000270750ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_HANDLER_FACTORY_REGISTRATOR_H #define FILE_HANDLER_FACTORY_REGISTRATOR_H #include "file_handling/file_signal_writer_factory.h" #include "file_handling/file_signal_reader_factory.h" namespace sigviewer { #define FILE_SIGNAL_WRITER_REGISTRATION(file_ending, writer) \ namespace Registrators_ { \ FileSignalWriterFactoryRegistrator file_writer_registrator ## writer ## file_ending (#file_ending, QSharedPointer (new writer)); \ } #define FILE_SIGNAL_READER_REGISTRATION(file_ending, reader) \ namespace Registrators_ { \ FileSignalReaderFactoryRegistrator file_reader_registrator ## reader ## file_ending (#file_ending, QSharedPointer (new reader)); \ } #define FILE_SIGNAL_READER_DEFAULT_REGISTRATION(reader) \ namespace Registrators_ { \ FileSignalReaderFactoryRegistrator file_reader_registrator ## reader (QSharedPointer (new reader)); \ } namespace Registrators_ { //----------------------------------------------------------------------------- class FileSignalWriterFactoryRegistrator { public: FileSignalWriterFactoryRegistrator (QString const& file_ending, QSharedPointer writer) { FileSignalWriterFactory::getInstance()->registerHandler (file_ending, writer); } }; //----------------------------------------------------------------------------- class FileSignalReaderFactoryRegistrator { public: FileSignalReaderFactoryRegistrator (QString const& file_ending, QSharedPointer reader) { FileSignalReaderFactory::getInstance()->registerHandler (file_ending, reader); } FileSignalReaderFactoryRegistrator (QSharedPointer reader) { FileSignalReaderFactory::getInstance()->registerDefaultHandler (reader); } }; } } #endif sigviewer-0.6.4/src/file_handling_impl/file_handling_impl.pri000066400000000000000000000011021345753661000244440ustar00rootroot00000000000000HEADERS += \ $$PWD/biosig_basic_header.h \ $$PWD/biosig_reader.h \ $$PWD/biosig_writer.h \ $$PWD/channel_manager_impl.h \ $$PWD/event_manager_impl.h \ $$PWD/event_table_file_reader.h \ $$PWD/evt_writer.h \ $$PWD/file_handler_factory_registrator.h \ $$PWD/xdf_reader.h SOURCES += \ $$PWD/biosig_basic_header.cpp \ $$PWD/biosig_reader.cpp \ $$PWD/biosig_writer.cpp \ $$PWD/channel_manager_impl.cpp \ $$PWD/event_manager_impl.cpp \ $$PWD/event_table_file_reader.cpp \ $$PWD/evt_writer.cpp \ $$PWD/xdf_reader.cpp sigviewer-0.6.4/src/file_handling_impl/gdf/000077500000000000000000000000001345753661000206725ustar00rootroot00000000000000sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_basic_header.cpp000066400000000000000000000034351345753661000246140ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_basic_header.h" namespace SigViewer_ { //------------------------------------------------------------------------------------------------- GDFBasicHeader::GDFBasicHeader (QString const& file_path, gdf::GDFHeaderAccess const& header_access) : BasicHeader (file_path), header_access_ (header_access) { setDownSamplingFactor (1); setSampleRate (header_access_.getSignalHeader_readonly(0).get_samplerate()); for (unsigned index = 0; index < header_access_.getNumSignals(); index++) { QSharedPointer channel (new SignalChannel (index, QString::number(index))); addChannel (index, channel); } } //--------------------------------------------------------------------------------------------- uint32 GDFBasicHeader::getNumberOfSamples () const { return header_access_.getSignalHeader_readonly(0).get_samples_per_record() * header_access_.getMainHeader_readonly().get_num_datarecords() / getDownSamplingFactor (); } } sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_basic_header.h000066400000000000000000000027541345753661000242640ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_BASICH_EADER_H #define GDF_BASICH_EADER_H #include "file_handling/basic_header.h" #include namespace SigViewer_ { //------------------------------------------------------------------------------------------------- class GDFBasicHeader : public BasicHeader { public: //--------------------------------------------------------------------------------------------- GDFBasicHeader (QString const& file_path, gdf::GDFHeaderAccess const& header_access); //--------------------------------------------------------------------------------------------- virtual uint32 getNumberOfSamples () const; private: gdf::GDFHeaderAccess const& header_access_; }; } #endif // GDF_BASICH_EADER_H sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_data_block.cpp000066400000000000000000000073331345753661000243070ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_data_block.h" #include #include #include namespace SigViewer_ { //------------------------------------------------------------------------------------------------- GDFDataBlock::GDFDataBlock (QSharedPointer cache, ChannelID channel, unsigned length, float32 sample_rate) : DataBlock (length, sample_rate), channel_ (channel), start_sample_ (0), current_min_ (-200), current_max_ (200), cache_ (cache) { } //------------------------------------------------------------------------------------------------- GDFDataBlock::GDFDataBlock (GDFDataBlock const& src, unsigned start_sample, unsigned length) : DataBlock (src, length), channel_ (src.channel_), start_sample_ (start_sample), current_min_ (src.current_min_), current_max_ (src.current_max_), downsampled_map_ (src.downsampled_map_), cache_ (src.cache_) { } //------------------------------------------------------------------------------------------------- GDFDataBlock::~GDFDataBlock () { } //------------------------------------------------------------------------------------------------- QSharedPointer GDFDataBlock::createSubBlock (uint32 start, uint32 length) const { return QSharedPointer (new GDFDataBlock (*this, start_sample_ + start, length)); } //------------------------------------------------------------------------------------------------- float32 const& GDFDataBlock::operator[] (uint32 index) const { current_value_ = cache_->getSample (channel_, start_sample_ + index); return current_value_; } //------------------------------------------------------------------------- float32 GDFDataBlock::getMin () const { return current_min_; } //------------------------------------------------------------------------- float32 GDFDataBlock::getMax () const { return current_max_; } //------------------------------------------------------------------------- void GDFDataBlock::addDownSampledVersion (QSharedPointer data, unsigned downsampling_factor) { downsampled_map_[downsampling_factor] = data; } //------------------------------------------------------------------------- std::pair, unsigned> GDFDataBlock::getNearbyDownsampledBlock (unsigned downsampling_factor) const { unsigned nearest_factor = 1; bool search = true; for (nearest_factor = downsampling_factor + 1; search && (nearest_factor > 1); --nearest_factor) if (downsampled_map_.contains (nearest_factor - 1)) search = false; if ((nearest_factor <= downsampling_factor) && (nearest_factor > 1)) { return std::pair, unsigned> (downsampled_map_[nearest_factor]->createSubBlock(start_sample_ / nearest_factor, size() / nearest_factor), nearest_factor); } else return std::pair, unsigned> (createSubBlock (0, size ()), 1); } } // namespace SigViewer_ sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_data_block.h000066400000000000000000000061771345753661000237610ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_DATA_BLOCK_H #define GDF_DATA_BLOCK_H #include "base/data_block.h" #include "gdf_signal_cache.h" #include "GDF/Reader.h" #include #include namespace SigViewer_ { //------------------------------------------------------------------------------------------------- class GDFDataBlock : public DataBlock { public: //--------------------------------------------------------------------------------------------- GDFDataBlock (QSharedPointer cache, ChannelID channel, unsigned length, float32 sample_rate); //--------------------------------------------------------------------------------------------- virtual ~GDFDataBlock (); //--------------------------------------------------------------------------------------------- virtual QSharedPointer createSubBlock (uint32 start, uint32 length) const; //--------------------------------------------------------------------------------------------- virtual float32 const& operator[] (uint32 index) const; //------------------------------------------------------------------------- virtual float32 getMin () const; //------------------------------------------------------------------------- virtual float32 getMax () const; //------------------------------------------------------------------------- void addDownSampledVersion (QSharedPointer data, unsigned downsampling_factor); //------------------------------------------------------------------------- std::pair, unsigned> getNearbyDownsampledBlock (unsigned downsampling_factor) const; private: //--------------------------------------------------------------------------------------------- GDFDataBlock (GDFDataBlock const& src, unsigned start_sample, unsigned length); //--------------------------------------------------------------------------------------------- Q_DISABLE_COPY (GDFDataBlock); //--------------------------------------------------------------------------------------------- ChannelID channel_; unsigned start_sample_; mutable float32 current_min_; mutable float32 current_max_; mutable float32 current_value_; QMap > downsampled_map_; mutable QSharedPointer cache_; }; } // namespace SigViewer_ #endif // GDF_DATA_BLOCK_H sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_file_signal_reader.cpp000066400000000000000000000136651345753661000260270ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_file_signal_reader.h" #include "../file_handler_factory_registrator.h" #include "gdf_data_block.h" #include "GDF/EventConverter.h" #include namespace SigViewer_ { //------------------------------------------------------------------------------------------------- //FILE_SIGNAL_READER_REGISTRATION(gdf, GDFFileSignalReader); //------------------------------------------------------------------------------------------------- GDFFileSignalReader::GDFFileSignalReader() : reader_ (0), downsampling_thread_ (0) { // nothing to do here } //------------------------------------------------------------------------------------------------- GDFFileSignalReader::~GDFFileSignalReader() { if (downsampling_thread_) { downsampling_thread_->terminate(); downsampling_thread_->wait(); } delete downsampling_thread_; if (reader_) { reader_->close (); delete reader_; } qDebug () << "deleting GDFFileSignalReader"; } //------------------------------------------------------------------------------------------------- QPair GDFFileSignalReader::createInstance (QString const& file_path) { GDFFileSignalReader* reader = new GDFFileSignalReader (); QString error = reader->open (file_path); if (error.size()) return QPair (0, error); else return QPair (reader, ""); } //------------------------------------------------------------------------------------------------- QSharedPointer GDFFileSignalReader::getSignalData (ChannelID channel_id, unsigned start_sample, unsigned length) const { if (channel_map_.size() == 0) { QList > data_for_downsampling; unsigned max_channel_length = 0; for (unsigned channel_index = 0; channel_index < reader_->getMainHeader_readonly().get_num_signals(); channel_index++) { unsigned current_channel_length = reader_->getSignalHeader_readonly(channel_index).get_samples_per_record() * reader_->getMainHeader_readonly().get_num_datarecords(); max_channel_length = std::max (max_channel_length, current_channel_length); QSharedPointer data (new GDFDataBlock (cache_, channel_index, current_channel_length, reader_->getSignalHeader_readonly(channel_index).get_samplerate())); channel_map_[channel_index] = data; data_for_downsampling.append (data); } downsampling_thread_ = new DownSamplingThread (data_for_downsampling, 3, max_channel_length / 2000); downsampling_thread_->start (QThread::LowestPriority); } return channel_map_[channel_id]->createSubBlock (start_sample, length); } //------------------------------------------------------------------------------------------------- QList > GDFFileSignalReader::getEvents () const { try { //qDebug () << "Number events " << reader_->getEventHeader()->getNumEvents() << "; Event Mode = " << reader_->getEventHeader()->getMode(); if (events_.size ()) return events_; std::vector mode_3_events; if (reader_->getEventHeader()->getMode() == 1) mode_3_events = gdf::convertMode1EventsIntoMode3Events (reader_->getEventHeader()->getMode1Events()); else mode_3_events = reader_->getEventHeader()->getMode3Events(); for (unsigned index = 0; index < mode_3_events.size (); index++) { gdf::Mode3Event& gdf_event = mode_3_events[index]; QSharedPointer event (new SignalEvent (gdf_event.position / header_->getDownSamplingFactor(), gdf_event.type, reader_->getEventHeader()->getSamplingRate() / header_->getDownSamplingFactor(), gdf_event.channel - 1, gdf_event.duration / header_->getDownSamplingFactor())); events_.push_back (event); } } catch (...) { //QMessageBox::critical (0, "Error", tr(exc.what())); } return events_; } //------------------------------------------------------------------------------------------------- QSharedPointer GDFFileSignalReader::getBasicHeader () { return header_; } //------------------------------------------------------------------------------------------------- QString GDFFileSignalReader::open (QString const& file_path) { if (reader_) delete reader_; reader_ = new gdf::Reader (); reader_->enableCache (false); try { reader_->open (file_path.toStdString()); } catch (std::exception& exc) { return QString (exc.what ()); } header_ = QSharedPointer (new GDFBasicHeader (file_path, reader_->getHeaderAccess_readonly())); cache_ = QSharedPointer (new GDFSignalCache (reader_)); return ""; } } // namespace sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_file_signal_reader.h000066400000000000000000000056331345753661000254700ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_FILE_SIGNAL_READER_H #define GDF_FILE_SIGNAL_READER_H #include "file_handling/file_signal_reader.h" #include "gdf_basic_header.h" #include "gdf_signal_cache.h" #include "gdf_data_block.h" #include "../down_sampling_thread.h" #include "GDF/Reader.h" #include namespace SigViewer_ { //----------------------------------------------------------------------------- class GDFFileSignalReader : public QObject, public FileSignalReader { Q_OBJECT public: //------------------------------------------------------------------------- GDFFileSignalReader (); //------------------------------------------------------------------------- virtual ~GDFFileSignalReader(); //------------------------------------------------------------------------- QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual QSharedPointer getSignalData (ChannelID channel_id, unsigned start_sample, unsigned length) const; //------------------------------------------------------------------------- virtual QList > getEvents () const; //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader (); //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader () const {return header_;} private: //------------------------------------------------------------------------- QString open (QString const& file_path); Q_DISABLE_COPY(GDFFileSignalReader) gdf::Reader* reader_; mutable DownSamplingThread* downsampling_thread_; QSharedPointer cache_; QSharedPointer header_; mutable QMap > channel_map_; mutable QList > events_; }; } // namespace #endif // GDF_FILE_SIGNAL_READER_H sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_file_signal_writer.cpp000066400000000000000000000142361345753661000260740ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_file_signal_writer.h" #include "file_handling/file_signal_writer_factory.h" #include "../file_handler_factory_registrator.h" #include "gui/progress_bar.h" #include "biosig.h" #include #include #include #include namespace SigViewer_ { //FILE_SIGNAL_WRITER_REGISTRATION(gdf, GDFFileSignalWriter); //------------------------------------------------------------------------- GDFFileSignalWriter::GDFFileSignalWriter() { qDebug() << "GDFFileSignalWriter constructed!"; } //------------------------------------------------------------------------- GDFFileSignalWriter::GDFFileSignalWriter (QString const& file_path) : new_file_path_ (file_path) { // nothing to do here } //------------------------------------------------------------------------- QPair GDFFileSignalWriter::createInstance (QString const& file_path) { return QPair (new GDFFileSignalWriter (file_path), ""); } //------------------------------------------------------------------------- QString GDFFileSignalWriter::saveEventsToSignalFile (QSharedPointer event_manager, std::set const& types) { gdf::Modifier modifier; modifier.open (new_file_path_.toStdString()); gdf::EventHeader* event_header = modifier.getEventHeader(); float32 event_sampling_rate = event_header->getSamplingRate(); event_header->clear(); event_header->setMode (3); event_header->setSamplingRate (event_sampling_rate); QList events; foreach (EventType type, types) events.append(event_manager->getEvents(type)); for (int index = 0; index < events.size(); index++) { gdf::Mode3Event gdf_event; QSharedPointer event = event_manager->getEvent(events[index]); if (event->getChannel() == UNDEFINED_CHANNEL) gdf_event.channel = 0; else gdf_event.channel = event->getChannel() + 1; gdf_event.duration = event->getDurationInSec() * event_sampling_rate; gdf_event.type = event->getType(); gdf_event.position = event->getPositionInSec() * event_sampling_rate; event_header->addEvent (gdf_event); } event_header->sort (); modifier.saveChanges (); modifier.close (); return ""; } //------------------------------------------------------------------------- QString GDFFileSignalWriter::save (QSharedPointer file_context, std::set const&) { qDebug () << "GDFFileSignalWriter::save"; gdf::Writer writer; writer.getMainHeader ().set_recording_id (file_context->getFileName().append(" converted to GDF2").toStdString()); // GDFWriter writer (new_file_path_.toStdString()); ChannelManager const& channel_manager = file_context->getChannelManager(); foreach (ChannelID channel, channel_manager.getChannels()) { writer.createSignal (channel); writer.getSignalHeader(channel).set_label (channel_manager.getChannelLabel (channel).toStdString()); writer.getSignalHeader(channel).set_datatype (gdf::FLOAT64); writer.getSignalHeader(channel).set_samplerate (channel_manager.getSampleRate()); writer.getSignalHeader(channel).set_digmin (-1); writer.getSignalHeader(channel).set_digmax (1); writer.getSignalHeader(channel).set_physmin (channel_manager.getMinValue (channel)); writer.getSignalHeader(channel).set_physmax (channel_manager.getMaxValue (channel)); } try { writer.setEventMode (3); writer.open (new_file_path_.toStdString(), gdf::writer_ev_memory | gdf::writer_overwrite); } catch (gdf::exception::header_issues &exception) { QString errors; if (exception.warnings.size () > 0) { foreach (std::string error, exception.errors) errors.append (error.c_str()); QMessageBox::warning (0, "Warning", errors); } if (exception.errors.size () > 0) { foreach (std::string error, exception.errors) errors.append (error.c_str()); return errors; } } try { QString progressbar_string = "Writing samples..."; for (unsigned sample_index = 0; sample_index < channel_manager.getNumberSamples(); sample_index++) { foreach (ChannelID channel_id, channel_manager.getChannels()) { writer.addSamplePhys (channel_id, (*(channel_manager.getData (channel_id, sample_index, 1)))[0]); } ProgressBar::instance().increaseValue (1, progressbar_string); } progressbar_string = "Writing events..."; QSharedPointer event_manager = file_context->getEventManager(); if (!event_manager.isNull()) { foreach (EventID event_id, event_manager->getAllEvents()) { QSharedPointer event = event_manager->getEvent(event_id); writer.addEvent (event->getPosition()+1, event->getType(), event->getChannel()+1, event->getDuration()); ProgressBar::instance().increaseValue (1, progressbar_string); } } } catch (std::exception & exception) { return exception.what(); } writer.close(); return ""; } } sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_file_signal_writer.h000066400000000000000000000040261345753661000255350ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_WRITER_H #define GDF_WRITER_H #include "file_handling/file_signal_writer.h" namespace SigViewer_ { //----------------------------------------------------------------------------- class GDFFileSignalWriter : public FileSignalWriter { public: //------------------------------------------------------------------------- GDFFileSignalWriter (); //------------------------------------------------------------------------- virtual QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual bool supportsSavingEvents () const {return true;} //------------------------------------------------------------------------- virtual QString saveEventsToSignalFile (QSharedPointer, std::set const& types); //------------------------------------------------------------------------- virtual QString save (QSharedPointer file_context, std::set const& types); private: GDFFileSignalWriter (QString const& file_path); QString new_file_path_; Q_DISABLE_COPY(GDFFileSignalWriter) }; } #endif // GDF_WRITER_H sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_load_data_thread.cpp000066400000000000000000000024111345753661000254530ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_load_data_thread.h" #include namespace SigViewer_ { //----------------------------------------------------------------------------- GDFLoadDataThread::GDFLoadDataThread(QObject *parent) : QThread(parent) { } //----------------------------------------------------------------------------- void GDFLoadDataThread::setNextIndex (unsigned sample_index) { } //----------------------------------------------------------------------------- void GDFLoadDataThread::run () { } } sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_load_data_thread.h000066400000000000000000000025501345753661000251240ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_LOAD_DATA_THREAD_H #define GDF_LOAD_DATA_THREAD_H #include #include namespace SigViewer_ { class GDFLoadDataThread : public QThread { Q_OBJECT public: explicit GDFLoadDataThread (QVector& channel_buffers_, QObject *parent = 0); void setNextIndex (unsigned sample_index); private: virtual void run (); bool currently_loading_; unsigned next_index_; unsigned current_index_; bool running_; QMutex current_index_mutex_; QMutex next_index_mutex_; QMutex currently_loading_mutex_; }; } #endif // GDF_LOAD_DATA_THREAD_H sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_signal_cache.cpp000066400000000000000000000116421345753661000246220ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #include "gdf_signal_cache.h" #include #include #include namespace SigViewer_ { unsigned const GDFSignalCache::CACHE_SIZE_PER_CHANNEL_ = 5000; //----------------------------------------------------------------------------- GDFSignalCache::GDFSignalCache (gdf::Reader* reader) : reader_ (reader) { qDebug () << "GDFSignalCache::GDFSignalCache"; } //----------------------------------------------------------------------------- GDFSignalCache::~GDFSignalCache () { foreach (QVector channel_buffer, channel_buffers_) { foreach (double* double_buffer, channel_buffer) { delete[] double_buffer; } } } //----------------------------------------------------------------------------- float32 GDFSignalCache::getSample (ChannelID channel, unsigned sample_index) { QMutexLocker locker (&rebuild_mutex_); if (!thread_cache_index_map_.contains (QThread::currentThread())) createNewThreadCacheIndex (); unsigned cache_index = thread_cache_index_map_[QThread::currentThread()]; if (!hasSampleIndex (cache_index, channel, sample_index)) rebuildCache (cache_index, channel, sample_index); return channel_buffers_[cache_index][channel][((sample_index - start_[cache_index][channel]) + cyclic_start_[cache_index][channel]) % CACHE_SIZE_PER_CHANNEL_]; } //----------------------------------------------------------------------------- bool GDFSignalCache::hasSampleIndex (unsigned cache_index, ChannelID channel, unsigned sample_index) const { return (sample_index >= start_[cache_index][channel]) && (sample_index < (start_[cache_index][channel] + CACHE_SIZE_PER_CHANNEL_)); } //----------------------------------------------------------------------------- void GDFSignalCache::rebuildCache (unsigned cache_index, ChannelID /*channel*/, unsigned sample_index) { // QMutexLocker locker (&rebuild_mutex_); size_t start = sample_index; // if (start > CACHE_SIZE_PER_CHANNEL_ / 2) // start -= CACHE_SIZE_PER_CHANNEL_ / 2; // else // start = 0; qDebug () << "GDFSignalCache::rebuildCache " << cache_index << " for thread " << thread_cache_index_map_.key (cache_index) << "; start = " << start; reader_->enableCache (true); //reader_->initCache(); for (int index = 0; index < channel_buffers_[cache_index].size (); index++) { // size_t old_start = start_[cache_index][index]; // size_t old_end = std::min(old_start + CACHE_SIZE_PER_CHANNEL_, reader_->getSignalHeader_readonly(index).get_samples_per_record() * reader_->getMainHeader_readonly().get_num_datarecords()); // unsigned old_cyclic_start = cyclic_start_[cache_index][index]; start_[cache_index][index] = start; size_t end = std::min(start + CACHE_SIZE_PER_CHANNEL_, reader_->getSignalHeader_readonly(index).get_samples_per_record() * reader_->getMainHeader_readonly().get_num_datarecords()); // unsigned cyclic_start = 0; // if (start > old_start && start < old_end) // { // cyclic_start = start - old_start; // } reader_->getSignal (index, channel_buffers_[cache_index][index], start, end); } reader_->resetCache (); } //----------------------------------------------------------------------------- unsigned GDFSignalCache::createNewThreadCacheIndex () { // QMutexLocker locker (&rebuild_mutex_); unsigned new_cache_index = channel_buffers_.size(); qDebug () << "GDFSignalCache::createNewThreadCacheIndex for thread " << QThread::currentThread() << "; new cache index = " << new_cache_index; channel_buffers_.append (QVector ()); start_.push_back (QVector ()); cyclic_start_.push_back (QVector ()); for (unsigned index = 0; index < reader_->getMainHeader_readonly().get_num_signals(); index++) { channel_buffers_[new_cache_index].push_back (new double[CACHE_SIZE_PER_CHANNEL_]); start_[new_cache_index].push_back (std::numeric_limits::max()); cyclic_start_[new_cache_index].push_back (0); } thread_cache_index_map_[QThread::currentThread()] = new_cache_index; return new_cache_index; } } sigviewer-0.6.4/src/file_handling_impl/gdf/gdf_signal_cache.h000066400000000000000000000034511345753661000242660ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef GDF_SIGNAL_CACHE_H #define GDF_SIGNAL_CACHE_H #include "../signal_cache.h" #include "GDF/Reader.h" #include #include #include #include namespace SigViewer_ { //----------------------------------------------------------------------------- class GDFSignalCache : public SignalCache { public: GDFSignalCache (gdf::Reader* reader); virtual ~GDFSignalCache (); virtual float32 getSample (ChannelID channel, unsigned sample_index); private: bool hasSampleIndex (unsigned cache_index, ChannelID channel, unsigned sample_index) const; void rebuildCache (unsigned cache_index, ChannelID channel, unsigned sample_index); unsigned createNewThreadCacheIndex (); gdf::Reader* reader_; static unsigned const CACHE_SIZE_PER_CHANNEL_; QList > channel_buffers_; QVector > start_; QVector > cyclic_start_; QMap thread_cache_index_map_; QMutex rebuild_mutex_; }; } #endif // GDF_SIGNAL_CACHE_H sigviewer-0.6.4/src/file_handling_impl/signal_cache.h000066400000000000000000000020411345753661000227000ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef SIGNAL_CACHE_H #define SIGNAL_CACHE_H #include "base/sigviewer_user_types.h" namespace SigViewer_ { class SignalCache { public: virtual ~SignalCache () {} virtual float32 getSample (ChannelID channel, unsigned sample_index) = 0; }; } #endif // SIGNAL_CACHE_H sigviewer-0.6.4/src/file_handling_impl/xdf_reader.cpp000066400000000000000000000334341345753661000227500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "xdf_reader.h" #include "biosig_basic_header.h" #include "file_handler_factory_registrator.h" #include "gui/progress_bar.h" #include "base/fixed_data_block.h" #include "gui_impl/dialogs/resampling_dialog.h" #include #include #include #include #include #include #include #include /* clock_t, clock, CLOCKS_PER_SEC */ namespace sigviewer { //the object to store XDF data QSharedPointer XDFdata = QSharedPointer(new Xdf); //----------------------------------------------------------------------------- FILE_SIGNAL_READER_REGISTRATION(xdf, XDFReader); //----------------------------------------------------------------------------- XDFReader::XDFReader() : basic_header_ (0), buffered_all_channels_ (false), buffered_all_events_ (false) { qDebug () << "Constructed XDFReader"; } //----------------------------------------------------------------------------- XDFReader::~XDFReader() { qDebug() << "Destructed XDFReader."; } //----------------------------------------------------------------------------- QPair XDFReader::createInstance (QString const& file_path) { XDFReader* reader (new XDFReader); QString error = reader->open (file_path); if (error.size() > 0) { qDebug () << error; //QMessageBox::critical(0, QObject::tr("Error"), error); return QPair (0, error); } else return QPair (reader, ""); } //----------------------------------------------------------------------------- QSharedPointer XDFReader::getSignalData (ChannelID channel_id, size_t start_sample, size_t length) const { QMutexLocker lock (&mutex_); if (!buffered_all_channels_) bufferAllChannels(); if (!channel_map_.contains(channel_id)) return QSharedPointer (0); if (length == basic_header_->getNumberOfSamples() && start_sample == 0) return channel_map_[channel_id]; else return channel_map_[channel_id]->createSubBlock (start_sample, length); } //----------------------------------------------------------------------------- QList > XDFReader::getEvents () const { QMutexLocker lock (&mutex_); if (!buffered_all_events_) bufferAllEvents(); return events_; } //----------------------------------------------------------------------------- QString XDFReader::open (QString const& file_path) { QMutexLocker lock (&mutex_); return loadFixedHeader (file_path); } //----------------------------------------------------------------------------- QString XDFReader::loadFixedHeader(const QString& file_path) { QMutexLocker locker (&xdf_access_lock_); clock_t t = clock(); clock_t t2 = clock(); if (QFile::exists(file_path)) //Double check whether file exists { if (XDFdata->load_xdf(file_path.toStdString()) == 0) { XDFdata->createLabels(); sampleRateTypes sampleRateType = selectSampleRateType(); switch (sampleRateType) { case No_streams_found: { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setText("No Stream Found"); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); return "non-exist"; } case Zero_Hz_Only: { ResamplingDialog prompt(XDFdata->majSR, XDFdata->maxSR); if (prompt.exec() == QDialog::Accepted) { XDFdata->majSR = prompt.getUserSrate(); XDFdata->resample(XDFdata->majSR); } else { Xdf empty; std::swap(*XDFdata, empty); return "Cancelled"; } } break; case Mono_Sample_Rate: { XDFdata->calcTotalLength(XDFdata->majSR); XDFdata->adjustTotalLength(); if (XDFdata->effectiveSampleRateVector.size()) { /* If and only if the file contains only one sample rate, we use effective sample rate to more accurately display events. Effective sample rates can be slightly different across streams, so we calculate the mean here */ double init = 0.0; XDFdata->fileEffectiveSampleRate = std::accumulate(XDFdata->effectiveSampleRateVector.begin(), XDFdata->effectiveSampleRateVector.end(), init) / XDFdata->effectiveSampleRateVector.size(); } } break; case Multi_Sample_Rate: { ResamplingDialog prompt(XDFdata->majSR, XDFdata->maxSR); if (prompt.exec() == QDialog::Accepted) { XDFdata->majSR = prompt.getUserSrate(); XDFdata->resample(XDFdata->majSR); } else { Xdf empty; std::swap(*XDFdata, empty); return "Cancelled"; } } break; default: qDebug() << "Unknown sample rate type."; break; } XDFdata->freeUpTimeStamps(); //to save some memory setStreamColors(); setEventTypeColors(); t = clock() - t; qDebug() << "it took " << ((float)t) / CLOCKS_PER_SEC << " seconds reading data"; t = clock() - t - t2; qDebug() << "it took " << ((float)t) / CLOCKS_PER_SEC << " additional seconds loading XDF header"; bool showWarning = false; for (auto const &stream : XDFdata->streams) { if (std::abs(stream.info.effective_sample_rate - stream.info.nominal_srate) > stream.info.nominal_srate / 20) { showWarning = true; } } if (showWarning) QMessageBox::warning(0, "SigViewer", "The effective sampling rate of at least one stream is significantly different than the reported nominal sampling rate. Signal visualization might be inaccurate.", QMessageBox::Ok, QMessageBox::Ok); basic_header_ = QSharedPointer (new BiosigBasicHeader ("XDF", file_path)); basic_header_->setNumberEvents(XDFdata->eventType.size()); if (XDFdata->fileEffectiveSampleRate) basic_header_->setEventSamplerate(XDFdata->fileEffectiveSampleRate); else basic_header_->setEventSamplerate(XDFdata->majSR); return ""; } else { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setText("Unable to open file."); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); return "non-exist"; } } else { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setText("File does not exist."); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); return "non-exist"; } } //----------------------------------------------------------------------------- QSharedPointer XDFReader::getBasicHeader () { //QMutexLocker lock (&mutex_); return basic_header_; } //----------------------------------------------------------------------------- int XDFReader::setStreamColors() { // Display each stream in a distinct color QSharedPointer colorPicker = ApplicationContextImpl::getInstance()->color_manager_; QVector colorList = {"#0055ff", "#00aa00", "#aa00ff", "#00557f", "#5555ff", "#ff55ff", "#00aaff", "#00aa7f"}; //some streams contains text only and no channels, so we skip those streams //because the colors I picked look the best when they are sorted in order int colorChoice = -1; int stream = -1; for (size_t i = 0; i < XDFdata->totalCh; i++) { if (stream != XDFdata->streamMap[i]) { stream = XDFdata->streamMap[i]; colorChoice++; if (colorChoice == 8) //we only have 8 colors colorChoice = 0; } colorPicker->setChannelColor(i, colorList[colorChoice]); } colorPicker->saveSettings(); return 0; } //----------------------------------------------------------------------------- XDFReader::sampleRateTypes XDFReader::selectSampleRateType() { switch (XDFdata->sampleRateMap.size()) { case 0: return No_streams_found; case 1: if (XDFdata->sampleRateMap.count(0)) return Zero_Hz_Only; else return Mono_Sample_Rate; case 2: if (XDFdata->sampleRateMap.count(0)) return Mono_Sample_Rate; else return Multi_Sample_Rate; default: return Multi_Sample_Rate; } } //----------------------------------------------------------------------------- void XDFReader::bufferAllChannels () const { size_t numberOfSamples = XDFdata->totalLen; QString progress_name = QObject::tr("Loading data..."); //load all signals channel by channel unsigned channel_id = 0; for (auto &stream : XDFdata->streams) { if (stream.info.nominal_srate != 0 && stream.info.channel_format.compare("string")) // filter the string streams { int startingPosition = (stream.info.first_timestamp - XDFdata->minTS) * XDFdata->majSR; if (stream.time_series.front().size() > XDFdata->totalLen - startingPosition ) startingPosition = XDFdata->totalLen - stream.time_series.front().size(); for (auto &row : stream.time_series) { ProgressBar::instance().increaseValue (1, progress_name); QSharedPointer > raw_data(new QVector (numberOfSamples, NAN)); std::copy(row.begin(), row.end(), raw_data->begin() + startingPosition); QSharedPointer data_block(new FixedDataBlock(raw_data, XDFdata->majSR)); channel_map_[channel_id] = data_block; channel_id++; std::vector nothing; row.swap(nothing); } std::vector nothing2; stream.time_stamps.swap(nothing2); } //else if: irregualar samples else if (stream.info.nominal_srate == 0 && !stream.time_series.empty()) { for (auto &row : stream.time_series) { ProgressBar::instance().increaseValue (1, progress_name); QSharedPointer > raw_data(new QVector (numberOfSamples, NAN)); for (size_t i = 0; i < row.size(); i++) { //find out the position using the timestamp provided float* pt = raw_data->begin() + (int)(round((stream.time_stamps[i]- XDFdata->minTS)* XDFdata->majSR)); *pt = row[i]; //if i is not the last element of the irregular time series if (i != stream.time_stamps.size() - 1) { //using linear interpolation to fill in the space between every two signals int interval = round((stream.time_stamps[i+1] - stream.time_stamps[i]) * XDFdata->majSR); for (int interpolation = 1; interpolation <= interval; interpolation++) { *(pt + interpolation) = row[i] + interpolation * ((row[i+1] - row[i])) / (interval + 1); } } } QSharedPointer data_block(new FixedDataBlock(raw_data, XDFdata->majSR)); channel_map_[channel_id] = data_block; channel_id++; std::vector nothing; row.swap(nothing); } std::vector nothing2; stream.time_stamps.swap(nothing2); } } buffered_all_channels_ = true; } //------------------------------------------------------------------------- void XDFReader::bufferAllEvents () const { unsigned number_events = XDFdata->eventMap.size(); double eventSampleRate = 0; if (XDFdata->fileEffectiveSampleRate) eventSampleRate = XDFdata->fileEffectiveSampleRate; else eventSampleRate = XDFdata->majSR; for (unsigned index = 0; index < number_events; index++) { QSharedPointer event (new SignalEvent (round ((XDFdata->eventMap[index].first.second - XDFdata->minTS) * eventSampleRate), XDFdata->eventType[index] + 1,//index+1 because in SigViewer and libbiosig //0 is reserved for a special type of event. Thus we increment by 1 eventSampleRate, XDFdata->eventMap[index].second)); event->setChannel (UNDEFINED_CHANNEL); event->setDuration (0); events_.append (event); } buffered_all_events_ = true; } } sigviewer-0.6.4/src/file_handling_impl/xdf_reader.h000066400000000000000000000052761345753661000224200ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef XDF_READER_H_ #define XDF_READER_H_ #include "file_handling/file_signal_reader.h" #include "xdf.h" #include #include #include namespace sigviewer { //the object to store XDF data extern QSharedPointer XDFdata; //XDFReader, modeled on BiosigReader class XDFReader : public FileSignalReader { public: XDFReader (); virtual ~XDFReader(); //------------------------------------------------------------------------- QPair createInstance (QString const& file_path); //------------------------------------------------------------------------- virtual QSharedPointer getSignalData (ChannelID channel_id, size_t start_sample, size_t length) const; //------------------------------------------------------------------------- virtual QList > getEvents () const; //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader (); //------------------------------------------------------------------------- virtual QSharedPointer getBasicHeader () const {return basic_header_;} //------------------------------------------------------------------------- int setStreamColors(); /*!< Set a distinct color for each stream. */ //------------------------------------------------------------------------- enum sampleRateTypes { No_streams_found, Zero_Hz_Only, Mono_Sample_Rate, Multi_Sample_Rate }; sampleRateTypes selectSampleRateType(); private: //------------------------------------------------------------------------- QString open (QString const& file_path); //------------------------------------------------------------------------- void bufferAllChannels () const; //------------------------------------------------------------------------- void bufferAllEvents () const; Q_DISABLE_COPY(XDFReader) QString loadFixedHeader(const QString& file_path); QSharedPointer basic_header_; mutable QMutex mutex_; mutable QMutex xdf_access_lock_; mutable bool buffered_all_channels_; mutable bool buffered_all_events_; mutable QMap > channel_map_; mutable QList > events_; }; } // namespace sigviewer #endif /*XDF_READER_H_*/ sigviewer-0.6.4/src/gui/000077500000000000000000000000001345753661000151125ustar00rootroot00000000000000sigviewer-0.6.4/src/gui/application_context.h000066400000000000000000000036161345753661000213400ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef APPLICATION_CONTEXT_H #define APPLICATION_CONTEXT_H #include "color_manager.h" #include "main_window_model.h" #include "tab_context.h" #include namespace sigviewer { enum ApplicationMode { APPLICATION_TEST_MODE, APPLICATION_NON_GUI_MODE }; ///---------------------------------------------------------------------------- /// ApplicationContext class ApplicationContext { public: //------------------------------------------------------------------------- virtual ~ApplicationContext () {} //------------------------------------------------------------------------- virtual bool modeActivated (ApplicationMode mode) const = 0; //------------------------------------------------------------------------- virtual QSharedPointer getCurrentFileContext () = 0; //------------------------------------------------------------------------- virtual void removeCurrentFileContext () = 0; //------------------------------------------------------------------------- virtual void addFileContext (QSharedPointerfile_context) = 0; //------------------------------------------------------------------------- virtual void setCurrentTabContext (QSharedPointer tab_context) = 0; //------------------------------------------------------------------------- virtual QSharedPointer getCurrentCommandExecuter () = 0; //------------------------------------------------------------------------- virtual QSharedPointer getMainWindowModel () = 0; //------------------------------------------------------------------------- virtual QSharedPointer getEventColorManager () = 0; }; } #endif // APPLICATION_CONTEXT_H sigviewer-0.6.4/src/gui/background_processes.cpp000066400000000000000000000017001345753661000220210ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "background_processes.h" namespace sigviewer { //------------------------------------------------------------------------- BackgroundProcesses& BackgroundProcesses::instance () { static BackgroundProcesses instance; return instance; } //------------------------------------------------------------------------- void BackgroundProcesses::addProcess (QString const& name, int max) { emit newProcess (name, max); } //------------------------------------------------------------------------- void BackgroundProcesses::setProcessState (QString const& name, int state) { emit processChangedState (name, state); } //------------------------------------------------------------------------- void BackgroundProcesses::removeProcess (QString const& name) { emit processRemoved (name); } } sigviewer-0.6.4/src/gui/background_processes.h000066400000000000000000000021601345753661000214670ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BACK_GROUND_PROCESSES_H #define BACK_GROUND_PROCESSES_H #include #include namespace sigviewer { //----------------------------------------------------------------------------- class BackgroundProcesses : public QObject { Q_OBJECT public: //------------------------------------------------------------------------- static BackgroundProcesses& instance (); //------------------------------------------------------------------------- void addProcess (QString const& name, int max); //------------------------------------------------------------------------- void setProcessState (QString const& name, int state); //------------------------------------------------------------------------- void removeProcess (QString const& name); signals: void newProcess (QString name, int max); void processChangedState (QString name, int state); void processRemoved (QString name); }; } #endif // BACK_GROUND_PROCESSES_H sigviewer-0.6.4/src/gui/color_manager.cpp000066400000000000000000000172511345753661000204340ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "color_manager.h" #include #include #include #include namespace sigviewer { const char* ColorManager::DEFAULT_CHANNEL_COLOR_SETTING_ = "Default Channel Color"; //----------------------------------------------------------------------------- ColorManager::ColorManager () { qDebug() << "constructing event color manager"; loadDefaultEventColors (); loadSettings(); } //----------------------------------------------------------------------------- ColorManager::~ColorManager () { qDebug() << "destructing event color manager"; } //----------------------------------------------------------------------------- QColor ColorManager::getChannelColor (ChannelID channel_id) const { if (channel_color_map_.contains (channel_id)) return channel_color_map_[channel_id]; else return default_channel_color_; } //----------------------------------------------------------------------------- QColor ColorManager::getDefaultChannelColor () const { return default_channel_color_; } //----------------------------------------------------------------------------- void ColorManager::setDefaultChannelColor (QColor const& color) { default_channel_color_ = color; QSettings settings; settings.beginGroup ("ColorManager"); settings.setValue (DEFAULT_CHANNEL_COLOR_SETTING_, color); settings.endGroup (); default_channel_color_ = color; } //----------------------------------------------------------------------------- void ColorManager::setChannelColor (ChannelID channel_id, QColor const& color) { channel_color_map_[channel_id] = color; } //----------------------------------------------------------------------------- QColor ColorManager::getEventColor (EventType type) const { if (type == 800) qDebug () << "ups"; EventColorMap::const_iterator it = event_type2color_.find(type); if (it == event_type2color_.end()) { if (default_event_colors_.contains (type)) return default_event_colors_[type]; else return default_event_color_; } else return *it; } //----------------------------------------------------------------------------- QColor ColorManager::getDefaultEventColor (EventType type) const { if (default_event_colors_.contains (type)) return default_event_colors_[type]; else return default_event_color_; } //----------------------------------------------------------------------------- void ColorManager::setEventColor (EventType type, const QColor& color) { event_type2color_[type] = color; } //----------------------------------------------------------------------------- bool ColorManager::isDark (QColor const& color) { double alpha_factor = color.alpha() / 255.0; double tmp = 255 * (1 - alpha_factor); float64 y = 0.299 * (tmp + color.red() * alpha_factor)+ 0.587 * (tmp + color.green() * alpha_factor) + 0.114 * (tmp + color.blue() * alpha_factor); return y < 127; } //----------------------------------------------------------------------------- void ColorManager::loadSettings() { // get event types from event table reader QColor alpha_color(0, 0, 0, 50); event_type2color_[-1] = alpha_color; EventTableFileReader::IntIterator it; for (it = event_table_file_reader_.eventTypesBegin(); it != event_table_file_reader_.eventTypesEnd(); it++) { event_type2color_[*it] = default_event_colors_[*it]; } QSettings settings; settings.beginGroup("ColorManager"); default_channel_color_ = QColor("#0055ff"); //vivid blue // default_channel_color_ = Qt::darkBlue; if (settings.contains (DEFAULT_CHANNEL_COLOR_SETTING_)) default_channel_color_ = settings.value (DEFAULT_CHANNEL_COLOR_SETTING_).value(); else settings.setValue (DEFAULT_CHANNEL_COLOR_SETTING_, default_channel_color_); int size = settings.beginReadArray("event"); for (int i = 0; i < size; i++) { settings.setArrayIndex(i); int32 id = settings.value("id").toInt(); QColor color = settings.value("color").toString(); color.setAlpha(settings.value("alpha").toInt()); event_type2color_[id] = color; } settings.endArray(); size = settings.beginReadArray("channel"); for (int i = 0; i < size; i++) { settings.setArrayIndex(i); ChannelID id = settings.value("id").toInt (); QColor color = settings.value("color").toString(); channel_color_map_[id] = color; } settings.endArray(); settings.endGroup(); } //----------------------------------------------------------------------------- void ColorManager::saveSettings() { qDebug() << "color manager save settings"; QSettings settings; settings.beginGroup("ColorManager"); settings.beginWriteArray("event"); int32 i = 0; for (EventColorMap::const_iterator it = event_type2color_.begin(); it != event_type2color_.end(); it++) { if (it.key() == UNDEFINED_EVENT_TYPE) { continue; } settings.setArrayIndex(i++); settings.setValue("id", it.key()); settings.setValue("color", it->name()); settings.setValue("alpha", it->alpha()); } settings.endArray(); i = 0; settings.beginWriteArray("channel"); foreach (ChannelID id, channel_color_map_.keys ()) { settings.setArrayIndex (i++); settings.setValue ("id", id); settings.setValue ("color", channel_color_map_[id]); } settings.endArray(); settings.endGroup(); } //----------------------------------------------------------------------------- void ColorManager::loadDefaultEventColors () { QFile color_settings_file (":/color_settings.xml"); QDomDocument color_doc; QString error_msg; int error_line; color_doc.setContent (&color_settings_file, true, &error_msg, &error_line); QDomElement root = color_doc.documentElement(); QDomNodeList default_elements = root.elementsByTagName("default"); if (default_elements.size() != 1) return; QDomElement default_node = default_elements.at(0).toElement(); QColor default_color; default_color.setAlpha (default_node.attribute("alpha").toUInt()); default_color.setRed (default_node.attribute("red").toUInt()); default_color.setGreen (default_node.attribute("green").toUInt()); default_color.setBlue (default_node.attribute("blue").toUInt()); default_event_color_ = default_color; QDomNodeList event_elements = root.elementsByTagName("event"); for (int index = 0; index < event_elements.size(); index++) { QDomElement element = event_elements.at(index).toElement(); QColor event_color = default_color; if (element.hasAttribute("red")) event_color.setRed(element.attribute("red").toUInt()); if (element.hasAttribute("green")) event_color.setGreen(element.attribute("green").toUInt()); if (element.hasAttribute("blue")) event_color.setBlue(element.attribute("blue").toUInt()); if (element.hasAttribute("alpha")) event_color.setAlpha(element.attribute("alpha").toUInt()); default_event_colors_[element.attribute("type").toInt(0, 16)] = event_color; } EventTableFileReader::IntIterator it; for (it = event_table_file_reader_.eventTypesBegin(); it != event_table_file_reader_.eventTypesEnd(); it++) { if (!default_event_colors_.contains(*it)) default_event_colors_[*it] = default_color; } } } sigviewer-0.6.4/src/gui/color_manager.h000066400000000000000000000026321345753661000200760ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_COLOR_MANAGER #define EVENT_COLOR_MANAGER #include "file_handling_impl/event_table_file_reader.h" #include #include #include namespace sigviewer { // color manager class ColorManager { public: ColorManager (); ~ColorManager (); void saveSettings(); void loadSettings(); QColor getChannelColor (ChannelID channel_id) const; QColor getDefaultChannelColor () const; void setDefaultChannelColor (QColor const& color); void setChannelColor (ChannelID channel_id, QColor const& color); QColor getEventColor (EventType type) const; QColor getDefaultEventColor (EventType type = UNDEFINED_EVENT_TYPE) const; void setEventColor (EventType type, const QColor& color); static bool isDark (QColor const& color); private: Q_DISABLE_COPY(ColorManager) void loadDefaultEventColors (); static const char* DEFAULT_CHANNEL_COLOR_SETTING_; QColor default_channel_color_; QColor default_event_color_; typedef QMap EventColorMap; typedef QMap ChannelColorMap; EventColorMap event_type2color_; EventColorMap default_event_colors_; ChannelColorMap channel_color_map_; EventTableFileReader event_table_file_reader_; }; } #endif sigviewer-0.6.4/src/gui/event_view.h000066400000000000000000000037241345753661000174440ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_VIEW_H #define EVENT_VIEW_H #include "base/sigviewer_user_types.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- class EventView { public: //------------------------------------------------------------------------- EventView (bool events_hidable = true, bool events_slidable = true) : events_hidable_ (events_hidable), events_slidable_ (events_slidable) {} //------------------------------------------------------------------------- virtual ~EventView () {} //------------------------------------------------------------------------- virtual bool eventsHidable () const {return events_hidable_;} //------------------------------------------------------------------------- virtual bool eventsSlidable () const {return events_slidable_;} //------------------------------------------------------------------------- virtual void setShownEventTypes (std::set const& event_types) = 0; //------------------------------------------------------------------------- virtual std::set getShownEventTypes () const = 0; //------------------------------------------------------------------------- virtual QSharedPointer getEventManager () const = 0; //------------------------------------------------------------------------- virtual QSharedPointer getEventManager () = 0; //------------------------------------------------------------------------- /// @return the id of the currently selected signal event virtual QList getSelectedEvents () const = 0; private: bool events_hidable_; bool events_slidable_; }; } #endif // EVENT_VIEW_H sigviewer-0.6.4/src/gui/gui.pri000066400000000000000000000012611345753661000164120ustar00rootroot00000000000000HEADERS += \ $$PWD/application_context.h \ $$PWD/background_processes.h \ $$PWD/color_manager.h \ $$PWD/event_view.h \ $$PWD/gui_action_command.h \ $$PWD/gui_action_factory.h \ $$PWD/gui_action_factory_registrator.h \ $$PWD/main_window_model.h \ $$PWD/progress_bar.h \ $$PWD/signal_view_settings.h \ $$PWD/signal_visualisation_model.h \ $$PWD/signal_visualisation_modes.h \ $$PWD/signal_visualisation_view.h SOURCES += \ $$PWD/background_processes.cpp \ $$PWD/color_manager.cpp \ $$PWD/gui_action_command.cpp \ $$PWD/gui_action_factory.cpp \ $$PWD/signal_view_settings.cpp \ $$PWD/signal_visualisation_model.cpp sigviewer-0.6.4/src/gui/gui_action_command.cpp000066400000000000000000000222571345753661000214450ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "gui_action_command.h" #include "gui_action_factory.h" #include "application_context_impl.h" #include namespace sigviewer { class GuiActionCommandException : public Exception { public: explicit GuiActionCommandException (QString const& action_id, std::string const& error) : Exception (std::string ("GuiActionCommand: \"") + action_id.toStdString () + "\" failed: " + error) {} }; //----------------------------------------------------------------------------- GuiActionCommand::GuiActionCommand (QStringList const& action_ids) : tab_edit_state_ (TAB_STATE_NO_REDO_NO_UNDO) { for (QStringList::const_iterator iter = action_ids.begin(); iter != action_ids.end(); ++iter) { action_map_[*iter] = new QAction (*iter, this); connectors_.push_back (new ActionConnector (this, *iter)); } } //----------------------------------------------------------------------------- void GuiActionCommand::initConnections() { for (ActionConnector* con : connectors_) { QAction* act = action_map_[con->getName()]; con->connect (act, SIGNAL(triggered()), SLOT(trigger())); connect (con, SIGNAL(triggered(QString const&)), SLOT(trigger(QString const&))); } QString firstActionId = connectors_.first()->getName(); qDebug() << "GuiActionCommand::GuiActionCommand connecting to ApplicationContextImpl::getInstance() = " << ApplicationContextImpl::getInstance(); if (!connect(ApplicationContextImpl::getInstance().data(), SIGNAL(stateChanged(ApplicationState)), SLOT(updateEnablednessToApplicationState(ApplicationState)))) throw (GuiActionCommandException(firstActionId, "connect to signal stateChanged(ApplicationState)")); else qDebug() << "GuiActionCommand::GuiActionCommand connect to signal stateChanged(ApplicationState) = true"; if (!connect(ApplicationContextImpl::getInstance().data(), SIGNAL(currentTabSelectionStateChanged(TabSelectionState)), SLOT(updateEnablednessToTabSelectionState(TabSelectionState)))) throw (GuiActionCommandException(firstActionId, "connect to signal currentTabSelectionStateChanged(TabSelectionState)")); if (!connect(ApplicationContextImpl::getInstance().data(), SIGNAL(currentTabEditStateChanged(TabEditState)), SLOT(updateEnablednessToTabEditState(TabEditState)))) throw (GuiActionCommandException(firstActionId, "connect to signal currentTabEditStateChanged(TabEditState)")); if (!connect(ApplicationContextImpl::getInstance().data(), SIGNAL(currentFileStateChanged(FileState)), SLOT(updateEnablednessToFileState(FileState)))) throw (GuiActionCommandException(firstActionId, "connect to signal currentFileStateChanged(FileState)")); } //----------------------------------------------------------------------------- QList GuiActionCommand::getQActions () { return action_map_.values (); } //----------------------------------------------------------------------------- QList GuiActionCommand::getActionIDs () const { return action_map_.keys (); } //----------------------------------------------------------------------------- QAction* GuiActionCommand::getQAction (QString const& id) { if (action_map_.contains (id)) return action_map_[id]; else throw GuiActionCommandException (id, "not exists"); return 0; } //----------------------------------------------------------------------------- void GuiActionCommand::updateEnablednessToApplicationState (ApplicationState state) { app_state_ = state; applicationStateChanged (); evaluateEnabledness (); } //----------------------------------------------------------------------------- void GuiActionCommand::updateEnablednessToFileState (FileState state) { file_state_ = state; evaluateEnabledness (); } //----------------------------------------------------------------------------- void GuiActionCommand::updateEnablednessToTabSelectionState (TabSelectionState state) { tab_selection_state_ = state; evaluateEnabledness (); } //----------------------------------------------------------------------------- void GuiActionCommand::updateEnablednessToTabEditState (TabEditState state) { tab_edit_state_ = state; evaluateEnabledness (); } //----------------------------------------------------------------------------- void GuiActionCommand::resetActionTriggerSlot (QString const& action_id, const char* slot) { if (!action_map_.contains (action_id)) throw (GuiActionCommandException (action_id, "resetActionTriggerSlot, action not exists")); QAction* action = action_map_[action_id]; action->disconnect (SIGNAL(triggered())); if (!connect (action, SIGNAL(triggered()), slot)) throw (GuiActionCommandException (action_id, std::string ("connect triggered to ") + slot)); } //----------------------------------------------------------------------------- void GuiActionCommand::setShortcut (QString const& action_id, QKeySequence const& key_sequence) { if (!action_map_.contains (action_id)) throw (GuiActionCommandException (action_id, "setting shortcut, action not exists")); action_map_[action_id]->setShortcut (key_sequence); } //----------------------------------------------------------------------------- void GuiActionCommand::setIcon (QString const& action_id, QIcon const& icon) { if (!action_map_.contains (action_id)) throw (GuiActionCommandException (action_id, "setting icon, action not exists")); action_map_[action_id]->setIcon (icon); } //------------------------------------------------------------------------- void GuiActionCommand::evaluateEnabledness () { } //------------------------------------------------------------------------- QSharedPointer GuiActionCommand::currentEventView () { QSharedPointer event_view; QSharedPointer main_window_model = ApplicationContextImpl::getInstance()->getMainWindowModel (); if (!main_window_model.isNull()) event_view = main_window_model->getCurrentEventView (); return event_view; } //------------------------------------------------------------------------- QSharedPointer GuiActionCommand::currentVisModel () { QSharedPointer model; QSharedPointer main_window_model = ApplicationContextImpl::getInstance()->getMainWindowModel (); if (!main_window_model.isNull()) model = main_window_model->getCurrentSignalVisualisationModel(); return model; } //------------------------------------------------------------------------- QSharedPointer GuiActionCommand::currentSignalViewSettings () { QSharedPointer settings; QSharedPointer vis_model = currentVisModel(); if (!vis_model.isNull()) settings = vis_model->getSignalViewSettings(); return settings; } //------------------------------------------------------------------------- QSharedPointer GuiActionCommand::currentFileContext () { return ApplicationContextImpl::getInstance()->getCurrentFileContext(); } //------------------------------------------------------------------------- QSharedPointer GuiActionCommand::applicationContext () { return ApplicationContextImpl::getInstance(); } //------------------------------------------------------------------------- bool GuiActionCommand::disableIfNoSignalIsVisualised (QStringList const &actions) { bool no_signal_is_visualised = currentVisModel().isNull(); if (no_signal_is_visualised) foreach (QString action, actions) action_map_[action]->setDisabled (no_signal_is_visualised); return no_signal_is_visualised; } //------------------------------------------------------------------------- bool GuiActionCommand::disableIfNoEventsPossible (QStringList const &actions) { bool no_events_possible = false; if (!currentEventView().isNull()) { if (currentEventView()->getEventManager().isNull()) no_events_possible = true; } else no_events_possible = true; foreach (QString action, actions) action_map_[action]->setDisabled (no_events_possible); return no_events_possible; } //------------------------------------------------------------------------- void GuiActionCommand::disableIfNoEventSelected (QStringList const &actions) { bool no_event_selected = app_state_ == APP_STATE_NO_FILE_OPEN || tab_selection_state_ == TAB_STATE_NO_EVENT_SELECTED || tab_selection_state_ == NO_TAB_SELECTION_STATE; foreach (QString action, actions) action_map_[action]->setDisabled (no_event_selected); } //------------------------------------------------------------------------- bool GuiActionCommand::disableIfNoFileIsOpened (QStringList const &actions) { bool no_file_open = (app_state_ == APP_STATE_NO_FILE_OPEN); foreach (QString action, actions) action_map_[action]->setDisabled (no_file_open); return no_file_open; } } sigviewer-0.6.4/src/gui/gui_action_command.h000066400000000000000000000124771345753661000211150ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef GUI_ACTION_COMMAND_H #define GUI_ACTION_COMMAND_H #include "application_context.h" #include "base/application_states.h" #include "base/tab_states.h" #include "base/file_states.h" #include "base/exception.h" #include "signal_visualisation_model.h" #include "event_view.h" #include "signal_view_settings.h" #include #include #include namespace sigviewer { class ActionConnector; class GuiActionCommand : public QObject { Q_OBJECT public: //------------------------------------------------------------------------- virtual ~GuiActionCommand () {} //------------------------------------------------------------------------- QList getQActions (); //------------------------------------------------------------------------- QList getActionIDs () const; //------------------------------------------------------------------------- void initConnections(); //------------------------------------------------------------------------- virtual void init () = 0; public slots: //------------------------------------------------------------------------- virtual void trigger (QString const&) {} //------------------------------------------------------------------------- void updateEnablednessToApplicationState (ApplicationState state); //------------------------------------------------------------------------- void updateEnablednessToFileState (FileState state); //------------------------------------------------------------------------- void updateEnablednessToTabSelectionState (TabSelectionState state); //------------------------------------------------------------------------- void updateEnablednessToTabEditState (TabEditState state); //------------------------------------------------------------------------- QAction* getQAction (QString const& id); protected: //------------------------------------------------------------------------- GuiActionCommand (QStringList const& action_ids); //------------------------------------------------------------------------- void resetActionTriggerSlot (QString const& action_id, const char* slot); //------------------------------------------------------------------------- void setShortcut (QString const& action_id, QKeySequence const& key_sequence); //------------------------------------------------------------------------- void setIcon (QString const& action_id, QIcon const& icon); //------------------------------------------------------------------------- virtual void applicationStateChanged () {} //------------------------------------------------------------------------- virtual void evaluateEnabledness (); //------------------------------------------------------------------------- QSharedPointer currentEventView (); //------------------------------------------------------------------------- QSharedPointer currentVisModel (); //------------------------------------------------------------------------- QSharedPointer currentSignalViewSettings (); //------------------------------------------------------------------------- QSharedPointer currentFileContext (); //------------------------------------------------------------------------- QSharedPointer applicationContext (); //------------------------------------------------------------------------- ApplicationState getApplicationState () const {return app_state_;} //------------------------------------------------------------------------- FileState getFileState () const {return file_state_;} //------------------------------------------------------------------------- TabSelectionState getTabSelectionState () const {return tab_selection_state_;} //------------------------------------------------------------------------- TabEditState getTabEditState () const {return tab_edit_state_;} //------------------------------------------------------------------------- bool disableIfNoSignalIsVisualised (QStringList const &actions); //------------------------------------------------------------------------- bool disableIfNoEventsPossible (QStringList const &actions); //------------------------------------------------------------------------- void disableIfNoEventSelected (QStringList const &actions); //------------------------------------------------------------------------- bool disableIfNoFileIsOpened (QStringList const &actions); private: QMap action_map_; QList connectors_; ApplicationState app_state_; FileState file_state_; TabSelectionState tab_selection_state_; TabEditState tab_edit_state_; }; class ActionConnector : public QObject { Q_OBJECT public: ActionConnector (QObject* parent, QString const& name) : QObject (parent), name_ (name) {} QString const& getName() const {return name_; } public slots: void trigger () {emit triggered (name_);} signals: void triggered (QString const& name); private: QString name_; }; } #endif // GUI_ACTION_COMMAND_H sigviewer-0.6.4/src/gui/gui_action_factory.cpp000066400000000000000000000041121345753661000214640ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "gui_action_factory.h" namespace sigviewer { GuiActionFactory* GuiActionFactory::instance_ = 0; //----------------------------------------------------------------------------- GuiActionFactory* GuiActionFactory::getInstance () { if (!instance_) { instance_ = new GuiActionFactory; } return instance_; } //----------------------------------------------------------------------------- void GuiActionFactory::registerCommand (QString const& name, QSharedPointer command) { command_map_[name] = command; QStringList action_ids = command->getActionIDs(); for (QStringList::const_iterator id_iter = action_ids.begin (); id_iter != action_ids.end (); ++id_iter) action_to_command_map_[*id_iter] = command; } //----------------------------------------------------------------------------- QList GuiActionFactory::getQActions (QString const& command_name) const { if (command_name.size() == 0) { QList actions; foreach (QSharedPointer command, command_map_.values()) actions.append (command->getQActions()); return actions; } else if (!command_map_.contains (command_name)) return QList(); else return command_map_[command_name]->getQActions (); } //----------------------------------------------------------------------------- QAction* GuiActionFactory::getQAction (QString const& action_id) const { if (!action_to_command_map_.contains (action_id)) return 0; else return action_to_command_map_[action_id]->getQAction (action_id); } //----------------------------------------------------------------------------- void GuiActionFactory::initAllCommands () { for (CommandMap::iterator cmd_iter = command_map_.begin(); cmd_iter != command_map_.end(); ++cmd_iter) { cmd_iter.value()->initConnections(); cmd_iter.value()->init(); } } } sigviewer-0.6.4/src/gui/gui_action_factory.h000066400000000000000000000025021345753661000211320ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef GUI_ACTION_FACTORY_H #define GUI_ACTION_FACTORY_H #include "gui_action_command.h" #include #include #include #include #include namespace sigviewer { class GuiActionFactory { public: static GuiActionFactory* getInstance (); //------------------------------------------------------------------------- void registerCommand (QString const& name, QSharedPointer command); //------------------------------------------------------------------------- /// the caller must not delete QList getQActions (QString const& command_name = "") const; //------------------------------------------------------------------------- /// the caller must not delete QAction* getQAction (QString const& action_id) const; //------------------------------------------------------------------------- void initAllCommands (); private: static GuiActionFactory* instance_; typedef QMap > CommandMap; CommandMap command_map_; CommandMap action_to_command_map_; }; } #endif // GUI_ACTION_FACTORY_H sigviewer-0.6.4/src/gui/gui_action_factory_registrator.h000066400000000000000000000011331345753661000235560ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef GUI_ACTION_FACTORY_REGISTRATOR_H #define GUI_ACTION_FACTORY_REGISTRATOR_H #include "gui_action_command.h" #include "gui_action_factory.h" #include #include namespace sigviewer { class GuiActionFactoryRegistrator { public: GuiActionFactoryRegistrator (QString const& name, QSharedPointer command) { GuiActionFactory::getInstance()->registerCommand (name, command); } }; } #endif sigviewer-0.6.4/src/gui/main_window_model.h000066400000000000000000000025501345753661000207600ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MAIN_WINDOW_MODEL_H #define MAIN_WINDOW_MODEL_H #include "signal_visualisation_model.h" #include "event_view.h" #include "file_context.h" namespace sigviewer { class MainWindowModel { public: //------------------------------------------------------------------------- virtual ~MainWindowModel() {} //------------------------------------------------------------------------- virtual void closeCurrentFileTabs() = 0; //------------------------------------------------------------------------- virtual QSharedPointer createSignalVisualisation(QString const& title, ChannelManager const& channel_manager) = 0; //------------------------------------------------------------------------- virtual QSharedPointer createSignalVisualisationOfFile(QSharedPointer file_ctx) = 0; //------------------------------------------------------------------------- virtual QSharedPointer getCurrentSignalVisualisationModel() = 0; //------------------------------------------------------------------------- virtual QSharedPointer getCurrentEventView() = 0; }; } #endif // MAIN_WINDOW_MODEL_H sigviewer-0.6.4/src/gui/progress_bar.h000066400000000000000000000034101345753661000177510ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef PROGRESS_BAR_H #define PROGRESS_BAR_H #include "application_context.h" #include #include #include namespace sigviewer { class ProgressBar { public: static ProgressBar& instance () { static ProgressBar instance_; return instance_; } void initAndShow (int max_value, QString const& title, QSharedPointer app_context) { non_gui_mode_ = app_context->modeActivated (APPLICATION_NON_GUI_MODE); value_ = 0; max_value_ = max_value; if (non_gui_mode_) return; progress_dialog_ = new QProgressDialog; progress_dialog_->setModal (true); progress_dialog_->setMinimumDuration (2000); progress_dialog_->setWindowTitle (title); progress_dialog_->setMinimum (value_); progress_dialog_->setMaximum (max_value); progress_dialog_->setValue (value_); qDebug () << title << ": max_value = " << max_value; } void close () { delete progress_dialog_; } bool increaseValue (int step, QString const& description) { value_ += step; if (non_gui_mode_) return true; if (progress_dialog_.isNull()) return true; if (progress_dialog_->wasCanceled()) return false; progress_dialog_->setLabelText (description); progress_dialog_->setValue (value_); return true; } private: QPointer progress_dialog_; bool non_gui_mode_; int max_value_; int value_; }; } #endif // PROGRESS_BAR_H sigviewer-0.6.4/src/gui/signal_view_settings.cpp000066400000000000000000000041171345753661000220500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_view_settings.h" namespace sigviewer { //----------------------------------------------------------------------------- SignalViewSettings::SignalViewSettings (ChannelManager const& channel_manager) : pixels_per_sample_ (1), channel_overlapping_ (0), channel_heigth_in_pixels_ (20), channel_manager_ (channel_manager) { grid_fragmentation_[Qt::Horizontal] = 10; grid_fragmentation_[Qt::Vertical] = 4; } //----------------------------------------------------------------------------- void SignalViewSettings::setPixelsPerSample (float pixels_per_sample) { float old_pixel_per_sample = pixels_per_sample_; pixels_per_sample_ = pixels_per_sample; if (old_pixel_per_sample != pixels_per_sample_) emit pixelsPerSampleChanged (); } //----------------------------------------------------------------------------- void SignalViewSettings::setChannelOverlapping (float channel_overlapping) { float old_channel_overlapping = channel_overlapping_; channel_overlapping_ = channel_overlapping; if (old_channel_overlapping != channel_overlapping_) emit channelOverlappingChanged (); } //------------------------------------------------------------------------- void SignalViewSettings::setChannelHeight (int channel_heigth_in_pixels) { int old_channel_height = channel_heigth_in_pixels_; channel_heigth_in_pixels_ = channel_heigth_in_pixels; if (old_channel_height != channel_heigth_in_pixels_) { emit channelHeightChanged (); emit channelHeightChanged (channel_heigth_in_pixels_); } } //------------------------------------------------------------------------- void SignalViewSettings::setGridFragmentation (Qt::Orientation orientation, int fragmentation) { int old_fragmentation = grid_fragmentation_[orientation]; grid_fragmentation_[orientation] = fragmentation; if (old_fragmentation != fragmentation) emit gridFragmentationChanged (); } } sigviewer-0.6.4/src/gui/signal_view_settings.h000066400000000000000000000075731345753661000215260ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_VIEW_SETTINGS_H #define SIGNAL_VIEW_SETTINGS_H #include "base/sigviewer_user_types.h" #include "file_handling/channel_manager.h" #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// SignalViewSettings /// /// provides methods for changing the visualisation of a signal class SignalViewSettings : public QObject { Q_OBJECT Q_PROPERTY(float pixelsPerSample READ getPixelsPerSample WRITE setPixelsPerSample) Q_PROPERTY(float channelOverlapping READ getChannelOverlapping WRITE setChannelOverlapping) Q_PROPERTY(int channelHeight READ getChannelHeight WRITE setChannelHeight) public: //------------------------------------------------------------------------- SignalViewSettings (ChannelManager const& channel_manager); //------------------------------------------------------------------------- ChannelManager const& getChannelManager () const {return channel_manager_;} //------------------------------------------------------------------------- float getPixelsPerSample () const {return pixels_per_sample_;} //------------------------------------------------------------------------- float getChannelOverlapping () const {return channel_overlapping_;} //------------------------------------------------------------------------- int getChannelHeight () const {return channel_heigth_in_pixels_;} //------------------------------------------------------------------------- float getSampleRate () const {return channel_manager_.getSampleRate();} //------------------------------------------------------------------------- int getGridFragmentation (Qt::Orientation orientation) const {return grid_fragmentation_[orientation];} //------------------------------------------------------------------------- /// @return a set of ids of the shown channels //std::set getShownChannels () const {return shown_channels_;} public slots: //------------------------------------------------------------------------- void setPixelsPerSample (float pixel_per_sample); //------------------------------------------------------------------------- void setChannelOverlapping (float channel_overlapping); //------------------------------------------------------------------------- void setChannelHeight (int channel_heigth_in_pixels); //------------------------------------------------------------------------- void setGridFragmentation (Qt::Orientation orientation, int fragmentation); //------------------------------------------------------------------------- /// @param channels a set of ids of channels that should be visible //void setShownChannels (std::set const& channels) {shown_channels_ = channels; // shownChannelsChanged (shown_channels_);} //------------------------------------------------------------------------- //virtual QSharedPointer getChannelManager () const = 0; signals: void pixelsPerSampleChanged (); void channelOverlappingChanged (); void channelHeightChanged (); void channelHeightChanged (unsigned channel_height_in_pixel); void gridFragmentationChanged (); void enableXGrid(bool enabled); void enableYGrid(bool enabled); void separatorEnabled(bool enabled); void gridColorChanged(QColor gridColor); void labelColorChanged(QColor labelColor); private: //std::set shown_channels_; float pixels_per_sample_; float channel_overlapping_; int channel_heigth_in_pixels_; QMap grid_fragmentation_; ChannelManager const& channel_manager_; }; } #endif // SIGNAL_VIEW_SETTINGS_H sigviewer-0.6.4/src/gui/signal_visualisation_model.cpp000066400000000000000000000064071345753661000232340ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_visualisation_model.h" #include namespace sigviewer { //----------------------------------------------------------------------------- SignalVisualisationModel::SignalVisualisationModel (std::set const& shown_types, ChannelManager const& channel_manager) : signal_view_settings_ (new SignalViewSettings (channel_manager)), //pixel_per_sample_ (1), mode_ (MODE_HAND), event_creation_type_ (1), shown_event_types_ (shown_types), scale_mode_ (MIN_TO_MAX), selected_channel_ (UNDEFINED_CHANNEL), info_widget_ (0) { // nothing to do here } //----------------------------------------------------------------------------- void SignalVisualisationModel::setMode (SignalVisualisationMode mode) { mode_ = mode; emit modeChanged (mode_); modeChangedImpl (mode_); } //----------------------------------------------------------------------------- SignalVisualisationMode SignalVisualisationModel::getMode () const { return mode_; } //----------------------------------------------------------------------------- void SignalVisualisationModel::setInfoWidget (QWidget* info_widget) { info_widget_ = info_widget; } //------------------------------------------------------------------------- ChannelID SignalVisualisationModel::getSelectedChannel () const { return selected_channel_; } //------------------------------------------------------------------------- void SignalVisualisationModel::selectChannel (ChannelID channel) { selected_channel_ = channel; } //----------------------------------------------------------------------------- QList SignalVisualisationModel::getSelectedEvents () const { return QList (); } //----------------------------------------------------------------------------- std::set SignalVisualisationModel::getShownEventTypes () const { return shown_event_types_; } //----------------------------------------------------------------------------- void SignalVisualisationModel::setShownEventTypes (std::set const& event_types) { shown_event_types_ = event_types; emit shownEventTypesChanged (shown_event_types_); shownEventTypesChangedImpl (); } //----------------------------------------------------------------------------- EventType SignalVisualisationModel::getActualEventCreationType () const { return event_creation_type_; } //------------------------------------------------------------------------- void SignalVisualisationModel::setAutoScaleMode (ScaleMode scale_mode) { scale_mode_ = scale_mode; } //------------------------------------------------------------------------- ScaleMode SignalVisualisationModel::getAutoScaleMode () const { return scale_mode_; } //----------------------------------------------------------------------------- void SignalVisualisationModel::setActualEventCreationType (EventType type) { event_creation_type_ = type; } //----------------------------------------------------------------------------- QWidget* SignalVisualisationModel::infoWidget () { return info_widget_; } } sigviewer-0.6.4/src/gui/signal_visualisation_model.h000066400000000000000000000124521345753661000226760ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_VISUALISATION_MODEL_H #define SIGNAL_VISUALISATION_MODEL_H #include "signal_visualisation_modes.h" #include "signal_visualisation_view.h" #include "event_view.h" #include "signal_view_settings.h" namespace sigviewer { //----------------------------------------------------------------------------- /// SignalVisualisationModel /// /// base class for all class SignalVisualisationModel : public QObject, public EventView { Q_OBJECT Q_PROPERTY(int sample_position_ READ getShownPosition WRITE goToSample) public: //------------------------------------------------------------------------- /// virtual destructor virtual ~SignalVisualisationModel () {} //------------------------------------------------------------------------- QSharedPointer getSignalViewSettings () {return signal_view_settings_;} //------------------------------------------------------------------------- QSharedPointer getSignalViewSettings () const {return signal_view_settings_;} //------------------------------------------------------------------------- virtual std::set getShownChannels () const = 0; //------------------------------------------------------------------------- virtual void setShownChannels (std::set const& shown_channels) = 0; //------------------------------------------------------------------------- void setMode (SignalVisualisationMode mode); //------------------------------------------------------------------------- SignalVisualisationMode getMode () const; //------------------------------------------------------------------------- /// the visualisation view takes ownership of the info_widget void setInfoWidget (QWidget* info_widget); //------------------------------------------------------------------------- virtual void scaleChannel (ChannelID id, float32 lower_value, float32 upper_value) = 0; //------------------------------------------------------------------------- virtual void scaleChannel (ChannelID id) = 0; //------------------------------------------------------------------------- virtual ChannelManager const& getChannelManager () const = 0; //------------------------------------------------------------------------- /// @return the number of sample which is shown on the left side virtual unsigned getShownPosition () const = 0; //------------------------------------------------------------------------- /// sets the view that the given sample is on the left side virtual void goToSample (unsigned sample) = 0; //------------------------------------------------------------------------- virtual ChannelID getSelectedChannel () const; //------------------------------------------------------------------------- virtual void selectChannel (ChannelID channel); //------------------------------------------------------------------------- /// @return the id of the currently selected signal event virtual QList getSelectedEvents () const; //------------------------------------------------------------------------- virtual std::set getShownEventTypes () const; //------------------------------------------------------------------------- virtual void setShownEventTypes (std::set const& event_types); //------------------------------------------------------------------------- virtual void selectEvent (EventID) = 0; //------------------------------------------------------------------------- EventType getActualEventCreationType () const; //------------------------------------------------------------------------- void setAutoScaleMode (ScaleMode scale_mode); //------------------------------------------------------------------------- ScaleMode getAutoScaleMode () const; //------------------------------------------------------------------------- virtual SignalVisualisationView const* view () const = 0; //------------------------------------------------------------------------- QWidget* infoWidget (); public slots: //------------------------------------------------------------------------- virtual void update () {} //------------------------------------------------------------------------- void setActualEventCreationType (EventType type); signals: void shownEventTypesChanged (std::set const& shown_event_types); void signalHeightChanged (uint32 signal_height); void modeChanged (SignalVisualisationMode mode); protected: SignalVisualisationModel (std::set const& shown_types, ChannelManager const& channel_manager); virtual void shownEventTypesChangedImpl () = 0; virtual void modeChangedImpl (SignalVisualisationMode) {} private: QSharedPointer signal_view_settings_; SignalVisualisationMode mode_; EventType event_creation_type_; std::set shown_event_types_; unsigned sample_position_; ScaleMode scale_mode_; ChannelID selected_channel_; QWidget* info_widget_; }; } #endif // SIGNAL_VISUALISATION_MODEL_H sigviewer-0.6.4/src/gui/signal_visualisation_modes.h000066400000000000000000000005511345753661000227020ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_BROWSER_MODES_H #define SIGNAL_BROWSER_MODES_H namespace sigviewer { enum SignalVisualisationMode { MODE_NEW, MODE_POINTER, MODE_HAND, MODE_VIEW_OPTIONS, MODE_INFO }; } #endif sigviewer-0.6.4/src/gui/signal_visualisation_view.h000066400000000000000000000012451345753661000225460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_VISUALISATION_VIEW_H #define SIGNAL_VISUALISATION_VIEW_H #include #include #include namespace sigviewer { class SignalVisualisationView { public: virtual QSharedPointer renderVisibleScene () const = 0; virtual bool getXAxisVisibility () const = 0; virtual bool getYAxisVisibility () const = 0; virtual bool getLabelsVisibility () const = 0; virtual int getViewportHeight () const = 0; virtual int getViewportWidth () const = 0; }; } #endif sigviewer-0.6.4/src/gui_impl/000077500000000000000000000000001345753661000161335ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/commands/000077500000000000000000000000001345753661000177345ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/commands/adapt_channel_view_gui_command.cpp000066400000000000000000000237621345753661000266270ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "adapt_channel_view_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "gui_impl/dialogs/scale_channel_dialog.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- QString const AdaptChannelViewGuiCommand::CHANNELS_ = "Channels..."; QString const AdaptChannelViewGuiCommand::CHANGE_COLOR_ = "Change Color..."; QString const AdaptChannelViewGuiCommand::SCALE_ = "Scale..."; QString const AdaptChannelViewGuiCommand::APPLY_SCALE_TO_OTHER_CHANNELS_ = "Apply Scale to Other Channels"; QString const AdaptChannelViewGuiCommand::HIDE_ = "Hide Channel"; QString const AdaptChannelViewGuiCommand::SCALE_ALL_ = "Scale All..."; QString const AdaptChannelViewGuiCommand::SET_AUTO_SCALE_MAX_TO_MAX_ = "Zero Line Centered"; QString const AdaptChannelViewGuiCommand::SET_AUTO_SCALE_MIN_TO_MAX_ = "Zero Line Fitted"; QString const AdaptChannelViewGuiCommand::ANIMATIONS_ = "Animations"; QString const AdaptChannelViewGuiCommand::SET_ANIMATION_DURATION_ = "Set Animation Duration"; QStringList const AdaptChannelViewGuiCommand::ACTIONS_ = QStringList() << AdaptChannelViewGuiCommand::CHANNELS_ << AdaptChannelViewGuiCommand::SCALE_ALL_ << AdaptChannelViewGuiCommand::SET_AUTO_SCALE_MAX_TO_MAX_ << AdaptChannelViewGuiCommand::SET_AUTO_SCALE_MIN_TO_MAX_ << AdaptChannelViewGuiCommand::CHANGE_COLOR_ << AdaptChannelViewGuiCommand::SCALE_ << AdaptChannelViewGuiCommand::HIDE_ << AdaptChannelViewGuiCommand::ANIMATIONS_ << AdaptChannelViewGuiCommand::SET_ANIMATION_DURATION_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator registrator_ ("Adapt Channel View", QSharedPointer (new AdaptChannelViewGuiCommand)); //----------------------------------------------------------------------------- AdaptChannelViewGuiCommand::AdaptChannelViewGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::init () { setIcon (CHANNELS_, QIcon(":/images/ic_reorder_black_24dp.png")); setIcon (SCALE_ALL_, QIcon(":/images/ic_autoscale_black_24dp.png")); resetActionTriggerSlot (CHANNELS_, SLOT(selectShownChannels())); resetActionTriggerSlot (SCALE_ALL_, SLOT(scaleAll())); resetActionTriggerSlot (CHANGE_COLOR_, SLOT(changeColor())); resetActionTriggerSlot (SCALE_, SLOT(scale())); resetActionTriggerSlot (HIDE_, SLOT(hide())); setShortcut (CHANNELS_, tr("Ctrl+C")); //setShortcut (SCALE_ALL_, tr("Ctrl+A")); QActionGroup* scale_mode_action_group = new QActionGroup (this); scale_mode_action_group->setExclusive(true); scale_mode_action_group->addAction (getQAction(SET_AUTO_SCALE_MAX_TO_MAX_)); scale_mode_action_group->addAction (getQAction(SET_AUTO_SCALE_MIN_TO_MAX_)); getQAction(SET_AUTO_SCALE_MAX_TO_MAX_)->setCheckable(true); getQAction(SET_AUTO_SCALE_MIN_TO_MAX_)->setCheckable(true); getQAction(ANIMATIONS_)->setCheckable(true); QSettings settings; settings.beginGroup("Animations"); getQAction(ANIMATIONS_)->setChecked (settings.value("activated", false).toBool()); settings.endGroup(); resetActionTriggerSlot (SET_AUTO_SCALE_MAX_TO_MAX_, SLOT(setScaleModeZeroCentered())); resetActionTriggerSlot (SET_AUTO_SCALE_MIN_TO_MAX_, SLOT(setScaleModeZeroFitted())); resetActionTriggerSlot (ANIMATIONS_, SLOT(toggleAnimations())); resetActionTriggerSlot (SET_ANIMATION_DURATION_, SLOT(setAnimationDuration())); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::selectShownChannels () { QSharedPointer sv_model = currentVisModel (); std::set previous_shown_channels = sv_model->getShownChannels (); std::set new_shown_channels = GuiHelper::selectChannels (sv_model->getChannelManager(), applicationContext()->getEventColorManager(), QSharedPointer(0), sv_model); if (previous_shown_channels != new_shown_channels) sv_model->setShownChannels (new_shown_channels); sv_model->update (); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::evaluateEnabledness () { QStringList disabled_actions_if_no_file = ACTIONS_; disabled_actions_if_no_file.removeAll(ANIMATIONS_); disabled_actions_if_no_file.removeAll(SET_ANIMATION_DURATION_); disableIfNoFileIsOpened (disabled_actions_if_no_file); disableIfNoSignalIsVisualised (disabled_actions_if_no_file); if (!currentVisModel().isNull()) { getQAction (SET_AUTO_SCALE_MAX_TO_MAX_)->setChecked (currentVisModel()->getAutoScaleMode() == MAX_TO_MAX); getQAction (SET_AUTO_SCALE_MIN_TO_MAX_)->setChecked (currentVisModel()->getAutoScaleMode() == MIN_TO_MAX); } } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::changeColor () { if (currentVisModel().isNull()) return; ChannelID channel = currentVisModel()->getSelectedChannel(); if (channel == UNDEFINED_CHANNEL) return; QSharedPointer color_manager = applicationContext()->getEventColorManager(); QColor old_color = color_manager->getChannelColor(channel); QColorDialog color_dialog (old_color); color_dialog.setOption(QColorDialog::ShowAlphaChannel); if (color_dialog.exec() == QDialog::Accepted) { color_manager->setChannelColor (channel, color_dialog.selectedColor()); color_manager->saveSettings (); currentVisModel()->update(); } } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::scale () { ChannelID channel = currentVisModel()->getSelectedChannel(); if (channel == UNDEFINED_CHANNEL) return; ScaleChannelDialog scale_dialog (channel, currentVisModel()->getShownChannels(), currentVisModel()->getChannelManager()); if (scale_dialog.exec() == QDialog::Accepted) { currentVisModel()->scaleChannel (channel, scale_dialog.lowerValue(), scale_dialog.upperValue()); } } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::applyScaleToOtherChannels () { ChannelID channel = currentVisModel()->getSelectedChannel(); if (channel == UNDEFINED_CHANNEL) return; // TODO: implement! } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::hide () { ChannelID channel = currentVisModel()->getSelectedChannel(); if (channel == UNDEFINED_CHANNEL) return; std::set shown_channels = currentVisModel()->getShownChannels(); shown_channels.erase (channel); currentVisModel()->setShownChannels (shown_channels); currentVisModel()->update(); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::scaleAll () { ScaleChannelDialog scale_dialog (UNDEFINED_CHANNEL, currentVisModel()->getShownChannels(), currentVisModel()->getChannelManager()); if (scale_dialog.exec() == QDialog::Accepted) { if (scale_dialog.autoScaling()) { currentVisModel()->setAutoScaleMode (MIN_TO_MAX); currentVisModel()->scaleChannel(UNDEFINED_CHANNEL); } else { currentVisModel()->scaleChannel (UNDEFINED_CHANNEL, scale_dialog.lowerValue(), scale_dialog.upperValue()); } } } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::setScaleModeZeroCentered () { currentVisModel()->setAutoScaleMode (MAX_TO_MAX); currentVisModel()->scaleChannel(UNDEFINED_CHANNEL); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::setScaleModeZeroFitted () { currentVisModel()->setAutoScaleMode (MIN_TO_MAX); currentVisModel()->scaleChannel(UNDEFINED_CHANNEL); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::toggleAnimations () { QSettings settings; settings.beginGroup ("Animations"); settings.setValue ("activated", getQAction(ANIMATIONS_)->isChecked ()); settings.endGroup (); } //------------------------------------------------------------------------- void AdaptChannelViewGuiCommand::setAnimationDuration () { QSettings settings; settings.beginGroup ("Animations"); bool ok = false; int new_duration = QInputDialog::getInt (0, tr("Set Animation Duration"), tr("Milliseconds:"), settings.value("duration", 200).toInt(), 0, 1000, 100, &ok); if (ok) settings.setValue ("duration", new_duration); settings.endGroup (); } } sigviewer-0.6.4/src/gui_impl/commands/adapt_channel_view_gui_command.h000066400000000000000000000051501345753661000262630ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef VIEW_OPTIONS_GUI_COMMAND_H #define VIEW_OPTIONS_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" namespace sigviewer { //----------------------------------------------------------------------------- class AdaptChannelViewGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- AdaptChannelViewGuiCommand (); //------------------------------------------------------------------------- virtual ~AdaptChannelViewGuiCommand () {} //------------------------------------------------------------------------- virtual void init (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private slots: //------------------------------------------------------------------------- void selectShownChannels (); //------------------------------------------------------------------------- void changeColor (); //------------------------------------------------------------------------- void scale (); //------------------------------------------------------------------------- void applyScaleToOtherChannels (); //------------------------------------------------------------------------- void hide (); //------------------------------------------------------------------------- void scaleAll (); //------------------------------------------------------------------------- void setScaleModeZeroCentered (); //------------------------------------------------------------------------- void setScaleModeZeroFitted (); //------------------------------------------------------------------------- void toggleAnimations (); //------------------------------------------------------------------------- void setAnimationDuration (); private: static QString const CHANNELS_; static QString const CHANGE_COLOR_; static QString const SCALE_; static QString const APPLY_SCALE_TO_OTHER_CHANNELS_; static QString const HIDE_; static QString const SCALE_ALL_; static QString const SET_AUTO_SCALE_MAX_TO_MAX_; static QString const SET_AUTO_SCALE_MIN_TO_MAX_; static QString const ANIMATIONS_; static QString const SET_ANIMATION_DURATION_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // VIEW_OPTIONS_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/adapt_event_view_gui_command.cpp000066400000000000000000000201311345753661000263230ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "adapt_event_view_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "gui/signal_visualisation_model.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QString const AdaptEventViewGuiCommand::FIT_TO_EVENT_ = "Fit View to Selected Event"; QString const AdaptEventViewGuiCommand::HIDE_EVENTS_OF_OTHER_TYPE_ = "Hide Events of other Type"; QString const AdaptEventViewGuiCommand::SHOW_ALL_EVENTS_ = "Show all Events"; QString const AdaptEventViewGuiCommand::GO_TO_NEXT_EVENT_ = "Goto and Select Next Event"; QString const AdaptEventViewGuiCommand::GO_TO_PREVIOUS_EVENT_ = "Goto and Select Previous Event"; QString const AdaptEventViewGuiCommand::SET_SHOWN_EVENTS_ = "Events..."; QStringList const AdaptEventViewGuiCommand::ACTIONS_ = QStringList() << AdaptEventViewGuiCommand::FIT_TO_EVENT_ << AdaptEventViewGuiCommand::GO_TO_NEXT_EVENT_ << AdaptEventViewGuiCommand::GO_TO_PREVIOUS_EVENT_ << AdaptEventViewGuiCommand::HIDE_EVENTS_OF_OTHER_TYPE_ << AdaptEventViewGuiCommand::SHOW_ALL_EVENTS_ << AdaptEventViewGuiCommand::SET_SHOWN_EVENTS_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator AdaptEventViewGuiCommand::registrator_ ("Adapt Event View", QSharedPointer (new AdaptEventViewGuiCommand)); //----------------------------------------------------------------------------- AdaptEventViewGuiCommand::AdaptEventViewGuiCommand () : GuiActionCommand (ACTIONS_), current_event_ (UNDEFINED_EVENT_ID), next_event_ (UNDEFINED_EVENT_ID), previous_event_ (UNDEFINED_EVENT_ID) { // nothing to do here } //----------------------------------------------------------------------------- void AdaptEventViewGuiCommand::init () { setShortcut (GO_TO_NEXT_EVENT_, QKeySequence("Ctrl+Right")); setShortcut (GO_TO_PREVIOUS_EVENT_, QKeySequence("Ctrl+Left")); setShortcut (SET_SHOWN_EVENTS_, tr("Ctrl+E")); setIcon (GO_TO_NEXT_EVENT_, QIcon(":/images/ic_chevron_right_black_24dp.png")); setIcon (GO_TO_PREVIOUS_EVENT_, QIcon(":/images/ic_chevron_left_black_24dp.png")); setIcon (SET_SHOWN_EVENTS_, QIcon(":/images/ic_flag_black_24dp.png")); setIcon (FIT_TO_EVENT_, QIcon(":/images/ic_zoom_out_map_black_24dp.png")); resetActionTriggerSlot (HIDE_EVENTS_OF_OTHER_TYPE_, SLOT(hideEventsOfOtherType())); resetActionTriggerSlot (SHOW_ALL_EVENTS_, SLOT(showAllEvents())); resetActionTriggerSlot (SET_SHOWN_EVENTS_, SLOT(setShownEvents())); } //----------------------------------------------------------------------------- void AdaptEventViewGuiCommand::trigger (QString const& action_name) { if (action_name == FIT_TO_EVENT_) fitViewToEvent (); else if (action_name == GO_TO_NEXT_EVENT_) gotoAndSelectEvent (true); else if (action_name == GO_TO_PREVIOUS_EVENT_) gotoAndSelectEvent (false); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::hideEventsOfOtherType () { QList > events = GuiHelper::getSelectedEvents (currentEventView()); if (events.size() != 1) return; std::set shown_types; shown_types.insert (events.first()->getType ()); currentVisModel()->setShownEventTypes (shown_types); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::showAllEvents () { std::set shown_types = currentVisModel()->getEventManager()->getEventTypes(); currentVisModel()->setShownEventTypes (shown_types); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::setShownEvents () { std::set shown_types = currentVisModel()->getShownEventTypes (); std::set new_shown_types = GuiHelper::selectEventTypes (shown_types, currentVisModel()->getEventManager(), applicationContext()->getEventColorManager()); if (shown_types != new_shown_types) currentVisModel()->setShownEventTypes (new_shown_types); currentVisModel()->update (); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::evaluateEnabledness () { if (disableIfNoFileIsOpened (ACTIONS_)) return; if (disableIfNoEventsPossible (ACTIONS_)) return; disableIfNoEventSelected (QStringList() << HIDE_EVENTS_OF_OTHER_TYPE_ << FIT_TO_EVENT_); setNextAndPreviousEvent (); getQAction (SET_SHOWN_EVENTS_)->setEnabled (currentEventView()->eventsHidable()); getQAction (HIDE_EVENTS_OF_OTHER_TYPE_)->setEnabled (currentEventView()->eventsHidable()); getQAction (SHOW_ALL_EVENTS_)->setEnabled (currentEventView()->eventsHidable()); getQAction (FIT_TO_EVENT_)->setEnabled (currentEventView()->eventsHidable()); getQAction (GO_TO_NEXT_EVENT_)->setEnabled (currentEventView()->eventsSlidable()); getQAction (GO_TO_PREVIOUS_EVENT_)->setEnabled (currentEventView()->eventsSlidable()); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::fitViewToEvent () { QList > events = GuiHelper::getSelectedEvents (currentVisModel()); if (events.size() != 1) return; QSharedPointer event = events.first(); float64 width = currentVisModel()->view()->getViewportWidth(); float64 desired_pixel_per_sample = width / event->getDuration (); currentSignalViewSettings()->setPixelsPerSample (desired_pixel_per_sample); currentVisModel()->goToSample (event->getPosition ()); } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::gotoAndSelectEvent (bool forward) { QSharedPointer event_manager = currentVisModel()->getEventManager(); if (event_manager.isNull()) { qCritical() << "AdaptEventViewGuiCommand::gotoAndSelectEvent no EventManager available!!"; return; } EventID event_id; if (forward) event_id = next_event_; else event_id = previous_event_; QSharedPointer event = event_manager->getEvent (event_id); if (!event.isNull()) { GuiHelper::animateProperty(currentVisModel().data(), "sample_position_", currentVisModel()->getShownPosition(), (unsigned) event->getPosition()); currentVisModel()->selectEvent (event->getId()); } } //------------------------------------------------------------------------- void AdaptEventViewGuiCommand::setNextAndPreviousEvent () { QList > events = GuiHelper::getSelectedEvents (currentVisModel()); if (events.size() != 1) return; QSharedPointer event = events.first(); if (!event.isNull ()) { if (current_event_ == event->getId ()) return; current_event_ = event->getId (); QSharedPointer event_manager = currentVisModel()->getEventManager (); next_event_ = event_manager->getNextEventOfSameType (event->getId ()); previous_event_ = event_manager->getPreviousEventOfSameType (event->getId ()); qDebug () << "next event " << next_event_; qDebug () << "previous event "<< previous_event_; } getQAction (GO_TO_NEXT_EVENT_)->setEnabled (next_event_ != UNDEFINED_EVENT_ID); getQAction (GO_TO_PREVIOUS_EVENT_)->setEnabled (previous_event_ != UNDEFINED_EVENT_ID); } } sigviewer-0.6.4/src/gui_impl/commands/adapt_event_view_gui_command.h000066400000000000000000000046461345753661000260050ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FIT_VIEW_GUI_COMMAND_H #define FIT_VIEW_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include namespace sigviewer { //------------------------------------------------------------------------- class AdaptEventViewGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- AdaptEventViewGuiCommand (); //------------------------------------------------------------------------- virtual ~AdaptEventViewGuiCommand () {} //------------------------------------------------------------------------- virtual void init (); public slots: //------------------------------------------------------------------------- virtual void trigger (QString const& action_name); //------------------------------------------------------------------------- void hideEventsOfOtherType (); //------------------------------------------------------------------------- void showAllEvents (); //------------------------------------------------------------------------- void setShownEvents (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: //------------------------------------------------------------------------- void fitViewToEvent (); //------------------------------------------------------------------------- void gotoAndSelectEvent (bool forward); //------------------------------------------------------------------------- void setNextAndPreviousEvent (); //------------------------------------------------------------------------- EventID current_event_; EventID next_event_; EventID previous_event_; //------------------------------------------------------------------------- static QString const FIT_TO_EVENT_; static QString const HIDE_EVENTS_OF_OTHER_TYPE_; static QString const SHOW_ALL_EVENTS_; static QString const GO_TO_NEXT_EVENT_; static QString const GO_TO_PREVIOUS_EVENT_; static QString const SET_SHOWN_EVENTS_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // FIT_VIEW_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/close_file_gui_command.cpp000066400000000000000000000064061345753661000251140ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "close_file_gui_command.h" #include "file_handling_impl/xdf_reader.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- QString const CloseFileGuiCommand::CLOSE_FILE_ = "Close"; QString const CloseFileGuiCommand::EXIT_APPLICATION_ = "Exit"; QStringList const CloseFileGuiCommand::ACTIONS_ = QStringList() << CloseFileGuiCommand::CLOSE_FILE_ << CloseFileGuiCommand::EXIT_APPLICATION_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator CloseFileGuiCommand::registrator_ ("Closing", QSharedPointer (new CloseFileGuiCommand)); //----------------------------------------------------------------------------- CloseFileGuiCommand::CloseFileGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void CloseFileGuiCommand::init () { getQAction(CLOSE_FILE_)->setShortcut (QKeySequence::Close); getQAction(CLOSE_FILE_)->setIcon (QIcon(":/images/ic_clear_black_24dp.png")); getQAction(EXIT_APPLICATION_)->setShortcut (QKeySequence::Quit); resetActionTriggerSlot(CLOSE_FILE_, SLOT(closeFile())); resetActionTriggerSlot(EXIT_APPLICATION_, SLOT(exitApplication())); } //------------------------------------------------------------------------- bool CloseFileGuiCommand::closeCurrentFile () { QSharedPointer current_file_context = applicationContext()->getCurrentFileContext(); if (current_file_context.isNull()) return true; if (current_file_context->getState () == FILE_STATE_CHANGED) { QString file_name = current_file_context->getFileName (); QMessageBox::StandardButton pressed_button = QMessageBox::question (0, tr("Really close?"), tr("Changes in '%1' are not saved!!").arg(file_name) + "\n" + tr("Really close?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (pressed_button == QMessageBox::No) return false; } if (current_file_context->getFileName().endsWith("xdf", Qt::CaseInsensitive)) { Xdf empty; std::swap(*XDFdata, empty);//clear the data of the previous XDF file } applicationContext()->getMainWindowModel ()->closeCurrentFileTabs (); applicationContext()->removeCurrentFileContext (); return true; } //------------------------------------------------------------------------- void CloseFileGuiCommand::closeFile () { closeCurrentFile (); } //------------------------------------------------------------------------- void CloseFileGuiCommand::exitApplication () { if (closeCurrentFile ()) QApplication::exit (); } //------------------------------------------------------------------------- void CloseFileGuiCommand::evaluateEnabledness () { disableIfNoFileIsOpened (QStringList() << CLOSE_FILE_); } } sigviewer-0.6.4/src/gui_impl/commands/close_file_gui_command.h000066400000000000000000000036701345753661000245610ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CLOSE_FILE_GUI_COMMAND_H #define CLOSE_FILE_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include "file_handling/file_signal_reader.h" namespace sigviewer { //----------------------------------------------------------------------------- /// CloseFileGuiCommand /// /// command for closing a file class CloseFileGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- CloseFileGuiCommand (); //------------------------------------------------------------------------- virtual ~CloseFileGuiCommand () {} //------------------------------------------------------------------------- virtual void init (); //------------------------------------------------------------------------- bool closeCurrentFile (); public slots: //------------------------------------------------------------------------- void closeFile (); //------------------------------------------------------------------------- void exitApplication (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: static QString const CLOSE_FILE_; static QString const EXIT_APPLICATION_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; //------------------------------------------------------------------------- QString showCloseDialog (QString const& path, QString const& extensions); //------------------------------------------------------------------------- QSharedPointer createAndCloseFileSignalReader (QString const& file_path) const; }; } #endif // CLOSE_FILE_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/commands.pri000066400000000000000000000015431345753661000222540ustar00rootroot00000000000000HEADERS += \ $$PWD/adapt_channel_view_gui_command.h \ $$PWD/adapt_event_view_gui_command.h \ $$PWD/close_file_gui_command.h \ $$PWD/event_editing_gui_command.h \ $$PWD/help_gui_command.h \ $$PWD/mouse_mode_gui_command.h \ $$PWD/open_file_gui_command.h \ $$PWD/save_gui_command.h \ $$PWD/signal_processing_gui_command.h \ $$PWD/undo_redo_gui_command.h \ $$PWD/zoom_gui_command.h SOURCES += \ $$PWD/adapt_channel_view_gui_command.cpp \ $$PWD/adapt_event_view_gui_command.cpp \ $$PWD/close_file_gui_command.cpp \ $$PWD/event_editing_gui_command.cpp \ $$PWD/help_gui_command.cpp \ $$PWD/mouse_mode_gui_command.cpp \ $$PWD/open_file_gui_command.cpp \ $$PWD/save_gui_command.cpp \ $$PWD/signal_processing_gui_command.cpp \ $$PWD/undo_redo_gui_command.cpp \ $$PWD/zoom_gui_command.cpp sigviewer-0.6.4/src/gui_impl/commands/event_editing_gui_command.cpp000066400000000000000000000226651345753661000256410ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_editing_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "editing_commands/delete_event_undo_command.h" #include "editing_commands/change_type_undo_command.h" #include "editing_commands/change_channel_undo_command.h" #include "editing_commands/new_event_undo_command.h" #include "editing_commands/macro_undo_command.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QString const EventEditingGuiCommand::DELETE_ = "Delete"; QString const EventEditingGuiCommand::CHANGE_TYPE_ = "Change Type..."; QString const EventEditingGuiCommand::CHANGE_CHANNEL_ = "Change Channel..."; QString const EventEditingGuiCommand::TO_ALL_CHANNEL_ = "To all Channels"; QString const EventEditingGuiCommand::COPY_TO_CHANNELS_ = "Copy to Channels..."; QString const EventEditingGuiCommand::INSERT_OVER_ = "Insert Over"; QStringList const EventEditingGuiCommand::ACTIONS_ = QStringList () << EventEditingGuiCommand::DELETE_ << EventEditingGuiCommand::CHANGE_TYPE_ << EventEditingGuiCommand::CHANGE_CHANNEL_ << EventEditingGuiCommand::TO_ALL_CHANNEL_ << EventEditingGuiCommand::COPY_TO_CHANNELS_ << EventEditingGuiCommand::INSERT_OVER_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator EventEditingGuiCommand::registrator_ ("Event Editing", QSharedPointer (new EventEditingGuiCommand)); //----------------------------------------------------------------------------- EventEditingGuiCommand::EventEditingGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- EventEditingGuiCommand::~EventEditingGuiCommand () { // nothing to do here } //----------------------------------------------------------------------------- void EventEditingGuiCommand::init () { resetActionTriggerSlot (DELETE_, SLOT (deleteSelectedEvent())); resetActionTriggerSlot (CHANGE_TYPE_, SLOT (changeTypeSelectedEvent())); resetActionTriggerSlot (CHANGE_CHANNEL_, SLOT (changeChannelSelectedEvent())); resetActionTriggerSlot (TO_ALL_CHANNEL_, SLOT (toAllChannelsSelectedEvent())); resetActionTriggerSlot (COPY_TO_CHANNELS_, SLOT (copyToChannelsSelectedEvent())); resetActionTriggerSlot (INSERT_OVER_, SLOT (insertEventOverSelectedEvent())); getQAction (DELETE_)->setIcon (QIcon(":/images/ic_delete_forever_black_24dp.png")); getQAction (TO_ALL_CHANNEL_)->setIcon (QIcon (":/images/ic_font_download_black_24dp.png")); getQAction (COPY_TO_CHANNELS_)->setIcon (QIcon (":/images/ic_content_copy_black_24dp.png")); getQAction (INSERT_OVER_)->setIcon (QIcon (":/images/ic_add_circle_outline_black_24dp.png")); getQAction (DELETE_)->setShortcut (QKeySequence::Delete); // getQAction (INSERT_OVER_)->setShortcut (QKeySequence("Ctrl+I")); } //----------------------------------------------------------------------------- void EventEditingGuiCommand::deleteSelectedEvent () { QList > commands; foreach (EventID event, GuiHelper::getSelectedEventIDs (currentEventView())) { commands.append (QSharedPointer (new DeleteEventUndoCommand ( currentEventView()->getEventManager(), event))); } executeCommands (commands); } //----------------------------------------------------------------------------- void EventEditingGuiCommand::changeTypeSelectedEvent () { QList > commands; foreach (EventID event, GuiHelper::getSelectedEventIDs (currentEventView())) { QSharedPointer event_manager = currentVisModel()->getEventManager(); EventType pre_selected_type = event_manager->getEvent (event)->getType (); EventType new_type = GuiHelper::selectEventType (pre_selected_type, currentVisModel()); if (new_type == UNDEFINED_EVENT_TYPE) return; commands.append (QSharedPointer (new ChangeTypeUndoCommand ( event_manager, event, new_type))); } executeCommands (commands); } //------------------------------------------------------------------------- void EventEditingGuiCommand::changeChannelSelectedEvent () { QList > commands; foreach (EventID event, GuiHelper::getSelectedEventIDs (currentEventView())) { QSharedPointer event_manager = currentVisModel()->getEventManager(); ChannelID preselected_channel = event_manager->getEvent (event)->getChannel (); ChannelID new_channel = GuiHelper::selectChannel (preselected_channel, currentVisModel()); if (new_channel == preselected_channel) return; commands.append (QSharedPointer (new ChangeChannelUndoCommand (event_manager, event, new_channel))); } executeCommands (commands); } //------------------------------------------------------------------------- void EventEditingGuiCommand::toAllChannelsSelectedEvent () { QList > commands; foreach (EventID event, GuiHelper::getSelectedEventIDs (currentEventView())) { QSharedPointer event_manager = currentVisModel()->getEventManager(); if (event_manager->getEvent (event)->getChannel () == UNDEFINED_CHANNEL) return; commands.append (QSharedPointer (new ChangeChannelUndoCommand (event_manager, event, UNDEFINED_CHANNEL))); } executeCommands (commands); } //------------------------------------------------------------------------- void EventEditingGuiCommand::copyToChannelsSelectedEvent () { QList > commands; foreach (EventID event_id, GuiHelper::getSelectedEventIDs (currentEventView())) { QSharedPointer event_manager = currentVisModel()->getEventManager(); QSharedPointer event = event_manager->getEvent (event_id); std::set channels = GuiHelper::selectShownChannels (event->getChannel (), currentVisModel()); if (channels.size () == 0) return; for (std::set::iterator channel_iter = channels.begin(); channel_iter != channels.end(); ++channel_iter) { QSharedPointer new_event (new SignalEvent (*event)); new_event->setChannel (*channel_iter); QSharedPointer command (new NewEventUndoCommand (event_manager, new_event, 1)); commands.append (command); } } executeCommands (commands); } //------------------------------------------------------------------------- void EventEditingGuiCommand::insertEventOverSelectedEvent () { QList > commands; foreach (EventID event, GuiHelper::getSelectedEventIDs (currentEventView())) { if (event == UNDEFINED_EVENT_ID) return; QSharedPointer event_manager = currentVisModel()->getEventManager(); QSharedPointer sv_model = currentVisModel(); QSharedPointer new_event (new SignalEvent (*(event_manager->getEvent (event)))); new_event->setType (sv_model->getActualEventCreationType ()); commands.append (QSharedPointer(new NewEventUndoCommand (event_manager, new_event, 1))); } executeCommands (commands); } //------------------------------------------------------------------------- void EventEditingGuiCommand::evaluateEnabledness () { if (disableIfNoFileIsOpened (ACTIONS_)) return; if (disableIfNoEventsPossible (ACTIONS_)) return; bool event_one_channel_selected = (getTabSelectionState() == TAB_STATE_EVENT_SELECTED_ONE_CHANNEL); getQAction(COPY_TO_CHANNELS_)->setEnabled(event_one_channel_selected); getQAction(TO_ALL_CHANNEL_)->setEnabled(event_one_channel_selected); disableIfNoEventSelected (QStringList() << INSERT_OVER_ << CHANGE_CHANNEL_ << CHANGE_TYPE_ << DELETE_); } //------------------------------------------------------------------------- void EventEditingGuiCommand::executeCommands (QList > commands) { MacroUndoCommand* macro = new MacroUndoCommand (commands); applicationContext()->getCurrentCommandExecuter()->executeCommand (macro); } } sigviewer-0.6.4/src/gui_impl/commands/event_editing_gui_command.h000066400000000000000000000041311345753661000252720ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_EDITING_GUI_COMMAND_H #define EVENT_EDITING_GUI_COMMAND_H #include "base/sigviewer_user_types.h" #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include namespace sigviewer { class EventEditingGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- EventEditingGuiCommand (); //------------------------------------------------------------------------- virtual ~EventEditingGuiCommand (); //------------------------------------------------------------------------- virtual void init (); public slots: //------------------------------------------------------------------------- void deleteSelectedEvent (); //------------------------------------------------------------------------- void changeTypeSelectedEvent (); //------------------------------------------------------------------------- void changeChannelSelectedEvent (); //------------------------------------------------------------------------- void toAllChannelsSelectedEvent (); //------------------------------------------------------------------------- void copyToChannelsSelectedEvent (); //------------------------------------------------------------------------- void insertEventOverSelectedEvent (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: void executeCommands (QList > commands); static QString const DELETE_; static QString const CHANGE_TYPE_; static QString const CHANGE_CHANNEL_; static QString const TO_ALL_CHANNEL_; static QString const COPY_TO_CHANNELS_; static QString const INSERT_OVER_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // EVENT_EDITING_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/help_gui_command.cpp000066400000000000000000000042701345753661000237350ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "help_gui_command.h" #include "tests/tests_dialog.h" #include "ui_about_dialog.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QString const HelpGuiCommand::ABOUT_ = "About"; QString const HelpGuiCommand::RUN_TESTS_ = "Run Tests..."; QStringList const HelpGuiCommand::ACTIONS_ = QStringList() << HelpGuiCommand::ABOUT_ << HelpGuiCommand::RUN_TESTS_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator HelpGuiCommand::registrator_ ("Help", QSharedPointer(new HelpGuiCommand)); //----------------------------------------------------------------------------- HelpGuiCommand::HelpGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void HelpGuiCommand::init () { resetActionTriggerSlot (ABOUT_, SLOT(showAboutDialog())); setIcon (ABOUT_, QIcon(":/images/ic_help_outline_black_24dp.png")); resetActionTriggerSlot (RUN_TESTS_, SLOT(runTests())); } //----------------------------------------------------------------------------- void HelpGuiCommand::showAboutDialog () { dialog_ = new QDialog(0); Ui::aboutDialog ui; ui.setupUi (&(*dialog_)); ui.aboutLabel->setText(ui.aboutLabel->text().replace(QString("VERSION_MAJOR"), QString::number(VERSION_MAJOR)) .replace(QString("VERSION_MINOR"), QString::number(VERSION_MINOR)) .replace(QString("VERSION_BUILD"), QString::number(VERSION_BUILD))); dialog_->setFixedSize(dialog_->minimumSizeHint()); dialog_->show(); } //----------------------------------------------------------------------------- void HelpGuiCommand::runTests () { TestsDialog tests_dialog; tests_dialog.exec (); } } sigviewer-0.6.4/src/gui_impl/commands/help_gui_command.h000066400000000000000000000022151345753661000233770ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef HELP_GUI_COMMAND_H #define HELP_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" namespace sigviewer { class HelpGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- HelpGuiCommand (); //------------------------------------------------------------------------- virtual ~HelpGuiCommand () {} //------------------------------------------------------------------------- virtual void init (); private slots: //------------------------------------------------------------------------- void showAboutDialog (); //------------------------------------------------------------------------- void runTests (); private: static QString const ABOUT_; static QString const RUN_TESTS_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; QDialog* dialog_; }; } #endif // HELP_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/mouse_mode_gui_command.cpp000066400000000000000000000111641345753661000251410ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "mouse_mode_gui_command.h" #include "gui/signal_visualisation_model.h" namespace sigviewer { //----------------------------------------------------------------------------- QString const MouseModeGuiCommand::NEW_MODE_TEXT_ = "New Event"; QString const MouseModeGuiCommand::POINTER_MODE_TEXT_ = "Edit Event"; QString const MouseModeGuiCommand::HAND_MODE_TEXT_ = "Scroll"; QString const MouseModeGuiCommand::VIEW_OPTIONS_TEXT_ = "View Options"; QString const MouseModeGuiCommand::INFO_MODE_TEXT_ = "Info"; QStringList const MouseModeGuiCommand::MODE_TEXTS_ = QStringList() << MouseModeGuiCommand::NEW_MODE_TEXT_ << MouseModeGuiCommand::POINTER_MODE_TEXT_ << MouseModeGuiCommand::HAND_MODE_TEXT_ << MouseModeGuiCommand::VIEW_OPTIONS_TEXT_; //<< MouseModeGuiCommand::INFO_MODE_TEXT_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator MouseModeGuiCommand::registrator_ ("Mouse Modes", QSharedPointer (new MouseModeGuiCommand)); //----------------------------------------------------------------------------- MouseModeGuiCommand::MouseModeGuiCommand () : GuiActionCommand (MODE_TEXTS_) { action_to_mode_map_[NEW_MODE_TEXT_] = MODE_NEW; action_to_mode_map_[POINTER_MODE_TEXT_] = MODE_POINTER; action_to_mode_map_[HAND_MODE_TEXT_] = MODE_HAND; action_to_mode_map_[VIEW_OPTIONS_TEXT_] = MODE_VIEW_OPTIONS; //action_to_mode_map_[INFO_MODE_TEXT_] = MODE_INFO; } //----------------------------------------------------------------------------- MouseModeGuiCommand::~MouseModeGuiCommand () { // nothing to do here } //----------------------------------------------------------------------------- void MouseModeGuiCommand::init () { QActionGroup* mouse_mode_action_group = new QActionGroup (this); mouse_mode_action_group->setExclusive(true); getQAction (NEW_MODE_TEXT_)->setIcon (QIcon(":/images/ic_add_box_black_24dp.png")); getQAction (POINTER_MODE_TEXT_)->setIcon (QIcon(":/images/ic_create_black_24dp.png")); getQAction (HAND_MODE_TEXT_)->setIcon (QIcon(":/images/ic_pan_tool_black_24dp.png")); getQAction (VIEW_OPTIONS_TEXT_)->setIcon (QIcon(":/images/ic_build_black_24dp.png")); getQAction (NEW_MODE_TEXT_)->setShortcut (QString("Ctrl+1")); getQAction (POINTER_MODE_TEXT_)->setShortcut (QString("Ctrl+2")); getQAction (HAND_MODE_TEXT_)->setShortcut (QString("Ctrl+3")); getQAction (VIEW_OPTIONS_TEXT_)->setShortcut (QString("Ctrl+4")); //getQAction (INFO_MODE_TEXT_)->setShortcut (QString("Ctrl+5")); // getQAction (NEW_MODE_TEXT_)->setToolTip(getQAction (NEW_MODE_TEXT_)->toolTip().append(tr(" (Ctrl+1)"))); // getQAction (POINTER_MODE_TEXT_)->setToolTip(getQAction (POINTER_MODE_TEXT_)->toolTip().append(tr(" (Ctrl+2)"))); // getQAction (HAND_MODE_TEXT_)->setToolTip(getQAction (HAND_MODE_TEXT_)->toolTip().append(tr(" (Ctrl+3)"))); // getQAction (VIEW_OPTIONS_TEXT_)->setToolTip(getQAction (VIEW_OPTIONS_TEXT_)->toolTip().append(tr(" (Ctrl+4)"))); QList actions = getQActions (); foreach (QAction* action, actions) { mouse_mode_action_group->addAction (action); action->setCheckable (true); } getQAction (HAND_MODE_TEXT_)->setChecked (true); } //----------------------------------------------------------------------------- void MouseModeGuiCommand::trigger (QString const& action_name) { currentVisModel()->setMode (action_to_mode_map_[action_name]); } //------------------------------------------------------------------------- void MouseModeGuiCommand::evaluateEnabledness () { if (disableIfNoFileIsOpened (MODE_TEXTS_)) return; if (disableIfNoSignalIsVisualised(MODE_TEXTS_)) return; if (!currentVisModel().isNull()) { getQAction(NEW_MODE_TEXT_)->setDisabled(currentVisModel()->getEventManager().isNull()); getQAction(POINTER_MODE_TEXT_)->setDisabled(currentVisModel()->getEventManager().isNull()); } } //----------------------------------------------------------------------------- void MouseModeGuiCommand::applicationStateChanged () { if (getApplicationState () == APP_STATE_FILE_OPEN) getQAction (HAND_MODE_TEXT_)->setChecked (true); } } sigviewer-0.6.4/src/gui_impl/commands/mouse_mode_gui_command.h000066400000000000000000000026121345753661000246040ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MOUSE_MODE_GUI_COMMAND_H #define MOUSE_MODE_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include "gui/signal_visualisation_modes.h" #include #include namespace sigviewer { class MouseModeGuiCommand : public GuiActionCommand { Q_OBJECT public: MouseModeGuiCommand (); virtual ~MouseModeGuiCommand (); virtual void init (); public slots: //------------------------------------------------------------------------- virtual void trigger (QString const& action_name); protected: //------------------------------------------------------------------------- virtual void applicationStateChanged (); //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: static QString const NEW_MODE_TEXT_; static QString const POINTER_MODE_TEXT_; static QString const HAND_MODE_TEXT_; static QString const VIEW_OPTIONS_TEXT_; static QString const INFO_MODE_TEXT_; static QStringList const MODE_TEXTS_; static GuiActionFactoryRegistrator registrator_; QMap action_to_mode_map_; }; } #endif // MOUSE_MODE_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/open_file_gui_command.cpp000066400000000000000000000340561345753661000247520ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "open_file_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "gui_impl/dialogs/basic_header_info_dialog.h" #include "gui/signal_visualisation_model.h" #include "file_handling/file_signal_reader_factory.h" #include "file_handling_impl/event_manager_impl.h" #include "file_handling_impl/channel_manager_impl.h" #include "tab_context.h" #include "file_context.h" #include "gui/main_window_model.h" #include "editing_commands/macro_undo_command.h" #include "editing_commands/new_event_undo_command.h" #include "gui/progress_bar.h" #include "gui/color_manager.h" #include "close_file_gui_command.h" #include "file_handling_impl/xdf_reader.h" #include #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- QString const OpenFileGuiCommand::IMPORT_EVENTS_ = "Import Events..."; QString const OpenFileGuiCommand::OPEN_ = "Open..."; QString const OpenFileGuiCommand::SHOW_FILE_INFO_ = "Info..."; QStringList const OpenFileGuiCommand::ACTIONS_ = QStringList() << OpenFileGuiCommand::IMPORT_EVENTS_ << OpenFileGuiCommand::OPEN_ << OpenFileGuiCommand::SHOW_FILE_INFO_; //----------------------------------------------------------------------------- QSharedPointer OpenFileGuiCommand::instance_ = QSharedPointer (new OpenFileGuiCommand); //----------------------------------------------------------------------------- GuiActionFactoryRegistrator OpenFileGuiCommand::registrator_ ("Opening", OpenFileGuiCommand::instance_); //----------------------------------------------------------------------------- OpenFileGuiCommand::OpenFileGuiCommand () : GuiActionCommand (ACTIONS_) { QSettings settings; do_not_show_warning_message = settings.value("DoNotShowWarningMessage", false).toBool(); } //------------------------------------------------------------------------- OpenFileGuiCommand::~OpenFileGuiCommand () { // nothing to do here } //----------------------------------------------------------------------------- void OpenFileGuiCommand::init () { setShortcut (OPEN_, QKeySequence::Open); setShortcut (SHOW_FILE_INFO_, tr("Ctrl+I")); setIcon (OPEN_, QIcon(":/images/ic_folder_open_black_24dp.png")); setIcon (SHOW_FILE_INFO_, QIcon(":/images/ic_info_outline_black_24dp.png")); setIcon (IMPORT_EVENTS_, QIcon(":/images/ic_file_download_black_24dp.png")); resetActionTriggerSlot (OPEN_, SLOT(open())); resetActionTriggerSlot (IMPORT_EVENTS_, SLOT(importEvents())); resetActionTriggerSlot (SHOW_FILE_INFO_, SLOT(showFileInfo())); } //----------------------------------------------------------------------------- void OpenFileGuiCommand::openFile (QString file_path) { if (!instance_->confirmClosingOldFile()) /*!< In case the user decides not to close the old file, return. */ return; //close the previous file before opening a new one //thus using less memory CloseFileGuiCommand closeObject; if (closeObject.closeCurrentFile()) { QSettings settings; settings.setValue("autoScaling", true); instance_->openFileImpl (file_path); } } //------------------------------------------------------------------------- bool OpenFileGuiCommand::confirmClosingOldFile() { QSharedPointer current_file_context = applicationContext()->getCurrentFileContext(); if (!current_file_context.isNull() && current_file_context->getState () == FILE_STATE_CHANGED) { QString file_name = current_file_context->getFileName (); QMessageBox::StandardButton pressed_button = QMessageBox::question (0, tr("Really close?"), tr("Changes in '%1' are not saved!!").arg(file_name) + "\n" + tr("Really close?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (pressed_button == QMessageBox::No) return false; else current_file_context->setState(FILE_STATE_UNCHANGED); } return true; } //------------------------------------------------------------------------- void OpenFileGuiCommand::evaluateEnabledness () { bool file_opened = (getApplicationState() == APP_STATE_FILE_OPEN); bool enable_import_events = file_opened; if (file_opened) { if (applicationContext()->getCurrentFileContext()->getFileName().endsWith("xdf")) enable_import_events = false;//Disabled because currently XDF files doesn't support importing events } getQAction (IMPORT_EVENTS_)->setEnabled (enable_import_events); getQAction (SHOW_FILE_INFO_)->setEnabled (file_opened); } //------------------------------------------------------------------------- void OpenFileGuiCommand::open () { if (!instance_->confirmClosingOldFile()) /*!< In case the user decides not to close the old file, return. */ return; QStringList extension_list = FileSignalReaderFactory::getInstance()->getAllFileEndingsWithWildcards(); QString extensions; foreach (QString extension, extension_list) extensions.append (extension + " "); QSettings settings; QString open_path = settings.value ("file_open_path").toString(); if (!open_path.length()) open_path = QDir::homePath (); QString file_path = showOpenDialog (open_path, extensions); if (file_path.isEmpty()) return; //close the previous file before opening a new one //thus using less memory CloseFileGuiCommand closeObject; if (closeObject.closeCurrentFile()) { QSettings settings; settings.setValue("autoScaling", true); instance_->openFileImpl (file_path); } } //------------------------------------------------------------------------- void OpenFileGuiCommand::importEvents () { QString extensions = "*.csv *.evt"; QSettings settings; QString open_path = settings.value ("file_open_path").toString(); if (!open_path.length()) open_path = QDir::homePath (); QString file_path = showOpenDialog (open_path, extensions); if (file_path.isEmpty()) return; FileSignalReader* file_signal_reader = FileSignalReaderFactory::getInstance()->getHandler (file_path); if (file_signal_reader != 0) { QList > events = file_signal_reader->getEvents (); QSharedPointer event_manager = applicationContext()->getCurrentFileContext()->getEventManager(); QList > creation_commands; foreach (QSharedPointer event, events) { QSharedPointer creation_command (new NewEventUndoCommand (event_manager, event)); creation_commands.append (creation_command); } MacroUndoCommand* macro_command = new MacroUndoCommand (creation_commands); applicationContext()->getCurrentCommandExecuter()->executeCommand (macro_command); delete file_signal_reader; return; } std::fstream file; file.open(file_path.toStdString()); if (file.is_open()) { std::string line; std::getline(file, line); if (line.compare("position,duration,channel,type,name")) { QMessageBox::critical(0, file_path, tr("This is not a valid event CSV file!")); return; } QList > events; QSharedPointer event_manager = applicationContext()->getCurrentFileContext()->getEventManager(); double sampleRate = event_manager->getSampleRate(); std::set types = event_manager->getEventTypes(); int numberChannels = applicationContext()->getCurrentFileContext()->getChannelManager().getNumberChannels(); while (std::getline(file, line)) { QStringList Qline = QString::fromStdString(line).split(','); size_t position = Qline[0].toUInt(); size_t duration = Qline[1].toULongLong(); ChannelID channel = Qline[2].toInt(); EventType type = Qline[3].toInt(); if (type <= 254 && do_not_show_warning_message == false) { QMessageBox msgBox; msgBox.setText("Currently customized event text cannot be properly imported."); msgBox.setIcon(QMessageBox::Warning); msgBox.addButton(QMessageBox::Ok); msgBox.addButton(QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); QCheckBox* dontShowCheckBox = new QCheckBox("Don't show this message again"); msgBox.setCheckBox(dontShowCheckBox); int32_t userReply = msgBox.exec(); if (userReply == QMessageBox::Ok) { if(dontShowCheckBox->checkState() == Qt::Checked) { QSettings settings; settings.setValue("DoNotShowWarningMessage", true); do_not_show_warning_message = true; } } else if (userReply == QMessageBox::Cancel) { if(dontShowCheckBox->checkState() == Qt::Checked) { QSettings settings; settings.setValue("DoNotShowWarningMessage", true); do_not_show_warning_message = true; return; } return; } } //boundary check & error handling if (position > event_manager->getMaxEventPosition() || position + duration > event_manager->getMaxEventPosition() || channel >= numberChannels || !types.count(type)) continue; QSharedPointer event = QSharedPointer(new SignalEvent(position, type, sampleRate, channel, duration)); events << event; } QList > creation_commands; foreach (QSharedPointer event, events) { QSharedPointer creation_command (new NewEventUndoCommand (event_manager, event)); creation_commands.append (creation_command); } MacroUndoCommand* macro_command = new MacroUndoCommand (creation_commands); applicationContext()->getCurrentCommandExecuter()->executeCommand (macro_command); } else { QMessageBox::critical(0, file_path, tr("Cannot open file.\nIs the target file open in another application?")); return; } } //------------------------------------------------------------------------- void OpenFileGuiCommand::showFileInfo () { basic_header_info_dialog = QSharedPointer (new BasicHeaderInfoDialog (applicationContext()->getCurrentFileContext()->getHeader())); basic_header_info_dialog->show(); } //------------------------------------------------------------------------- void OpenFileGuiCommand::openFileImpl (QString file_path, bool instantly) { file_path = QDir::toNativeSeparators (file_path); FileSignalReader* file_signal_reader = FileSignalReaderFactory::getInstance()->getHandler (file_path); if (file_signal_reader == 0) return; QString file_name = file_path.section (QDir::separator(), -1); ChannelManager* channel_manager (new ChannelManagerImpl (file_signal_reader)); std::set shown_channels; if (instantly) shown_channels = channel_manager->getChannels(); else shown_channels = GuiHelper::selectChannels (*channel_manager, applicationContext()->getEventColorManager(), file_signal_reader->getBasicHeader()); if (shown_channels.size() == 0) { delete channel_manager; return; } ProgressBar::instance().initAndShow (channel_manager->getNumberChannels() * 3, tr("Opening ") + file_name, applicationContext()); QSharedPointer event_manager (new EventManagerImpl (*file_signal_reader)); QSharedPointer file_context (new FileContext (file_path, event_manager, channel_manager, file_signal_reader->getBasicHeader())); QSettings settings; settings.setValue("file_open_path", file_path.left (file_path.length() - file_name.length())); QSharedPointer signal_visualisation_model = applicationContext()->getMainWindowModel()->createSignalVisualisationOfFile (file_context); signal_visualisation_model->setShownChannels (shown_channels); signal_visualisation_model->update(); applicationContext()->addFileContext (file_context); ProgressBar::instance().close(); } //----------------------------------------------------------------------------- QString OpenFileGuiCommand::showOpenDialog (QString const& path, QString const& extensions) { QString extension_selection = tr("Signal files (%1)").arg(extensions); QStringList ext_list = extensions.split (" "); for (QStringList::iterator it = ext_list.begin(); it != ext_list.end(); it++) { if (it->size ()) extension_selection += ";; " + *it +" (" + *it + ")"; } extension_selection += ";; *.* (*.*)"; return QFileDialog::getOpenFileName (0, tr("Chose signal file to open"), path, extension_selection); } } sigviewer-0.6.4/src/gui_impl/commands/open_file_gui_command.h000066400000000000000000000046171345753661000244170ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef OPEN_FILE_GUI_COMMAND_H #define OPEN_FILE_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include "file_handling/file_signal_reader.h" #include "gui_impl/dialogs/basic_header_info_dialog.h" namespace sigviewer { //----------------------------------------------------------------------------- /// OpenFileGuiCommand /// /// command for opening a file class OpenFileGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- OpenFileGuiCommand (); //------------------------------------------------------------------------- virtual ~OpenFileGuiCommand (); //------------------------------------------------------------------------- virtual void init (); //------------------------------------------------------------------------- static void openFile (QString file_path); //!In case user has made changes to the old file but hasn't saved it, prompt the user to confirm whether to still close it bool confirmClosingOldFile(); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private slots: //------------------------------------------------------------------------- void open (); //------------------------------------------------------------------------- void importEvents (); //------------------------------------------------------------------------- void showFileInfo (); private: static QString const IMPORT_EVENTS_; static QString const OPEN_; static QString const SHOW_FILE_INFO_; static QStringList const ACTIONS_; static QSharedPointer instance_; static GuiActionFactoryRegistrator registrator_; //------------------------------------------------------------------------- void openFileImpl (QString file_path, bool instantly = true); //------------------------------------------------------------------------- QString showOpenDialog (QString const& path, QString const& extensions); bool do_not_show_warning_message; QSharedPointer basic_header_info_dialog; }; } #endif // OPEN_FILE_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/save_gui_command.cpp000066400000000000000000000345011345753661000237430ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "save_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "file_handling/file_signal_writer_factory.h" #include "open_file_gui_command.h" #include "file_handling_impl/xdf_reader.h" #include "fstream" #include #include #include #include #include #include #include #include namespace sigviewer { QString const SaveGuiCommand::SAVE_AS_ = "Save as..."; QString const SaveGuiCommand::SAVE_ = "Save"; QString const SaveGuiCommand::EXPORT_TO_PNG_ = "Export to PNG..."; QString const SaveGuiCommand::EXPORT_TO_GDF_ = "Export to GDF..."; QString const SaveGuiCommand::EXPORT_EVENTS_CSV_ = "Export Events to CSV..."; QString const SaveGuiCommand::EXPORT_EVENTS_EVT_ = "Export Events to EVT..."; QStringList const SaveGuiCommand::ACTIONS_ = QStringList() << SaveGuiCommand::SAVE_AS_ << SaveGuiCommand::SAVE_ << SaveGuiCommand::EXPORT_TO_GDF_ << SaveGuiCommand::EXPORT_EVENTS_CSV_ << SaveGuiCommand::EXPORT_EVENTS_EVT_ << SaveGuiCommand::EXPORT_TO_PNG_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator SaveGuiCommand::registrator_ ("Saving", QSharedPointer (new SaveGuiCommand)); //----------------------------------------------------------------------------- SaveGuiCommand::SaveGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void SaveGuiCommand::init () { setIcon(SAVE_, QIcon (":/images/ic_save_black_24dp.png")); setIcon(EXPORT_EVENTS_CSV_, QIcon (":/images/ic_file_upload_black_24dp.png")); setIcon(EXPORT_EVENTS_EVT_, QIcon (":/images/ic_file_upload_black_24dp.png")); setShortcut (SAVE_, QKeySequence::Save); setShortcut (SAVE_AS_, QKeySequence::SaveAs); resetActionTriggerSlot (SAVE_AS_, SLOT(saveAs())); resetActionTriggerSlot (SAVE_, SLOT(save())); resetActionTriggerSlot (EXPORT_TO_PNG_, SLOT(exportToPNG())); resetActionTriggerSlot (EXPORT_TO_GDF_, SLOT(exportToGDF())); resetActionTriggerSlot (EXPORT_EVENTS_CSV_, SLOT(exportEventsToCSV())); resetActionTriggerSlot (EXPORT_EVENTS_EVT_, SLOT(exportEventsToEVT())); } //----------------------------------------------------------------------------- void SaveGuiCommand::saveAs () { QSharedPointer file_context = applicationContext()->getCurrentFileContext(); QString old_file_path = file_context->getFilePath (); QString old_file_path_and_name = file_context->getFilePathAndName(); QString file_name = file_context->getFileName(); QString extension = file_name.mid(file_name.lastIndexOf('.')); extension = "*" + extension; QString new_file_path = GuiHelper::getFilePathFromSaveAsDialog (old_file_path, extension, tr("Signal files")); old_file_path_and_name.replace("\\", "/"); //change back slashes into forward slashes... if (new_file_path.size()) { if (QFile::exists (new_file_path)) { //if (QMessageBox::question(0, tr("Overwrite"), tr("Replace ") + new_file_path + tr("?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) //else // return; ///^There is already another dialog asking whether to overwrite: why do we need 2 dialogs? I commented it out for now if (old_file_path_and_name.compare(new_file_path) != 0) //if the old path is NOT the same as the new path { QFile::remove(new_file_path); QFile::copy (old_file_path_and_name, new_file_path); } //otherwise just leave it as is } else QFile::copy (old_file_path_and_name, new_file_path); //add save events to XDF support if (new_file_path.endsWith("xdf", Qt::CaseInsensitive)) { XDFdata->writeEventsToXDF(new_file_path.toStdString()); applicationContext()->getCurrentFileContext()->setState(FILE_STATE_UNCHANGED); } else { FileSignalWriter* writer (FileSignalWriterFactory::getInstance()->getHandler(new_file_path)); bool can_save_events = false; if (writer) can_save_events = writer->supportsSavingEvents (); QSharedPointer event_mgr = file_context->getEventManager(); if (writer && can_save_events) { QString error = writer->saveEventsToSignalFile (event_mgr, event_mgr->getEventTypes()); if (error.size()) QMessageBox::critical(0, new_file_path, error); else { file_context->resetFilePathAndName (new_file_path); file_context->setState(FILE_STATE_UNCHANGED); } } else if (event_mgr->getNumberOfEvents() > 0) QMessageBox::information(0, "", "Events not stored to " + new_file_path + "\n If you want to store events export the file to GDF or export the events into a EVT file!"); delete writer; } } else QMessageBox::critical(0, "Saving.... failed!", "Could not save " + file_name + " to " + new_file_path); } //----------------------------------------------------------------------------- void SaveGuiCommand::save () { QString file_path = applicationContext()->getCurrentFileContext()->getFilePathAndName(); QString file_name = applicationContext()->getCurrentFileContext()->getFileName(); //add save events to XDF support if (file_path.endsWith("xdf", Qt::CaseInsensitive)) { XDFdata->writeEventsToXDF(file_path.toStdString()); applicationContext()->getCurrentFileContext()->setState(FILE_STATE_UNCHANGED); } else //Original Sigviewer code (not XDF) { FileSignalWriter* writer = FileSignalWriterFactory::getInstance()->getHandler (file_path); bool can_save_events = false; if (writer) can_save_events = writer->supportsSavingEvents(); if (writer && can_save_events) { QSharedPointer event_mgr = applicationContext()->getCurrentFileContext()->getEventManager(); QString error = writer->saveEventsToSignalFile(event_mgr, event_mgr->getEventTypes()); if (error.size()) QMessageBox::critical (0, tr("Error"), error); else applicationContext()->getCurrentFileContext()->setState(FILE_STATE_UNCHANGED); } else { QMessageBox::StandardButton pressed_button = QMessageBox::question (0, file_name, tr("Saving of Events is not possible to this file format! Do you want to convert this file into GDF?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (pressed_button == QMessageBox::Yes) exportToGDF (); } delete writer; } } //----------------------------------------------------------------------------- void SaveGuiCommand::exportToPNG () { QString extension = "*.png"; QString file_path = GuiHelper::getFilePathFromSaveAsDialog (applicationContext()->getCurrentFileContext()->getFilePath(), extension, tr("PNG files")); SignalVisualisationView const* view = currentVisModel()->view(); QSharedPointer image = view->renderVisibleScene (); image->save (file_path, "PNG", 100); } //----------------------------------------------------------------------------- void SaveGuiCommand::exportToGDF () { QMessageBox::information (0, "Information", "Attention: Converting to GDF is in testing phase. Meta-data will not be converted."); QString extensions = "*.gdf"; QString current_file_path = applicationContext()->getCurrentFileContext()->getFilePathAndName(); QString current_file_name = applicationContext()->getCurrentFileContext()->getFileName(); current_file_path = current_file_path.left(current_file_path.size() - current_file_name.size()); QString new_file_path = GuiHelper::getFilePathFromSaveAsDialog (current_file_path, extensions, tr("GDF files")); if (new_file_path.size() == 0) return; FileSignalWriter* writer = FileSignalWriterFactory::getInstance()->getHandler (new_file_path); if (writer == 0) { QMessageBox::critical (0, tr("Error"), tr("Export failed!")); return; } QSharedPointer event_mgr = currentVisModel()->getEventManager(); QString error = writer->save (applicationContext()->getCurrentFileContext(), event_mgr->getEventTypes()); if (error.size() == 0) { QMessageBox::StandardButton pressed_button = QMessageBox::question(0, current_file_name, current_file_name + tr(" has been converted into GDF and stored in:\n") + new_file_path + tr("\n\nDo you want to open the GDF file?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (pressed_button == QMessageBox::Yes) OpenFileGuiCommand::openFile (new_file_path); } else QMessageBox::critical (0, current_file_name, tr("Exporting to GDF failed!\n") + error); delete writer; } //------------------------------------------------------------------------- void SaveGuiCommand::exportEventsToEVT () { QSharedPointer event_manager_pt = applicationContext()->getCurrentFileContext()->getEventManager(); std::set types = event_manager_pt->getEventTypes(); QString current_file_path = applicationContext()->getCurrentFileContext()->getFilePathAndName(); QString extension = ".evt"; QString extensions = "*.evt"; QString new_file_path = GuiHelper::getFilePathFromSaveAsDialog (current_file_path.left(current_file_path.lastIndexOf('.')) + extension, extensions, tr("Events files")); if (new_file_path.size() == 0) return; FileSignalWriter* file_signal_writer = FileSignalWriterFactory::getInstance() ->getHandler(new_file_path); qDebug() << new_file_path; file_signal_writer->save (applicationContext()->getCurrentFileContext(), types); delete file_signal_writer; } //------------------------------------------------------------------------- void SaveGuiCommand::exportEventsToCSV () { QString current_file_path = applicationContext()->getCurrentFileContext()->getFilePathAndName(); QString extension = ".csv"; QString extensions = "*.csv"; QString new_file_path = GuiHelper::getFilePathFromSaveAsDialog (current_file_path.left(current_file_path.lastIndexOf('.')) + extension, extensions, tr("CSV files")); if (new_file_path.size() == 0) return; std::ofstream file; file.open(new_file_path.toStdString()); if (file.is_open()) { file << "position,duration,channel,type,name\n"; QSharedPointer event_manager_pt = applicationContext() ->getCurrentFileContext()->getEventManager(); struct row { unsigned long pos; unsigned long dur; int chan; int id; QString name; }; QVector events; for (unsigned int i = 0; i < event_manager_pt->getNumberOfEvents(); i++) { row tmp = { event_manager_pt->getEvent(i)->getPosition(), event_manager_pt->getEvent(i)->getDuration(), event_manager_pt->getEvent(i)->getChannel(), event_manager_pt->getEvent(i)->getType(), event_manager_pt->getNameOfEvent(i) }; events.append(tmp); } std::sort(events.begin(), events.end(), [](const row& a, const row& b) { return a.pos < b.pos; } ); for (int i = 0; i < events.size(); ++i) { file << events[i].pos << "," << events[i].dur << "," << events[i].chan << "," << events[i].id << "," << events[i].name.remove(",").toStdString() << "\n"; } file.close(); } else { QMessageBox::critical (0, current_file_path, tr("Exporting events to CSV failed!\nIs the target file open in another application?")); } } //------------------------------------------------------------------------- void SaveGuiCommand::evaluateEnabledness () { disableIfNoFileIsOpened (QStringList() << EXPORT_TO_PNG_); disableIfNoSignalIsVisualised (QStringList() << EXPORT_TO_PNG_); bool file_open = getApplicationState () == APP_STATE_FILE_OPEN; bool no_gdf_file_open = false; bool file_changed = false; bool has_events = false; if (file_open) { no_gdf_file_open = !(applicationContext()->getCurrentFileContext()->getFileName().endsWith("gdf")); file_changed = (getFileState () == FILE_STATE_CHANGED); has_events = applicationContext()->getCurrentFileContext()->getEventManager()->getNumberOfEvents() > 0; if (applicationContext()->getCurrentFileContext()->getFileName().endsWith("xdf")) no_gdf_file_open = false;//Disabled because currently XDF to GDF conversion doesn't work } getQAction (SAVE_)->setEnabled (file_changed); getQAction (SAVE_AS_)->setEnabled (file_open); getQAction (EXPORT_TO_GDF_)->setEnabled (no_gdf_file_open); getQAction (EXPORT_EVENTS_CSV_)->setEnabled (has_events); getQAction (EXPORT_EVENTS_EVT_)->setEnabled (has_events); } } sigviewer-0.6.4/src/gui_impl/commands/save_gui_command.h000066400000000000000000000036011345753661000234050ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SAVE_GUI_COMMAND_H #define SAVE_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" namespace sigviewer { //----------------------------------------------------------------------------- /// SaveGuiCommand /// /// command for saving a file and converting to other file format class SaveGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- SaveGuiCommand (); //------------------------------------------------------------------------- virtual void init (); public slots: //------------------------------------------------------------------------- void saveAs (); //------------------------------------------------------------------------- void save (); //------------------------------------------------------------------------- void exportToPNG (); //------------------------------------------------------------------------- void exportToGDF (); //------------------------------------------------------------------------- void exportEventsToCSV (); void exportEventsToEVT (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: //------------------------------------------------------------------------- static QString const SAVE_AS_; static QString const SAVE_; static QString const EXPORT_TO_PNG_; static QString const EXPORT_TO_GDF_; static QString const EXPORT_EVENTS_CSV_; static QString const EXPORT_EVENTS_EVT_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // SAVE_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/signal_processing_gui_command.cpp000066400000000000000000000225071345753661000265210ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_processing_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include "gui_impl/processed_signal_channel_manager.h" #include "gui/progress_bar.h" #include "base/fixed_data_block.h" #include namespace sigviewer { //----------------------------------------------------------------------------- QString const SignalProcessingGuiCommand::MEAN_ = "Calculate Mean..."; QString const SignalProcessingGuiCommand::POWER_SPECTRUM_ = "Power Spectrum..."; QStringList const SignalProcessingGuiCommand::ACTIONS_ = QStringList () << SignalProcessingGuiCommand::MEAN_ << SignalProcessingGuiCommand::POWER_SPECTRUM_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator SignalProcessingGuiCommand::registrator_ ("Signal Processing", QSharedPointer(new SignalProcessingGuiCommand)); //----------------------------------------------------------------------------- SignalProcessingGuiCommand::SignalProcessingGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void SignalProcessingGuiCommand::init () { resetActionTriggerSlot (MEAN_, SLOT(calculateMeanAndStandardDeviation())); resetActionTriggerSlot (POWER_SPECTRUM_, SLOT(calculatePowerSpectrum())); } //----------------------------------------------------------------------------- void SignalProcessingGuiCommand::evaluateEnabledness () { disableIfNoFileIsOpened (ACTIONS_); } //----------------------------------------------------------------------------- void SignalProcessingGuiCommand::calculateMeanAndStandardDeviation () { ChannelManager const& channel_manager = currentFileContext()->getChannelManager(); QSharedPointer event_manager = currentFileContext()->getEventManager(); QSharedPointer event_dialog = getFinishedEventTimeSelectionDialog(); if (event_dialog.isNull()) return; unsigned num_samples = channel_manager.getSampleRate() * event_dialog->getLengthInSeconds (); unsigned samples_before = channel_manager.getSampleRate() * event_dialog->getSecondsBeforeEvent (); ProcessedSignalChannelManager* processed_channel_manager (new ProcessedSignalChannelManager(channel_manager.getSampleRate(), num_samples, currentFileContext().data())); processed_channel_manager->setXAxisUnitLabel(channel_manager.getXAxisUnitLabel()); ChannelID new_channel_id = 0; QList events (event_manager->getEvents(event_dialog->getSelectedEventType ())); foreach (ChannelID channel_id, event_dialog->getSelectedChannels ()) { std::list > data; foreach (EventID event_id, events) { QSharedPointer event = event_manager->getEvent (event_id); if (event->getPosition () < samples_before) { QMessageBox::warning (0, "Warning", QString("Event at ").append(QString::number(event->getPositionInSec())).append("s will be ignored! (because no data can be added in front of this event)")); continue; } QSharedPointer data_block = channel_manager.getData (channel_id, event->getPosition() - samples_before, num_samples); if (!data_block.isNull()) data.push_back (data_block); } QSharedPointer mean = FixedDataBlock::calculateMean (data); QSharedPointer standard_deviation = FixedDataBlock::calculateStandardDeviation (data, mean); processed_channel_manager->addExtraChannel (new_channel_id, standard_deviation, tr("Standard Deviation\n") + channel_manager.getChannelLabel(channel_id), channel_manager.getChannelYUnitString(channel_id)); new_channel_id++; processed_channel_manager->addChannel (new_channel_id, mean, channel_manager.getChannelLabel(channel_id), channel_manager.getChannelYUnitString(channel_id)); new_channel_id++; //applicationContext()->getEventColorManager()->setChannelColor(stddev_id, // applicationContext()->getEventColorManager()->getChannelColor(channel_id)); } createVisualisation (tr("Mean"), *processed_channel_manager); } //------------------------------------------------------------------------- void SignalProcessingGuiCommand::calculatePowerSpectrum () { ChannelManager const& channel_manager = currentFileContext()->getChannelManager(); QSharedPointer event_manager = currentFileContext()->getEventManager(); QSharedPointer event_dialog = getFinishedEventTimeSelectionDialog(); if (event_dialog.isNull()) return; unsigned num_samples = channel_manager.getSampleRate() * event_dialog->getLengthInSeconds (); unsigned samples_before = channel_manager.getSampleRate() * event_dialog->getSecondsBeforeEvent (); unsigned fft_samples = 1; while (fft_samples < num_samples) fft_samples *= 2; ProcessedSignalChannelManager* processed_channel_manager (new ProcessedSignalChannelManager(static_cast(fft_samples) / channel_manager.getSampleRate(), fft_samples / 2, currentFileContext().data())); processed_channel_manager->setXAxisUnitLabel ("Hz"); QList events (event_manager->getEvents(event_dialog->getSelectedEventType ())); ProgressBar::instance().initAndShow (event_dialog->getSelectedChannels ().size(), tr("Fourier Transformation"), applicationContext()); foreach (ChannelID channel_id, event_dialog->getSelectedChannels ()) { ProgressBar::instance().increaseValue (1, channel_manager.getChannelLabel(channel_id)); std::list > data; foreach (EventID event_id, events) { QSharedPointer event = event_manager->getEvent (event_id); if (event->getPosition () < samples_before) { QMessageBox::warning (0, "Warning", QString("Event at ").append(QString::number(event->getPositionInSec())).append("s will be ignored! (because no data can be added in front of this event)")); continue; } QSharedPointer data_block = channel_manager.getData (channel_id, event->getPosition() - samples_before, num_samples); if (!data_block.isNull()) data.push_back (FixedDataBlock::createPowerSpectrum(data_block)); } QSharedPointer mean = FixedDataBlock::calculateMean (data); QString unit = QString("log(").append(channel_manager.getChannelYUnitString (channel_id)) .append(QChar(0xb2)) .append("/Hz)"); processed_channel_manager->addChannel (channel_id, mean, channel_manager.getChannelLabel(channel_id), unit); } ProgressBar::instance().close(); createVisualisation (tr("Power Spectrum"), *processed_channel_manager); } //------------------------------------------------------------------------- QSharedPointer SignalProcessingGuiCommand::getFinishedEventTimeSelectionDialog () { QSharedPointer event_dialog ( new EventTimeSelectionDialog (currentFileContext()->getMainVisualisationModel()->getShownEventTypes(), currentFileContext()->getMainVisualisationModel()->getShownChannels(), currentFileContext()->getMainVisualisationModel()->getChannelManager(), currentFileContext()->getMainVisualisationModel()->getEventManager())); if (event_dialog->exec() == QDialog::Accepted) return event_dialog; else return QSharedPointer (0); } //------------------------------------------------------------------------- void SignalProcessingGuiCommand::createVisualisation (QString const& title, ChannelManager const& channel_manager) { QSharedPointer signal_visualisation_model = applicationContext()->getMainWindowModel()->createSignalVisualisation (title, channel_manager); signal_visualisation_model->setShownChannels (channel_manager.getChannels()); signal_visualisation_model->update(); } } sigviewer-0.6.4/src/gui_impl/commands/signal_processing_gui_command.h000066400000000000000000000031701345753661000261610ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_PROCESSING_GUI_COMMAND_H #define SIGNAL_PROCESSING_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" #include "gui_impl/dialogs/event_time_selection_dialog.h" namespace sigviewer { class SignalProcessingGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- SignalProcessingGuiCommand (); //------------------------------------------------------------------------- virtual void init (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private slots: //------------------------------------------------------------------------- void calculateMeanAndStandardDeviation (); //------------------------------------------------------------------------- void calculatePowerSpectrum (); private: //------------------------------------------------------------------------- QSharedPointer getFinishedEventTimeSelectionDialog (); //------------------------------------------------------------------------- void createVisualisation (QString const& title, ChannelManager const& channel_manager); static QString const MEAN_; static QString const POWER_SPECTRUM_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // SIGNAL_PROCESSING_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/undo_redo_gui_command.cpp000066400000000000000000000050761345753661000247700ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "undo_redo_gui_command.h" namespace sigviewer { //----------------------------------------------------------------------------- QString const UndoRedoGuiCommand::UNDO_ = "Undo"; QString const UndoRedoGuiCommand::REDO_ = "Redo"; QStringList const UndoRedoGuiCommand::ACTIONS_ = QStringList () << UndoRedoGuiCommand::UNDO_ << UndoRedoGuiCommand::REDO_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator UndoRedoGuiCommand::registrator_ ("UndoRedo", QSharedPointer (new UndoRedoGuiCommand)); //----------------------------------------------------------------------------- UndoRedoGuiCommand::UndoRedoGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void UndoRedoGuiCommand::init () { setShortcut (UNDO_, QKeySequence::Undo); setShortcut (REDO_, QKeySequence::Redo); setIcon (UNDO_, QIcon (":/images/ic_undo_black_24dp.png")); setIcon (REDO_, QIcon (":/images/ic_redo_black_24dp.png")); resetActionTriggerSlot (UNDO_, SLOT(undo())); resetActionTriggerSlot (REDO_, SLOT(redo())); } //----------------------------------------------------------------------------- void UndoRedoGuiCommand::undo () { applicationContext()->getCurrentCommandExecuter()->undo(); } //----------------------------------------------------------------------------- void UndoRedoGuiCommand::redo () { applicationContext()->getCurrentCommandExecuter()->redo(); } //------------------------------------------------------------------------- void UndoRedoGuiCommand::evaluateEnabledness () { bool can_undo = getTabEditState() != TAB_STATE_NO_UNDO && getTabEditState() != TAB_STATE_NO_REDO_NO_UNDO && getTabEditState() != NO_TAB_EDIT_STATE && getApplicationState() == APP_STATE_FILE_OPEN; bool can_redo = getTabEditState() != TAB_STATE_NO_REDO && getTabEditState() != TAB_STATE_NO_REDO_NO_UNDO && getTabEditState() != NO_TAB_EDIT_STATE && getApplicationState() == APP_STATE_FILE_OPEN; getQAction (UNDO_)->setEnabled (can_undo); getQAction (REDO_)->setEnabled (can_redo); } } sigviewer-0.6.4/src/gui_impl/commands/undo_redo_gui_command.h000066400000000000000000000026371345753661000244350ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef UNDO_REDO_GUI_COMMAND_H #define UNDO_REDO_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" namespace sigviewer { //----------------------------------------------------------------------------- class UndoRedoGuiCommand : public GuiActionCommand { Q_OBJECT public: //------------------------------------------------------------------------- UndoRedoGuiCommand (); //------------------------------------------------------------------------- virtual ~UndoRedoGuiCommand () {} //------------------------------------------------------------------------- virtual void init (); public slots: //------------------------------------------------------------------------- void undo (); //------------------------------------------------------------------------- void redo (); protected: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private: //------------------------------------------------------------------------- static QString const UNDO_; static QString const REDO_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // UNDO_REDO_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/commands/zoom_gui_command.cpp000066400000000000000000000265131345753661000237750ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "zoom_gui_command.h" #include "gui_impl/gui_helper_functions.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- QString const ZoomGuiCommand::GOTO_ = "Go to..."; QString const ZoomGuiCommand::ZOOM_IN_VERTICAL_ = "Zoom In Vertical"; QString const ZoomGuiCommand::ZOOM_OUT_VERTICAL_ = "Zoom Out Vertical"; QString const ZoomGuiCommand::ZOOM_IN_HORIZONTAL_ = "Zoom In Horizontal"; QString const ZoomGuiCommand::ZOOM_OUT_HORIZONTAL_ = "Zoom Out Horizontal"; QString const ZoomGuiCommand::SCALE_X_AXIS_ = "Scale X Axis"; QString const ZoomGuiCommand::CHANNEL_PER_PAGE_ = "Channels per Page..."; QString const ZoomGuiCommand::AUTO_ZOOM_VERTICAL_ = "Auto Zoom Vertical"; QStringList const ZoomGuiCommand::ACTIONS_ = QStringList() << ZoomGuiCommand::ZOOM_IN_VERTICAL_ << ZoomGuiCommand::ZOOM_OUT_VERTICAL_ << ZoomGuiCommand::ZOOM_IN_HORIZONTAL_ << ZoomGuiCommand::ZOOM_OUT_HORIZONTAL_ << ZoomGuiCommand::GOTO_ << ZoomGuiCommand::SCALE_X_AXIS_ << ZoomGuiCommand::CHANNEL_PER_PAGE_; //----------------------------------------------------------------------------- GuiActionFactoryRegistrator ZoomGuiCommand::registrator_ ("Zooming", QSharedPointer (new ZoomGuiCommand)); //----------------------------------------------------------------------------- ZoomGuiCommand::ZoomGuiCommand () : GuiActionCommand (ACTIONS_) { // nothing to do here } //----------------------------------------------------------------------------- void ZoomGuiCommand::init () { getQAction (GOTO_)->setIcon (QIcon(":/images/ic_directions_run_black_24dp.png")); getQAction (ZOOM_IN_VERTICAL_)->setIcon (QIcon(":/images/ic_zoom_in_v_black_24dp.png")); getQAction (ZOOM_OUT_VERTICAL_)->setIcon (QIcon(":/images/ic_zoom_out_v_black_24dp.png")); getQAction (ZOOM_IN_HORIZONTAL_)->setIcon (QIcon(":/images/ic_zoom_in_h_black_24dp.png")); getQAction (ZOOM_OUT_HORIZONTAL_)->setIcon (QIcon(":/images/ic_zoom_out_h_black_24dp.png")); QList zoomInVertical; zoomInVertical << QKeySequence::ZoomIn << Qt::CTRL + Qt::Key_Equal; getQAction(ZOOM_IN_VERTICAL_)->setShortcuts(zoomInVertical); QList zoomInHorizontal; zoomInHorizontal << Qt::ALT + Qt::Key_Plus << Qt::ALT + Qt::Key_Equal; getQAction(ZOOM_IN_HORIZONTAL_)->setShortcuts(zoomInHorizontal); setShortcut (ZOOM_OUT_VERTICAL_, QKeySequence::ZoomOut); setShortcut (ZOOM_OUT_HORIZONTAL_, Qt::ALT + Qt::Key_Minus); resetActionTriggerSlot (GOTO_, SLOT(goTo())); resetActionTriggerSlot (ZOOM_IN_VERTICAL_, SLOT(zoomInVertical())); resetActionTriggerSlot (ZOOM_OUT_VERTICAL_, SLOT(zoomOutVertical())); resetActionTriggerSlot (ZOOM_IN_HORIZONTAL_, SLOT(zoomInHorizontal())); resetActionTriggerSlot (ZOOM_OUT_HORIZONTAL_, SLOT(zoomOutHorizontal())); resetActionTriggerSlot (SCALE_X_AXIS_, SLOT(scaleXAxis())); resetActionTriggerSlot (CHANNEL_PER_PAGE_, SLOT(setChannelsPerPage())); } //------------------------------------------------------------------------- void ZoomGuiCommand::evaluateEnabledness () { if (disableIfNoSignalIsVisualised (ACTIONS_)) return; qDebug () << "blaaahaha"; QSharedPointer vis = currentSignalViewSettings (); QSharedPointer vis_model = currentVisModel(); bool file_open = getApplicationState () == APP_STATE_FILE_OPEN; bool zoom_out_vertical_possible = false; bool zoom_in_vertical_possible = false; bool zoom_out_horizontal_possible = false; bool zoom_in_horizontal_possible = false; if (file_open && !vis.isNull()) { zoom_out_vertical_possible = (vis_model->getSignalViewSettings()->getChannelHeight() * vis_model->getShownChannels().size() > static_cast(vis_model->view()->getViewportHeight())); zoom_in_vertical_possible = (vis_model->getSignalViewSettings()->getChannelHeight() < vis_model->view()->getViewportHeight()); zoom_out_horizontal_possible = vis->getPixelsPerSample() > minPixelPerSample(); zoom_in_horizontal_possible = vis->getPixelsPerSample() < maxPixelPerSample(); } getQAction (ZOOM_OUT_VERTICAL_)->setEnabled (zoom_out_vertical_possible); getQAction (ZOOM_IN_VERTICAL_)->setEnabled (zoom_in_vertical_possible); getQAction (ZOOM_OUT_HORIZONTAL_)->setEnabled (zoom_out_horizontal_possible); getQAction (ZOOM_IN_HORIZONTAL_)->setEnabled (zoom_in_horizontal_possible); disableIfNoFileIsOpened (QStringList() << GOTO_ << SCALE_X_AXIS_ << CHANNEL_PER_PAGE_); } //------------------------------------------------------------------------- void ZoomGuiCommand::goTo () { QSharedPointer vis_model = currentVisModel(); bool ok; double sec = QInputDialog::getDouble (0, tr("Go to..."), tr("Second: "), 0, 0, vis_model->getChannelManager().getDurationInSec(), 1, &ok); if (!ok) return; vis_model->goToSample (sec * vis_model->getChannelManager().getSampleRate ()); } //----------------------------------------------------------------------------- void ZoomGuiCommand::zoomInHorizontal () { float32 pixel_per_sample = currentSignalViewSettings()->getPixelsPerSample(); float32 new_pixel_per_sample = std::min (pixel_per_sample * ZOOM_FACTOR_, maxPixelPerSample() ); GuiHelper::animateProperty (currentSignalViewSettings().data(), "pixelsPerSample", pixel_per_sample, new_pixel_per_sample, this, SLOT(evaluateEnabledness())); } //----------------------------------------------------------------------------- void ZoomGuiCommand::zoomOutHorizontal () { float32 pixel_per_sample = currentSignalViewSettings()->getPixelsPerSample(); float32 new_pixel_per_sample = std::max (pixel_per_sample / ZOOM_FACTOR_, minPixelPerSample ()); GuiHelper::animateProperty (currentSignalViewSettings().data(), "pixelsPerSample", pixel_per_sample, new_pixel_per_sample, this, SLOT(evaluateEnabledness())); } //----------------------------------------------------------------------------- void ZoomGuiCommand::zoomInVertical () { unsigned channel_height = currentVisModel()->getSignalViewSettings()->getChannelHeight(); unsigned channels_per_page = currentVisModel()->view()->getViewportHeight() / channel_height; if (channels_per_page <= 1) return; unsigned new_channel_height = currentVisModel()->view()->getViewportHeight() / (channels_per_page - 1); if (new_channel_height < channel_height + 10) new_channel_height += 10; new_channel_height = std::min (new_channel_height, maxChannelHeight()); GuiHelper::animateProperty (currentVisModel()->getSignalViewSettings().data(), "channelHeight", channel_height, new_channel_height, this, SLOT(evaluateEnabledness())); } //----------------------------------------------------------------------------- void ZoomGuiCommand::zoomOutVertical () { unsigned channel_height = currentSignalViewSettings()->getChannelHeight(); unsigned channels_per_page = currentVisModel()->view()->getViewportHeight() / channel_height; unsigned new_channel_height = currentVisModel()->view()->getViewportHeight() / (channels_per_page + 1); if (new_channel_height == channel_height) new_channel_height -= 25; new_channel_height = std::max (new_channel_height, minChannelHeight()); GuiHelper::animateProperty (currentVisModel()->getSignalViewSettings().data(), "channelHeight", channel_height, new_channel_height, this, SLOT(evaluateEnabledness())); } //----------------------------------------------------------------------------- void ZoomGuiCommand::autoZoomVertical () { } //------------------------------------------------------------------------- void ZoomGuiCommand::scaleXAxis () { float32 sample_rate = currentVisModel()->getChannelManager().getSampleRate(); float32 pixel_per_second = currentSignalViewSettings()->getPixelsPerSample() * sample_rate; float32 width = currentVisModel()->view()->getViewportWidth(); float32 new_secs_per_page = QInputDialog::getDouble (0, tr("Scale X Axis"), tr("Seconds"), width / pixel_per_second, minPixelPerSample() / sample_rate, currentVisModel()->getChannelManager().getDurationInSec()); float32 pixel_per_sample = width / (new_secs_per_page * sample_rate); GuiHelper::animateProperty (currentSignalViewSettings().data(), "pixelsPerSample", currentSignalViewSettings()->getPixelsPerSample(), pixel_per_sample, this, SLOT(evaluateEnabledness())); } //------------------------------------------------------------------------- void ZoomGuiCommand::setChannelsPerPage () { unsigned channel_height = currentVisModel()->getSignalViewSettings()->getChannelHeight(); float viewport_height = currentVisModel()->view()->getViewportHeight(); float channels_per_page = viewport_height / channel_height; bool ok = false; float new_channels_per_page = QInputDialog::getInt (0, tr("Vertical Zooming"), tr("Channels per Page"), channels_per_page, 1, currentVisModel()->getShownChannels().size(), 1, &ok); if (!ok) return; unsigned new_channel_height = viewport_height / new_channels_per_page; if (new_channel_height == channel_height) return; GuiHelper::animateProperty (currentVisModel()->getSignalViewSettings().data(), "channelHeight", channel_height, new_channel_height, this, SLOT(evaluateEnabledness())); } //------------------------------------------------------------------------- unsigned ZoomGuiCommand::maxChannelHeight () { return currentVisModel()->view()->getViewportHeight(); } //------------------------------------------------------------------------- unsigned ZoomGuiCommand::minChannelHeight () { return std::max (20, currentVisModel()->view()->getViewportHeight() / currentVisModel()->getShownChannels().size()); } //------------------------------------------------------------------------- float32 ZoomGuiCommand::maxPixelPerSample () { return static_cast(currentVisModel()->view()->getViewportWidth ()) / 4.0; } //------------------------------------------------------------------------- float32 ZoomGuiCommand::minPixelPerSample () { return static_cast(currentVisModel()->view()->getViewportWidth()) / static_cast(currentVisModel()->getChannelManager().getNumberSamples ()); } } sigviewer-0.6.4/src/gui_impl/commands/zoom_gui_command.h000066400000000000000000000046671345753661000234500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef ZOOM_GUI_COMMAND_H #define ZOOM_GUI_COMMAND_H #include "gui/gui_action_command.h" #include "gui/gui_action_factory_registrator.h" namespace sigviewer { class ZoomGuiCommand : public GuiActionCommand { Q_OBJECT public: ZoomGuiCommand (); virtual void init (); protected slots: //------------------------------------------------------------------------- virtual void evaluateEnabledness (); private slots: //------------------------------------------------------------------------- void goTo (); //------------------------------------------------------------------------- void zoomInHorizontal (); //------------------------------------------------------------------------- void zoomOutHorizontal (); //------------------------------------------------------------------------- void zoomInVertical (); //------------------------------------------------------------------------- void zoomOutVertical (); //------------------------------------------------------------------------- void autoZoomVertical (); //------------------------------------------------------------------------- void scaleXAxis (); //------------------------------------------------------------------------- void setChannelsPerPage (); private: //------------------------------------------------------------------------- unsigned maxChannelHeight (); //------------------------------------------------------------------------- unsigned minChannelHeight (); //------------------------------------------------------------------------- float32 maxPixelPerSample (); //------------------------------------------------------------------------- float32 minPixelPerSample (); static int const ZOOM_FACTOR_ = 2; static int const MAX_HORIZONTAL_ZOOM_IN_ = 32; static QString const GOTO_; static QString const ZOOM_IN_VERTICAL_; static QString const ZOOM_OUT_VERTICAL_; static QString const ZOOM_IN_HORIZONTAL_; static QString const ZOOM_OUT_HORIZONTAL_; static QString const SCALE_X_AXIS_; static QString const CHANNEL_PER_PAGE_; static QString const AUTO_ZOOM_VERTICAL_; static QStringList const ACTIONS_; static GuiActionFactoryRegistrator registrator_; }; } #endif // ZOOM_GUI_COMMAND_H sigviewer-0.6.4/src/gui_impl/dialogs/000077500000000000000000000000001345753661000175555ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/dialogs/about_dialog.ui000066400000000000000000000055411345753661000225520ustar00rootroot00000000000000 aboutDialog true About SigViewer false :/images/sigviewer128.png Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 0 0 <html><head/><body><p><span style=" font-weight:600;">SigViewer</span></p><p>Version VERSION_MAJOR.VERSION_MINOR.VERSION_BUILD</p><p><a href="https://github.com/cbrnr/sigviewer"><span style=" text-decoration: underline; color:#0000ff;">github.com/cbrnr/sigviewer</span></a></p><p>Licensed under the <a href="https://www.gnu.org/licenses/gpl-3.0.en.html"><span style=" text-decoration: underline; color:#0000ff;">GNU GPL</span></a>.</p></body></html> Qt::AutoText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true QDialogButtonBox::Close buttonBox rejected() aboutDialog close() 198 261 198 141 sigviewer-0.6.4/src/gui_impl/dialogs/basic_header_info_dialog.cpp000066400000000000000000000340721345753661000252120ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "basic_header_info_dialog.h" #include "file_handling/basic_header.h" #include "file_handling_impl/xdf_reader.h" #include #include #include #include #include #include #include #include #include namespace sigviewer { // constructor BasicHeaderInfoDialog::BasicHeaderInfoDialog(QSharedPointer header, QWidget* parent) : QDialog(parent), basic_header_(header) { setWindowTitle(tr("Basic Header Info")); QVBoxLayout* top_layout = new QVBoxLayout(this); top_layout->setMargin(10); top_layout->setSpacing(10); info_tree_widget_ = new QTreeWidget(this); top_layout->addWidget(info_tree_widget_); QHBoxLayout* button_layout = new QHBoxLayout; button_layout->setMargin(0); top_layout->addLayout(button_layout); button_layout->addStretch(1); close_button_ = new QPushButton(tr("Close"), this); toggle_button_ = new QPushButton(tr("Collapse All"), this); button_layout->addWidget(toggle_button_); button_layout->addWidget(close_button_); button_layout->addStretch(1); buildTree(); resize(850, 850); top_layout->activate(); readSettings(); connect(close_button_, SIGNAL(clicked()), this, SLOT(closeInfoDialog())); connect(this, SIGNAL(finished(int)), this, SLOT(closeInfoDialog())); connect(toggle_button_, SIGNAL(clicked()), this, SLOT(toggleCollapseExpand())); // connect(info_tree_widget_, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(showStreamName(QTreeWidgetItem*))); // connect(info_tree_widget_, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(hideStreamName(QTreeWidgetItem*))); } void BasicHeaderInfoDialog::toggleCollapseExpand() { if (toggle_button_->text().compare("Collapse All") == 0) { info_tree_widget_->collapseAll(); toggle_button_->setText("Expand All"); } else if (toggle_button_->text().compare("Expand All") == 0) { info_tree_widget_->expandAll(); toggle_button_->setText("Collapse All"); } } void BasicHeaderInfoDialog::showStreamName(QTreeWidgetItem *item) { if (item->text(0).startsWith("Stream", Qt::CaseInsensitive)) { QRegExp rx("(\\d+)"); int pos = rx.indexIn(item->text(0)); QString str; if (pos > -1) { str = rx.cap(1); } int streamNumber = str.toInt() - 1; //-1 to switch back to 0-based indexing // int streamNumber = item->text(0).remove("Stream ").toInt() - 1;//-1 to switch back to 0 index item->setText(1, QString::fromStdString(XDFdata->streams[streamNumber].info.name)); } } void BasicHeaderInfoDialog::hideStreamName(QTreeWidgetItem *item) { if (item->text(0).startsWith("Stream", Qt::CaseInsensitive)) { item->setText(1, ""); } } void BasicHeaderInfoDialog::closeInfoDialog() { QSettings settings; settings.beginGroup("BasicHeaderInfoDialog"); settings.setValue("geometry", saveGeometry()); settings.endGroup(); close(); } void BasicHeaderInfoDialog::readSettings() { QSettings settings; settings.beginGroup("BasicHeaderInfoDialog"); restoreGeometry(settings.value("geometry").toByteArray()); settings.endGroup(); } // build tree void BasicHeaderInfoDialog::buildTree() { info_tree_widget_->setIconSize(QSize(16, 16)); info_tree_widget_->setRootIsDecorated(true); QStringList header_labels; header_labels << tr("Property") << tr("Value"); info_tree_widget_->setHeaderLabels(header_labels); info_tree_widget_->header()->setSectionResizeMode(QHeaderView::Interactive); info_tree_widget_->setColumnWidth(0, width() * 0.65); info_tree_widget_->setAnimated(true); QTreeWidgetItem* root_item; QTreeWidgetItem* tmp_item; // basic root_item = new QTreeWidgetItem(info_tree_widget_); root_item->setText(0, tr("Basic")); // root_item->setIcon(0, QIcon(":/images/ic_info_outline_black_24dp.png")); tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, tr("File Type")); tmp_item->setText(1, basic_header_->getFileTypeString()); QMap recording_info = basic_header_->getRecordingInfo(); foreach (QString key, recording_info.keys()) { tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, key); tmp_item->setText(1, recording_info[key]); } // tmp_item = new QTreeWidgetItem(root_item); // tmp_item->setText(0, tr("Recording Time")); // tmp_item->setText(1, basic_header_->getRecordingTime().toString("dd.MM.yyyy hh:mm:ss")); // tmp_item = new QTreeWidgetItem(root_item); // // tmp_item ->setTextAlignment(1, Qt::AlignRight); // tmp_item->setText(0, tr("Triggered")); // tmp_item->setText(1, basic_header_->isTriggered() ? tr("yes") : tr("no")); // tmp_item = new QTreeWidgetItem(root_item); // // tmp_item ->setTextAlignment(1, Qt::AlignRight); // tmp_item->setText(0, tr("Recording")); // tmp_item->setText(1, QString::number(basic_header_->getRecordDuration() * // basic_header_->getNumberRecords())); // tmp_item->setText(2, tr("seconds")); // file root_item = new QTreeWidgetItem(info_tree_widget_); root_item->setText(0, tr("File")); // root_item->setIcon(0, QIcon(":/images/ic_folder_open_black_24dp.png")); tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, tr("Size")); QFileInfo file_info (basic_header_->getFilePath()); tmp_item->setText(1, QString::number(file_info.size() / 1024).append(tr(" KB"))); tmp_item->setText(0, tr("File Size")); // events root_item = new QTreeWidgetItem(info_tree_widget_); root_item->setText(0, tr("Events")); // root_item->setIcon(0, QIcon(":/images/ic_font_download_black_24dp.png")); tmp_item = new QTreeWidgetItem(root_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Number")); tmp_item->setText(1, QString::number(basic_header_->getNumberEvents()).append(tr(" events"))); tmp_item = new QTreeWidgetItem(root_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Sample Rate")); tmp_item->setText(1, QString::number(basic_header_->getEventSamplerate()).append(tr(" Hz"))); //exclusively for XDF if (basic_header_->getFileTypeString().startsWith("XDF", Qt::CaseInsensitive)) { for (size_t i =0; i < XDFdata->streams.size(); i++) { // basic root_item = new QTreeWidgetItem(info_tree_widget_); // root_item->setText(0, "Stream "+QString::number(i + 1));//+1 for user's convenience (1 based instead 0 based) root_item->setText(0, QString("Stream %1 (%2)").arg(QString::number(i+1)). //+1 for 1-based indexing arg(QString::fromStdString(XDFdata->streams[i].info.name))); // root_item->setIcon(0, QIcon(":/images/ic_flag_black_24dp.png")); QDomDocument streamHeader; streamHeader.setContent(QString::fromStdString(XDFdata->streams[i].streamHeader)); QDomElement rootElement = streamHeader.firstChildElement(); for (QDomNode n = rootElement.firstChild(); !n.isNull();) { tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, n.nodeName()); if (!n.firstChild().isElement()) { tmp_item->setText(1, n.toElement().text()); while (n.nextSibling().isNull() && n.parentNode() != rootElement) { n = n.parentNode(); tmp_item = tmp_item->parent(); root_item = tmp_item->parent(); } n = n.nextSibling(); } else { n = n.firstChild(); root_item = tmp_item; } } QDomDocument streamFooter; streamFooter.setContent(QString::fromStdString(XDFdata->streams[i].streamFooter)); rootElement = streamFooter.firstChildElement(); for (QDomNode n = rootElement.firstChild(); !n.isNull();) { tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, n.nodeName()); if (!n.firstChild().isElement()) { tmp_item->setText(1, n.toElement().text()); while (n.nextSibling().isNull() && n.parentNode() != rootElement) { n = n.parentNode(); tmp_item = tmp_item->parent(); root_item = tmp_item->parent(); } n = n.nextSibling(); } else { n = n.firstChild(); root_item = tmp_item; } } } } //XDF ends here else { // patient root_item = new QTreeWidgetItem(info_tree_widget_); root_item->setText(0, tr("Patient")); // root_item->setIcon(0, QIcon(":/images/patient_16x16.png")); QMap patient_info = basic_header_->getPatientInfo(); foreach (QString key, patient_info.keys()) { tmp_item = new QTreeWidgetItem(root_item); tmp_item->setText(0, key); tmp_item->setText(1, patient_info[key]); } // channels root_item = new QTreeWidgetItem(info_tree_widget_); root_item->setText(0, tr("Channels")); // root_item->setIcon(0, QIcon(":/images/channels_22x22.png")); for (uint32 channel_nr = 0; channel_nr < basic_header_->getNumberChannels(); channel_nr++) { QTreeWidgetItem* channel_item; QSharedPointer channel = basic_header_->getChannel (channel_nr); channel_item = new QTreeWidgetItem(root_item); // QRegExp rx("(^channel\\s*\\d+)"); // rx.setCaseSensitivity(Qt::CaseInsensitive); // if (channel->getLabel().contains(rx)) // channel_item->setText(0, channel->getLabel()); // else channel_item->setText(0, QString("Channel %1 (%2)").arg(channel_nr + 1) // +1 for 1-based indexing .arg(channel->getLabel())); // channel basic tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Label")); tmp_item->setText(1, channel->getLabel()); tmp_item = new QTreeWidgetItem(channel_item); tmp_item->setText(0, tr("Sample Rate")); float64 fs = channel->getSampleRate(); if (fs < 0.0) fs = basic_header_->getSampleRate(); tmp_item->setText(1, QString::number(fs).append(tr(" Hz"))); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Physical Dimension")); tmp_item->setText(1, channel->getPhysicalDim()); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Physical Maximum")); tmp_item->setText(1, QString::number(channel->getPhysicalMaximum())); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Physical Minimum")); tmp_item->setText(1, QString::number(channel->getPhysicalMinimum())); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Digital Maximum")); tmp_item->setText(1, QString::number(channel->getDigitalMaximum())); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Digital Minimum")); tmp_item->setText(1, QString::number(channel->getDigitalMinimum())); tmp_item = new QTreeWidgetItem(channel_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Data Type")); tmp_item->setText(1, channel->typeString()); // filter QTreeWidgetItem* filter_item; filter_item = new QTreeWidgetItem(channel_item); filter_item->setText(0, tr("Filter")); tmp_item = new QTreeWidgetItem(filter_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Highpass")); //tmp_item->setText(1, isnan(channel->getHighpass()) ? tr("unknown") : // (channel->getHighpass() < 0 ? "" : // QString::number(channel->getHighpass()))); tmp_item->setText(2, tr("Hz")); tmp_item = new QTreeWidgetItem(filter_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Lowpass")); // tmp_item->setText(1, channel->getLowpass() ? tr("unknown") : // (channel->getLowpass() < 0 ? "" : // QString::number(channel->getLowpass()))); tmp_item->setText(2, tr("Hz")); tmp_item = new QTreeWidgetItem(filter_item); // tmp_item ->setTextAlignment(1, Qt::AlignRight); tmp_item->setText(0, tr("Notch")); //tmp_item->setText(1, isnan(channel->getNotch()) ? tr("unknown") : (channel->getNotch() ? tr("yes") : tr("no"))); } } info_tree_widget_->expandAll(); } } sigviewer-0.6.4/src/gui_impl/dialogs/basic_header_info_dialog.h000066400000000000000000000023151345753661000246520ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef BASIC_HEADER_INFO_DIALOG_H #define BASIC_HEADER_INFO_DIALOG_H #include "file_handling/basic_header.h" #include #include #include class QPushButton; namespace sigviewer { // basic header info dialog class BasicHeaderInfoDialog : public QDialog { Q_OBJECT public: BasicHeaderInfoDialog(QSharedPointer header, QWidget* parent = 0); public slots: void toggleCollapseExpand(); void showStreamName(QTreeWidgetItem* item); //show Stream name when collapsed void hideStreamName(QTreeWidgetItem* item); //hide Stream name when expanded void closeInfoDialog(); private: // not allowed BasicHeaderInfoDialog(); BasicHeaderInfoDialog(const BasicHeaderInfoDialog&); const BasicHeaderInfoDialog& operator=(const BasicHeaderInfoDialog&); void buildTree(); QSharedPointer basic_header_; QTreeWidget* info_tree_widget_; QPushButton* close_button_; QPushButton* toggle_button_; //toggle expand/collapse all void readSettings(); }; } #endif sigviewer-0.6.4/src/gui_impl/dialogs/channel_dialog.ui000066400000000000000000000104721345753661000230470ustar00rootroot00000000000000 ChannelDialog 0 0 633 744 Channels false true 1 0 Select All false Unselect All false Collapse All false 162 99 Color Settings false false Reset All Colors false Set Default Color false Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok treeWidget select_all_button_ unselect_all_button_ reset_colors_button_ set_default_color_button_ button_box_ accepted() ChannelDialog accept() 248 254 157 274 button_box_ rejected() ChannelDialog reject() 316 260 286 274 sigviewer-0.6.4/src/gui_impl/dialogs/channel_selection_dialog.cpp000066400000000000000000000305311345753661000252570ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "channel_selection_dialog.h" #include "file_handling_impl/xdf_reader.h" #include "application_context_impl.h" #include namespace sigviewer { QColor const ChannelSelectionDialog::NOT_VISIBLE_COLOR_ (Qt::gray); QColor const ChannelSelectionDialog::VISIBLE_COLOR_ (Qt::black); ChannelSelectionDialog::ChannelSelectionDialog(ChannelManager const& channel_manager, QSharedPointer header, QSharedPointer color_manager, QWidget* parent) : QDialog (parent), channel_manager_ (channel_manager), color_manager_ (color_manager), header_ (header) { ui_.setupUi (this); setWindowTitle (tr("Select Channels")); QStringList headerLabels; headerLabels << tr("Channel") << tr("Color"); ui_.treeWidget->setHeaderLabels(headerLabels); ui_.treeWidget->setColumnCount(2); ui_.treeWidget->header()->resizeSection(0, width() * 0.6); ui_.treeWidget->setAnimated(true); if (ApplicationContextImpl::getInstance()->getCurrentFileContext()->getFileName().endsWith("XDF", Qt::CaseInsensitive)) { int channelCount = 0; for (size_t i = 0; i < XDFdata->streams.size(); i++) { QTreeWidgetItem* streamItem = new QTreeWidgetItem(ui_.treeWidget); streamItem->setText(0, tr("Stream ").append (QString::number(i + 1).append(tr(" (")).append //+1 for user's convenience (1 based instead 0 based) (QString::fromStdString(XDFdata->streams[i].info.name)) .append(") "))); #if QT_VERSION >= 0x050600 streamItem->setFlags(Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); #else streamItem->setFlags(Qt::ItemIsTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); #endif streamItem->setExpanded(true); if (XDFdata->streams[i].info.channel_format.compare("string") == 0) { streamItem->setForeground(0, NOT_VISIBLE_COLOR_); //streamItem->setText(0, streamItem->text(0).append(tr(" -text events only"))); } else { QColor streamColor = color_manager_->getChannelColor (channelCount); streamItem->setText(1, streamColor.name()); streamItem->setBackgroundColor(1, streamColor); if (ColorManager::isDark(streamColor)) streamItem->setForeground(1, Qt::white); for (int j = 0; j < XDFdata->streams[i].info.channel_count; j++) { QTreeWidgetItem* channelItem = new QTreeWidgetItem(streamItem); QString channelLabel; if (!XDFdata->streams[i].info.channels.empty()) { for (auto const &entry : XDFdata->streams[i].info.channels[j]) { if ((entry.first.compare("label")==0 || entry.first.compare("type")==0) && entry.second != "") channelLabel += QString::fromStdString(entry.second) + ' '; } } if (channelLabel.isEmpty()) channelItem->setText(0, tr("Channel ").append(QString::number(j + 1)));//+1 for user's convenience (1 based instead 0 based) else channelItem->setText(0, tr("Channel ").append(QString::number(j + 1)).append(" (").append(channelLabel.trimmed()).append(")"));//+1 for user's convenience (1 based instead 0 based) channelItem->setCheckState(0, Qt::Checked); #if QT_VERSION >= 0x050600 channelItem->setFlags(Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); #else channelItem->setFlags(Qt::ItemIsTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); #endif QColor color = color_manager_->getChannelColor (channelCount); channelItem->setText(1, color.name()); channelItem->setBackgroundColor(1, color); if (ColorManager::isDark(color)) channelItem->setForeground(1, Qt::white); channelCount++; } } } ui_.toggle_button->setText(tr("Collapse All")); } else { int row = 0; foreach (ChannelID id, channel_manager_.getChannels()) { QTreeWidgetItem* channelItem = new QTreeWidgetItem (ui_.treeWidget); // QRegExp rx("(^channel\\s*\\d+)"); // rx.setCaseSensitivity(Qt::CaseInsensitive); // if (channel_manager_.getChannelLabel(id).contains(rx)) // channelItem->setText(0, channel_manager_.getChannelLabel(id)); // else channelItem->setText(0, tr("Channel ").append(QString::number(id+1)). //+1 for 1-based index append(" (").append(channel_manager_.getChannelLabel(id)).append(")")); channelItem->setFlags((Qt::ItemIsEnabled | Qt::ItemIsUserCheckable)); QColor color = color_manager_->getChannelColor (id); channelItem->setText(1, color.name()); channelItem->setBackgroundColor(1, color); if (ColorManager::isDark(color)) channelItem->setForeground(1, Qt::white); row++; } ui_.toggle_button->hide(); } ui_.select_all_button_->setDisabled (true); ui_.unselect_all_button_->setDisabled (false); } //----------------------------------------------------------------------------- void ChannelSelectionDialog::resizeEvent(QResizeEvent *event) { ui_.treeWidget->setColumnWidth(0, this->width() * 0.6); QDialog::resizeEvent(event); } //----------------------------------------------------------------------------- bool ChannelSelectionDialog::isSelected (ChannelID channel_id) { QTreeWidgetItemIterator it(ui_.treeWidget); int channelNumber = 0; while (*it) { if ((*it)->text(0).startsWith("Channel ", Qt::CaseInsensitive)) { if (channelNumber++ == channel_id) { return (*it)->checkState(0) == Qt::Checked; break; } } it++; } return false; } //----------------------------------------------------------------------------- void ChannelSelectionDialog::setSelected (ChannelID channel_id, bool selected) { Qt::CheckState state = selected ? Qt::Checked : Qt::Unchecked; QTreeWidgetItemIterator it(ui_.treeWidget); int channelNumber = 0; while (*it) { if ((*it)->text(0).startsWith("Channel ", Qt::CaseInsensitive)) { if (channelNumber++ == channel_id) { (*it)->setCheckState(0, state); break; } } it++; } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_unselect_all_button__clicked () { QTreeWidgetItemIterator it(ui_.treeWidget); while (*it) { if ((*it)->foreground(0) != NOT_VISIBLE_COLOR_)/*!< These are streams with text only */ { (*it)->setCheckState(0, Qt::Unchecked); } ++it; } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_select_all_button__clicked () { QTreeWidgetItemIterator it(ui_.treeWidget); while (*it) { if ((*it)->foreground(0) != NOT_VISIBLE_COLOR_)/*!< These are streams with text only */ { (*it)->setCheckState(0, Qt::Checked); } ++it; } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_reset_colors_button__clicked () { QTreeWidgetItemIterator it(ui_.treeWidget); while (*it) { if ((*it)->foreground(0) != NOT_VISIBLE_COLOR_) { updateColor(*it, color_manager_->getDefaultChannelColor()); } it++; } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_button_box__accepted () { QTreeWidgetItemIterator it(ui_.treeWidget); size_t channelNumber = 0; while (*it) { if ((*it)->text(0).startsWith("Channel")) { if ((*it)->checkState(0) == Qt::Checked) color_manager_->setChannelColor(channelNumber, (*it)->backgroundColor(1)); channelNumber++; } it++; } color_manager_->saveSettings (); } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_set_default_color_button__clicked () { QColor new_default_color = QColorDialog::getColor (color_manager_->getDefaultChannelColor(), this, tr("Default Color"), QColorDialog::ShowAlphaChannel); if (new_default_color.isValid()) color_manager_->setDefaultChannelColor (new_default_color); } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column) { if (column == COLOR_INDEX_) { if (item->text(0).startsWith("Channel", Qt::CaseInsensitive)) { QColorDialog color_dialog (item->backgroundColor (1), this); color_dialog.setOption(QColorDialog::ShowAlphaChannel); if (color_dialog.exec () == QDialog::Accepted) updateColor(item, color_dialog.selectedColor()); } else if (item->text(0).startsWith("Stream", Qt::CaseInsensitive) && item->childCount()) { QColorDialog color_dialog (item->backgroundColor (1), this); color_dialog.setOption(QColorDialog::ShowAlphaChannel); if (color_dialog.exec () == QDialog::Accepted) { updateColor(item, color_dialog.selectedColor()); for (int i = 0; i < item->childCount(); i++) { if (item->child(i)->checkState(0) == Qt::Checked) updateColor(item->child(i), color_dialog.selectedColor()); } } } } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column) { if (column == VISIBLE_INDEX_) { bool select_all_disabled = true; bool unselect_all_disabled = true; QTreeWidgetItemIterator it(ui_.treeWidget); while (*it) { if ((*it)->foreground(0) != NOT_VISIBLE_COLOR_) { if ((*it)->checkState(0) == Qt::Unchecked) { select_all_disabled = false; } else { unselect_all_disabled = false; } } it++; } ui_.select_all_button_->setDisabled (select_all_disabled); ui_.unselect_all_button_->setDisabled (unselect_all_disabled); if (item->isDisabled()) //unnecessary but to get rid of compiler warnings... return; } } //----------------------------------------------------------------------------- void ChannelSelectionDialog::updateColor (QTreeWidgetItem *item, QColor const& color) { item->setBackgroundColor(1, color); item->setText(1, color.name()); if (ColorManager::isDark(color)) item->setForeground(1, Qt::white); else item->setForeground(1, Qt::black); } } void sigviewer::ChannelSelectionDialog::on_toggle_button_clicked() { if (ui_.toggle_button->text().compare("Collapse All") == 0) { ui_.treeWidget->collapseAll(); ui_.toggle_button->setText(tr("Expand All")); } else if (ui_.toggle_button->text().compare("Expand All") == 0) { ui_.treeWidget->expandAll(); ui_.toggle_button->setText(tr("Collapse All")); } } sigviewer-0.6.4/src/gui_impl/dialogs/channel_selection_dialog.h000066400000000000000000000042641345753661000247300ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef CHANNEL_SELECTION_DIALOG_H #define CHANNEL_SELECTION_DIALOG_H #include "base/sigviewer_user_types.h" #include "file_handling/channel_manager.h" #include "file_handling/basic_header.h" #include "gui/color_manager.h" #include "ui_channel_dialog.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- class ChannelSelectionDialog : public QDialog { Q_OBJECT friend class FileOpenTest; public: ChannelSelectionDialog (ChannelManager const& channel_manager, QSharedPointer header, QSharedPointer color_manager, QWidget* parent = 0); bool isSelected (ChannelID channel_id); void setSelected (ChannelID channel_id, bool selected); private slots: void on_unselect_all_button__clicked (); void on_select_all_button__clicked (); void on_reset_colors_button__clicked (); void on_button_box__accepted (); void on_set_default_color_button__clicked (); void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column); void on_treeWidget_itemChanged(QTreeWidgetItem *item, int column); void on_toggle_button_clicked(); private: void updateColor (QTreeWidgetItem *item, QColor const& color); void resizeEvent(QResizeEvent *event); //------------------------------------------------------------------------- /// disabled ChannelSelectionDialog(); ChannelSelectionDialog(const ChannelSelectionDialog&); const ChannelSelectionDialog& operator=(const ChannelSelectionDialog&); ChannelManager const& channel_manager_; QSharedPointer color_manager_; QSharedPointer header_; public: Ui::ChannelDialog ui_; private: static int const VISIBLE_INDEX_ = 0; static int const LABEL_INDEX_ = 0; static int const COLOR_INDEX_ = 1; static int const ID_INDEX_ = 2; static QColor const NOT_VISIBLE_COLOR_; static QColor const VISIBLE_COLOR_; }; } #endif sigviewer-0.6.4/src/gui_impl/dialogs/dialogs.pri000066400000000000000000000013161345753661000217140ustar00rootroot00000000000000HEADERS += \ $$PWD/basic_header_info_dialog.h \ $$PWD/channel_selection_dialog.h \ $$PWD/event_time_selection_dialog.h \ $$PWD/event_types_selection_dialog.h \ $$PWD/scale_channel_dialog.h \ $$PWD/resampling_dialog.h SOURCES += \ $$PWD/basic_header_info_dialog.cpp \ $$PWD/channel_selection_dialog.cpp \ $$PWD/event_time_selection_dialog.cpp \ $$PWD/event_types_selection_dialog.cpp \ $$PWD/scale_channel_dialog.cpp \ $$PWD/resampling_dialog.cpp FORMS += \ $$PWD/about_dialog.ui \ $$PWD/channel_dialog.ui \ $$PWD/event_time_selection_dialog.ui \ $$PWD/event_type_selection_dialog.ui \ $$PWD/scale_channel_dialog.ui \ $$PWD/resampling_dialog.ui sigviewer-0.6.4/src/gui_impl/dialogs/event_time_selection_dialog.cpp000066400000000000000000000136501345753661000260110ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_time_selection_dialog.h" #include "file_handling/event_manager.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- EventTimeSelectionDialog::EventTimeSelectionDialog (std::set const& shown_event_types, std::set const& shown_channels, ChannelManager const& channel_manager, QSharedPointer event_manager) : shown_event_types_ (shown_event_types), shown_channels_ (shown_channels), event_manager_ (event_manager), start_before_value_ (0) { ui_.setupUi (this); foreach (ChannelID channel_id, shown_channels) { QListWidgetItem* item = new QListWidgetItem (channel_manager.getChannelLabel(channel_id), ui_.list_widget_); item->setData (Qt::UserRole, channel_id); } foreach (EventType event_type, shown_event_types_) { if (event_manager_->getEvents (event_type).count ()) ui_.event_combo_box_->addItem (event_manager_->getNameOfEventType(event_type), QVariant(event_type)); } ui_.button_box_->button(QDialogButtonBox::Ok)->setEnabled (false); updateOkEnabled (); } //----------------------------------------------------------------------------- std::set EventTimeSelectionDialog::getSelectedChannels () const { std::set channels; foreach (QListWidgetItem* list_item, ui_.list_widget_->selectedItems()) channels.insert (list_item->data(Qt::UserRole).toInt()); return channels; } //----------------------------------------------------------------------------- EventType EventTimeSelectionDialog::getSelectedEventType () const { return ui_.event_combo_box_->itemData(ui_.event_combo_box_->currentIndex()).toUInt(); } //----------------------------------------------------------------------------- float EventTimeSelectionDialog::getSecondsBeforeEvent () const { return ui_.add_before_spinbox_->value(); } //----------------------------------------------------------------------------- float EventTimeSelectionDialog::getLengthInSeconds () const { return ui_.length_spinbox_->value(); } //----------------------------------------------------------------------------- void EventTimeSelectionDialog::on_unselect_all_button__clicked () { for (int row = 0; row < ui_.list_widget_->count(); ++row) ui_.list_widget_->item (row)->setSelected (false); } //----------------------------------------------------------------------------- void EventTimeSelectionDialog::on_select_all_button__clicked () { for (int row = 0; row < ui_.list_widget_->count(); ++row) ui_.list_widget_->item (row)->setSelected (true); } //----------------------------------------------------------------------------- void EventTimeSelectionDialog::on_event_combo_box__currentIndexChanged (int combo_box_index) { QList event_ids = event_manager_->getEvents (ui_.event_combo_box_->itemData(combo_box_index).toUInt()); float32 shortest_duration = std::numeric_limits::max(); float32 longest_duration = 0; float32 average_duration = 0; for (QList::ConstIterator id_iter = event_ids.begin(); id_iter != event_ids.end(); ++id_iter) { float32 dur = event_manager_->getEvent(*id_iter)->getDurationInSec(); if (dur > longest_duration) longest_duration = dur; if (dur < shortest_duration) shortest_duration = dur; average_duration += dur; } average_duration /= event_ids.size(); ui_.number_of_events_label_->setText (QString::number(event_ids.size())); QString text_for_time_statistic = QString::number(average_duration) + QString("s"); if (average_duration != longest_duration || average_duration != shortest_duration) { text_for_time_statistic += QString (" (max: ") + QString::number(longest_duration) + QString ("s; min: ") + QString::number(shortest_duration)+ QString ("s)"); } //event_type_average_time_label_->setText (text_for_time_statistic); ui_.length_spinbox_->setValue (average_duration + start_before_value_); } //----------------------------------------------------------------------------- void EventTimeSelectionDialog::on_add_before_spinbox__valueChanged (double value) { ui_.length_spinbox_->setValue (ui_.length_spinbox_->value() - start_before_value_ + value); start_before_value_ = value; } //----------------------------------------------------------------------------- void EventTimeSelectionDialog::on_list_widget__itemSelectionChanged () { updateOkEnabled (); } //------------------------------------------------------------------------- void EventTimeSelectionDialog::on_length_spinbox__valueChanged (double) { updateOkEnabled (); } //------------------------------------------------------------------------- void EventTimeSelectionDialog::updateOkEnabled () { int num_selected_items = ui_.list_widget_->selectedItems().count(); bool nothing_selected = (num_selected_items == 0); bool all_selected = (num_selected_items == ui_.list_widget_->count()); bool length_is_zero = (ui_.length_spinbox_->value() == 0); bool no_event_selected = (ui_.event_combo_box_->currentIndex() == -1); ui_.button_box_->button(QDialogButtonBox::Ok)->setDisabled (nothing_selected || length_is_zero || no_event_selected); ui_.unselect_all_button_->setDisabled (nothing_selected); ui_.select_all_button_->setDisabled (all_selected); } } sigviewer-0.6.4/src/gui_impl/dialogs/event_time_selection_dialog.h000066400000000000000000000050771345753661000254620ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TIME_SELECTION_DIALOG_H #define EVENT_TIME_SELECTION_DIALOG_H #include "base/sigviewer_user_types.h" #include "file_handling/event_manager.h" #include "file_handling/channel_manager.h" #include "ui_event_time_selection_dialog.h" #include #include #include #include namespace sigviewer { class EventTimeSelectionDialog : public QDialog { Q_OBJECT public: //------------------------------------------------------------------------- EventTimeSelectionDialog (std::set const& shown_event_types, std::set const& shown_channels, ChannelManager const& channel_manager, QSharedPointer event_manager); //------------------------------------------------------------------------- std::set getSelectedChannels () const; //------------------------------------------------------------------------- EventType getSelectedEventType () const; //------------------------------------------------------------------------- float getSecondsBeforeEvent () const; //------------------------------------------------------------------------- float getLengthInSeconds () const; private slots: //------------------------------------------------------------------------- void on_unselect_all_button__clicked (); //------------------------------------------------------------------------- void on_select_all_button__clicked (); //------------------------------------------------------------------------- void on_event_combo_box__currentIndexChanged (int combo_box_index); //------------------------------------------------------------------------- void on_add_before_spinbox__valueChanged (double value); //------------------------------------------------------------------------- void on_list_widget__itemSelectionChanged (); //------------------------------------------------------------------------- void on_length_spinbox__valueChanged (double value); private: //------------------------------------------------------------------------- void updateOkEnabled (); std::set shown_event_types_; std::set shown_channels_; QSharedPointer event_manager_; double start_before_value_; Ui::EventTimeSelectionDialog ui_; }; } #endif sigviewer-0.6.4/src/gui_impl/dialogs/event_time_selection_dialog.ui000066400000000000000000000066321345753661000256460ustar00rootroot00000000000000 EventTimeSelectionDialog 0 0 434 512 Event Time Channel QAbstractItemView::MultiSelection Select All Unselect All Number of Events Length s Start before s Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok button_box_ accepted() EventTimeSelectionDialog accept() 248 254 157 274 button_box_ rejected() EventTimeSelectionDialog reject() 316 260 286 274 sigviewer-0.6.4/src/gui_impl/dialogs/event_type_selection_dialog.ui000066400000000000000000000117331345753661000256670ustar00rootroot00000000000000 EventTypeSelectionDialog 0 0 633 744 Dialog 10 true 4 75 0 1 2 3 4 Select All false Unselect All false Collapse All false View All Events Existing Events true true Color Settings false false Reset All Colors false Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox rejected() EventTypeSelectionDialog reject() 316 260 286 274 buttonBox accepted() EventTypeSelectionDialog accept() 248 254 157 274 sigviewer-0.6.4/src/gui_impl/dialogs/event_types_selection_dialog.cpp000066400000000000000000000332211345753661000262130ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_types_selection_dialog.h" #include #include #define max(a,b) ((a) > (b) ? (a) : (b)) namespace sigviewer { //----------------------------------------------------------------------------- EventTypesSelectionDialog::EventTypesSelectionDialog (QString const& caption, QSharedPointer event_manager, std::set const& preselected_types, QSharedPointer color_manager, QWidget* parent) : QDialog(parent), event_manager_ (event_manager), selected_types_ (preselected_types), color_manager_ (color_manager) { ui_.setupUi (this); setWindowTitle (caption); buildTree (true); color_manager_->loadSettings(); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::buildTree (bool only_existing_events) { QStringList header_labels; header_labels << tr("Event Type") << tr("Color") << tr("Alpha") << tr("Type Id"); ui_.tree_widget_->setHeaderLabels (header_labels); ui_.tree_widget_->setColumnWidth(ID_COLUMN_INDEX_, 0); ui_.tree_widget_->header()->setSectionResizeMode (QHeaderView::Interactive); ui_.tree_widget_->header()->resizeSection (NAME_COLUMN_INDEX_, width() * 0.6); ui_.tree_widget_->header()->resizeSection (COLOR_COLUMN_INDEX_, width() * 0.18); ui_.tree_widget_->header()->resizeSection (ID_COLUMN_INDEX_, 0); ui_.tree_widget_->setColumnHidden (ID_COLUMN_INDEX_, true); std::set existing_types; foreach (EventID event_id, event_manager_->getAllEvents ()) existing_types.insert (event_manager_->getEvent (event_id)->getType ()); if (event_manager_->getFileType().startsWith("xdf", Qt::CaseInsensitive)) { foreach (EventType event_type, event_manager_->getEventTypes ()) { if (only_existing_events && !existing_types.count(event_type)) continue; QString event_name = event_manager_->getNameOfEventType (event_type); QTreeWidgetItem* event_item = new QTreeWidgetItem (ui_.tree_widget_); event_item->setFlags (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); QColor color = color_manager_->getEventColor(event_type); if (selected_types_.count(event_type)) event_item->setCheckState (CHECKBOX_COLUMN_INDEX_, Qt::Checked); else event_item->setCheckState (CHECKBOX_COLUMN_INDEX_, Qt::Unchecked); event_item->setText (NAME_COLUMN_INDEX_, event_name); color.setAlpha (255); event_item->setBackgroundColor (COLOR_COLUMN_INDEX_, color); event_item->setTextColor (COLOR_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); event_item->setText (COLOR_COLUMN_INDEX_, color.name()); color = color_manager_->getEventColor(event_type); //reselect the same color but less Alpha value event_item->setBackgroundColor (ALPHA_COLUMN_INDEX_, color); event_item->setTextColor(ALPHA_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); event_item->setText(ALPHA_COLUMN_INDEX_, QString("%1").arg(color.alpha())); event_item->setText (ID_COLUMN_INDEX_, QString::number(event_type)); } } else { QMap group_id2list_item; foreach (QString group_id, event_manager_->getEventTypeGroupIDs()) { QString group_name = group_id; // TODO: event_table_file_reader.getEventGroupName(*group_it); bool show_group = !only_existing_events; foreach (EventType group_type, event_manager_->getEventTypes (group_id)) if (existing_types.count(group_type) && only_existing_events) show_group = true; if (show_group) { QTreeWidgetItem * group_item = new QTreeWidgetItem(ui_.tree_widget_); group_item->setFlags (Qt::ItemIsUserCheckable | Qt::ItemIsTristate | Qt::ItemIsEnabled); group_item->setText (NAME_COLUMN_INDEX_, group_name); group_item->setExpanded (true); group_id2list_item[group_id] = group_item; foreach (EventType event_type, event_manager_->getEventTypes (group_id)) { if (only_existing_events && !existing_types.count(event_type)) continue; QString event_name = event_manager_->getNameOfEventType (event_type); QTreeWidgetItem* event_item = new QTreeWidgetItem (group_item); event_item->setFlags (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); QColor color = color_manager_->getEventColor(event_type); if (selected_types_.count(event_type)) event_item->setCheckState (CHECKBOX_COLUMN_INDEX_, Qt::Checked); else event_item->setCheckState (CHECKBOX_COLUMN_INDEX_, Qt::Unchecked); event_item->setText (NAME_COLUMN_INDEX_, event_name); color.setAlpha (255); event_item->setBackgroundColor (COLOR_COLUMN_INDEX_, color); event_item->setTextColor (COLOR_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); event_item->setText (COLOR_COLUMN_INDEX_, color.name()); color = color_manager_->getEventColor(event_type); //reselect the same color but less Alpha value event_item->setBackgroundColor (ALPHA_COLUMN_INDEX_, color); event_item->setTextColor(ALPHA_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); event_item->setText(ALPHA_COLUMN_INDEX_, QString("%1").arg(color.alpha())); event_item->setText (ID_COLUMN_INDEX_, QString::number(event_type)); } } } } ui_.tree_widget_->setAnimated(true); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_tree_widget__itemClicked(QTreeWidgetItem* item, int column) { switch (column) { case COLOR_COLUMN_INDEX_: handleColor (item); break; case ALPHA_COLUMN_INDEX_: handleAlpha (item); break; } } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::storeColors() { if (event_manager_->getFileType().startsWith("xdf", Qt::CaseInsensitive)) { // in XDF files we don't display libbiosig event groups, so top level items are events for (int nr = 0; nr < ui_.tree_widget_->topLevelItemCount(); nr++) { QTreeWidgetItem* event_item = ui_.tree_widget_->topLevelItem(nr); EventType type = event_item->text(ID_COLUMN_INDEX_).toUInt(); color_manager_->setEventColor (type, event_item->backgroundColor(ALPHA_COLUMN_INDEX_)); } } else { // in non-XDF files, top level items are libbiosig event groups for (int group_nr = 0; group_nr < ui_.tree_widget_->topLevelItemCount(); group_nr++) { QTreeWidgetItem* group_item = ui_.tree_widget_->topLevelItem (group_nr); for (int nr = 0; nr < group_item->childCount(); nr++) { QTreeWidgetItem* event_item = group_item->child(nr); EventType type = event_item->text(ID_COLUMN_INDEX_).toUInt(); color_manager_->setEventColor (type, event_item->backgroundColor(ALPHA_COLUMN_INDEX_)); } } } color_manager_->saveSettings(); } //----------------------------------------------------------------------------- std::set EventTypesSelectionDialog::getSelectedTypes () const { return selected_types_; } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_tree_widget__itemChanged (QTreeWidgetItem* item, int column) { if (item->childCount()) return; if (column == CHECKBOX_COLUMN_INDEX_) handleSelected (item); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_all_events_button__toggled (bool checked) { if (!checked) return; ui_.tree_widget_->clear(); buildTree (); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_existing_events_button__toggled (bool checked) { if (!checked) return; ui_.tree_widget_->clear(); buildTree (true); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_select_all_button__clicked () { for (int index = 0; index < ui_.tree_widget_->topLevelItemCount(); index++) ui_.tree_widget_->topLevelItem(index)->setCheckState(CHECKBOX_COLUMN_INDEX_, Qt::Checked); selected_types_ = event_manager_->getEventTypes (); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_unselect_all_button__clicked () { for (int index = 0; index < ui_.tree_widget_->topLevelItemCount(); index++) ui_.tree_widget_->topLevelItem(index)->setCheckState(CHECKBOX_COLUMN_INDEX_, Qt::Unchecked); selected_types_.clear (); } //----------------------------------------------------------------------------- void EventTypesSelectionDialog::on_reset_colors_button__clicked () { QTreeWidgetItemIterator color_iterator (ui_.tree_widget_, QTreeWidgetItemIterator::NoChildren); while (*color_iterator) { QColor color = color_manager_->getDefaultEventColor((*color_iterator)->text (ID_COLUMN_INDEX_).toUInt ()); color.setAlpha (255); (*color_iterator)->setBackgroundColor (COLOR_COLUMN_INDEX_, color); (*color_iterator)->setTextColor (COLOR_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); (*color_iterator)->setText (COLOR_COLUMN_INDEX_, color.name()); ++color_iterator; } QTreeWidgetItemIterator alpha_iterator (ui_.tree_widget_, QTreeWidgetItemIterator::NoChildren); while (*alpha_iterator) { QColor color = color_manager_->getDefaultEventColor((*alpha_iterator)->text (ID_COLUMN_INDEX_).toUInt ()); (*alpha_iterator)->setBackgroundColor (ALPHA_COLUMN_INDEX_, color); (*alpha_iterator)->setTextColor(ALPHA_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); (*alpha_iterator)->setText(ALPHA_COLUMN_INDEX_, QString("%1").arg(color.alpha())); ++alpha_iterator; } } //------------------------------------------------------------------------- void EventTypesSelectionDialog::handleSelected (QTreeWidgetItem* item) { if (item->checkState (CHECKBOX_COLUMN_INDEX_) == Qt::Checked) selected_types_.insert (item->text (ID_COLUMN_INDEX_).toUInt()); else selected_types_.erase (item->text (ID_COLUMN_INDEX_).toUInt()); } //------------------------------------------------------------------------- void EventTypesSelectionDialog::handleColor (QTreeWidgetItem* item) { if (item->text(ID_COLUMN_INDEX_).size() == 0) return; QColor color = item->backgroundColor (COLOR_COLUMN_INDEX_); color = QColorDialog::getColor (color, this, tr("Event Color"), QColorDialog::ShowAlphaChannel); if (!color.isValid()) return; item->setBackgroundColor (COLOR_COLUMN_INDEX_, color); item->setTextColor (COLOR_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); item->setText (COLOR_COLUMN_INDEX_, QString("%1").arg(color.name())); color.setAlpha (item->text(ALPHA_COLUMN_INDEX_).toInt()); item->setBackgroundColor (ALPHA_COLUMN_INDEX_, color); item->setTextColor (ALPHA_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); item->setText (ALPHA_COLUMN_INDEX_, QString::number (color.alpha())); } //------------------------------------------------------------------------- void EventTypesSelectionDialog::handleAlpha (QTreeWidgetItem* item) { if (item->text(ID_COLUMN_INDEX_).size() == 0) return; QColor color = item->backgroundColor (ALPHA_COLUMN_INDEX_); color.setAlpha (QInputDialog::getInt(this, tr("Alpha"), tr("Enter new Value"), color.alpha(), 0, 255, 25)); item->setBackgroundColor (ALPHA_COLUMN_INDEX_, color); item->setTextColor (ALPHA_COLUMN_INDEX_, ColorManager::isDark(color) ? Qt::white : Qt::black); item->setText (ALPHA_COLUMN_INDEX_, QString::number (color.alpha())); } } void sigviewer::EventTypesSelectionDialog::on_toggle_collapse_expand_button_clicked() { if (ui_.toggle_collapse_expand_button->text().compare("Collapse All") == 0) { ui_.tree_widget_->collapseAll(); ui_.toggle_collapse_expand_button->setText("Expand All"); } else if (ui_.toggle_collapse_expand_button->text().compare("Expand All") == 0) { ui_.tree_widget_->expandAll(); ui_.toggle_collapse_expand_button->setText("Collapse All"); } } sigviewer-0.6.4/src/gui_impl/dialogs/event_types_selection_dialog.h000066400000000000000000000053761345753661000256720ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TYPES_SELECTION_DIALOG_H #define EVENT_TYPES_SELECTION_DIALOG_H #include "file_handling/event_manager.h" #include "gui/color_manager.h" #include "ui_event_type_selection_dialog.h" class QTreeWidget; class QPushButton; class QTreeWidgetItem; namespace sigviewer { //----------------------------------------------------------------------------- /// EventTypesSelectionDialog class EventTypesSelectionDialog : public QDialog { Q_OBJECT public: //------------------------------------------------------------------------- EventTypesSelectionDialog (QString const& caption, QSharedPointer event_manager, std::set const& preselected_types, QSharedPointer color_manager, QWidget* parent = 0); void storeColors(); std::set getSelectedTypes () const; private slots: void on_tree_widget__itemClicked (QTreeWidgetItem* item, int column); void on_tree_widget__itemChanged (QTreeWidgetItem* item ,int column); void on_all_events_button__toggled (bool checked); void on_existing_events_button__toggled (bool checked); void on_select_all_button__clicked (); void on_unselect_all_button__clicked (); void on_reset_colors_button__clicked (); void on_toggle_collapse_expand_button_clicked(); private: //------------------------------------------------------------------------- // not allowed EventTypesSelectionDialog(); EventTypesSelectionDialog(const EventTypesSelectionDialog&); const EventTypesSelectionDialog& operator=(const EventTypesSelectionDialog&); //------------------------------------------------------------------------- void buildTree (bool only_existing_events = false); //------------------------------------------------------------------------- void handleSelected (QTreeWidgetItem* item); //------------------------------------------------------------------------- void handleColor (QTreeWidgetItem* item); //------------------------------------------------------------------------- void handleAlpha (QTreeWidgetItem* item); static int const CHECKBOX_COLUMN_INDEX_ = 0; static int const NAME_COLUMN_INDEX_ = 0; static int const COLOR_COLUMN_INDEX_ = 1; static int const ALPHA_COLUMN_INDEX_ = 2; static int const ID_COLUMN_INDEX_ = 3; QSharedPointer event_manager_; std::set selected_types_; QSharedPointer color_manager_; Ui::EventTypeSelectionDialog ui_; }; } #endif sigviewer-0.6.4/src/gui_impl/dialogs/resampling_dialog.cpp000066400000000000000000000070371345753661000237500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "resampling_dialog.h" #include "ui_resampling_dialog.h" #include "file_handling_impl/xdf_reader.h" namespace sigviewer { ResamplingDialog::ResamplingDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ResamplingDialog) { ui->setupUi(this); } ResamplingDialog::ResamplingDialog(int nativeSrate, int highestSampleRate, QWidget *parent) : QDialog(parent), ui(new Ui::ResamplingDialog) { ui->setupUi(this); this->setWindowTitle("Resampling"); if (XDFdata->sampleRateMap.size() > 1) { QString text = "This file contains signals of multiple sample rates.
" "Sigviewer needs to resample all channels to a unified sample rate in order to display them.
" "Please choose a sample rate below (This won't change the actual file content):"; ui->label->setText(text); } else if (XDFdata->sampleRateMap.size() == 1 && XDFdata->sampleRateMap.count(0)) { ui->label->setText("The nominal sample rate of this file is 0.\n" "Please choose a preferred sample rate:"); } else { QString text = "Would you like to resample this file? (This won't change the actual file content) "; ui->label->setText(text); } ui->treeWidget->setColumnCount(2); ui->treeWidget->setColumnWidth(0, this->width()/2.15); ui->treeWidget->setAnimated(true); QStringList headers; headers << "Stream" << "Info"; ui->treeWidget->setHeaderLabels(headers); for (size_t i = 0; i < XDFdata->streams.size(); i++) { QTreeWidgetItem* streamItem = new QTreeWidgetItem(ui->treeWidget); streamItem->setText(0, "Stream "+QString::number(i+1));//+1 for user's convenience (1 based instead 0 based) // streamItem->setIcon(0, QIcon(":/images/ic_flag_black_24dp.png")); QTreeWidgetItem* infoItem = new QTreeWidgetItem(streamItem); infoItem->setText(0, tr("Name")); infoItem->setText(1, QString::fromStdString(XDFdata->streams[i].info.name)); infoItem = new QTreeWidgetItem(streamItem); infoItem->setText(0, tr("Type")); infoItem->setText(1, QString::fromStdString(XDFdata->streams[i].info.type)); infoItem = new QTreeWidgetItem(streamItem); infoItem->setText(0, tr("Sample Rate")); infoItem->setText(1, QString::number(XDFdata->streams[i].info.nominal_srate).append(tr(" Hz"))); if (XDFdata->streams[i].info.nominal_srate == 0) infoItem->setText(1, tr("Irregular")); infoItem = new QTreeWidgetItem(streamItem); infoItem->setText(0, tr("Channel Count")); infoItem->setText(1, QString::number(XDFdata->streams[i].info.channel_count)); infoItem = new QTreeWidgetItem(streamItem); infoItem->setText(0, tr("Channel Format")); infoItem->setText(1, QString::fromStdString(XDFdata->streams[i].info.channel_format)); } ui->spinBox->setMinimum(1); ui->spinBox->setValue(nativeSrate); if (highestSampleRate > 0) ui->spinBox->setMaximum(highestSampleRate); else ui->spinBox->setMaximum(2048); ui->treeWidget->expandAll(); } ResamplingDialog::~ResamplingDialog() { delete ui; } void ResamplingDialog::on_resample_button_clicked() { userSrate = ui->spinBox->value(); done(QDialog::Accepted); } void ResamplingDialog::on_cancel_button_clicked() { done(QDialog::Rejected); } } sigviewer-0.6.4/src/gui_impl/dialogs/resampling_dialog.h000066400000000000000000000013561345753661000234130ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef RESAMPLING_DIALOG_H #define RESAMPLING_DIALOG_H #include namespace Ui { class ResamplingDialog; } namespace sigviewer { class ResamplingDialog : public QDialog { Q_OBJECT public: explicit ResamplingDialog(QWidget *parent = 0); ResamplingDialog(int nativeSrate, int highestSampleRate, QWidget *parent = 0); ~ResamplingDialog(); int getUserSrate() {return userSrate;} private slots: void on_resample_button_clicked(); void on_cancel_button_clicked(); private: Ui::ResamplingDialog *ui; int userSrate = 0; }; } #endif // RESAMPLING_DIALOG_H sigviewer-0.6.4/src/gui_impl/dialogs/resampling_dialog.ui000066400000000000000000000056751345753661000236110ustar00rootroot00000000000000 ResamplingDialog 0 0 699 671 Dialog TextLabel 1 0 0 1 100000 Hz Qt::Horizontal 428 20 0 0 Resample 0 0 Cancel sigviewer-0.6.4/src/gui_impl/dialogs/scale_channel_dialog.cpp000066400000000000000000000120221345753661000243540ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "scale_channel_dialog.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- ScaleChannelDialog::ScaleChannelDialog (ChannelID preselected_channel, std::set const& shown_channels, ChannelManager const& channel_manager, QWidget *parent) : QDialog(parent), selected_channel_ (preselected_channel), shown_channels_ (shown_channels), channel_manager_ (channel_manager) { ui_.setupUi (this); if (selected_channel_ == UNDEFINED_CHANNEL) setWindowTitle (tr("Scale All Channels")); else setWindowTitle (tr("Scale Channel ").append(channel_manager_.getChannelLabel(preselected_channel))); ui_.upper_spinbox_->setMaximum (std::numeric_limits::max()); ui_.upper_spinbox_->setMinimum (-std::numeric_limits::max()); ui_.lower_spinbox_->setMaximum (std::numeric_limits::max()); ui_.lower_spinbox_->setMinimum (-std::numeric_limits::max()); QString unit_string = channel_manager_.getChannelYUnitString (selected_channel_); if (unit_string.size()) ui_.unitLabelLower->setText (QString ("(").append (unit_string).append (")")); ui_.unitLabelUpper->setText (ui_.unitLabelLower->text()); if (selected_channel_ != UNDEFINED_CHANNEL) { ui_.upper_spinbox_->setValue (channel_manager_.getMaxValue (selected_channel_)); ui_.lower_spinbox_->setValue (channel_manager_.getMinValue (selected_channel_)); } connect (this, SIGNAL(accepted()), SLOT(storeAccepted())); ui_.unitLabelLower->hide(); ui_.unitLabelUpper->hide(); QSettings settings; if (settings.value("autoScaling", true).toBool()) ui_.autoButton->setChecked(true); else ui_.manualButton->setChecked(true); last_max_ = settings.value("scaling_upper_value", 75).toDouble(); last_min_ = settings.value("scaling_lower_value", -75).toDouble(); ui_.upper_spinbox_->setValue(last_max_); ui_.lower_spinbox_->setValue(last_min_); ui_.upper_spinbox_->setMinimum(ui_.lower_spinbox_->value()); ui_.lower_spinbox_->setMaximum(ui_.upper_spinbox_->value()); } //----------------------------------------------------------------------------- bool ScaleChannelDialog::autoScaling () const { return ui_.autoButton->isChecked (); } //----------------------------------------------------------------------------- bool ScaleChannelDialog::physAutoScaling () const { return false;//ui_.physButton->isChecked(); } //----------------------------------------------------------------------------- float ScaleChannelDialog::upperValue () const { return ui_.upper_spinbox_->value(); } //----------------------------------------------------------------------------- float ScaleChannelDialog::lowerValue () const { return ui_.lower_spinbox_->value(); } //----------------------------------------------------------------------------- void ScaleChannelDialog::on_manualButton_toggled (bool checked) { ui_.upper_spinbox_->setEnabled(checked); ui_.lower_spinbox_->setEnabled(checked); if (!checked) return; ui_.upper_spinbox_->setValue (last_max_); ui_.lower_spinbox_->setValue (last_min_); QSettings settings; settings.setValue("autoScaling", false); } //----------------------------------------------------------------------------- void ScaleChannelDialog::on_autoButton_toggled (bool checked) { if (!checked) return; double upper_value = 0; double lower_value = 0; if (selected_channel_ != UNDEFINED_CHANNEL) { upper_value = channel_manager_.getMaxValue (selected_channel_); lower_value = channel_manager_.getMinValue (selected_channel_); } else { upper_value = last_max_; lower_value = last_min_; } ui_.upper_spinbox_->setValue (upper_value); ui_.lower_spinbox_->setValue (lower_value); QSettings settings; settings.setValue("autoScaling", true); } //----------------------------------------------------------------------------- void ScaleChannelDialog::storeAccepted () { if (ui_.manualButton->isChecked()) { last_max_ = ui_.upper_spinbox_->value(); last_min_ = ui_.lower_spinbox_->value(); QSettings settings; settings.setValue("scaling_upper_value", last_max_); settings.setValue("scaling_lower_value", last_min_); } } //----------------------------------------------------------------------------- void ScaleChannelDialog::on_upper_spinbox__valueChanged(double arg1) { ui_.lower_spinbox_->setMaximum(arg1); } //----------------------------------------------------------------------------- void ScaleChannelDialog::on_lower_spinbox__valueChanged(double arg1) { ui_.upper_spinbox_->setMinimum(arg1); } } sigviewer-0.6.4/src/gui_impl/dialogs/scale_channel_dialog.h000066400000000000000000000024401345753661000240240ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SCALEC_HANNEL_DIALOG_H #define SCALEC_HANNEL_DIALOG_H #include "base/sigviewer_user_types.h" #include "file_handling/channel_manager.h" #include "ui_scale_channel_dialog.h" #include namespace sigviewer { class ScaleChannelDialog : public QDialog { Q_OBJECT public: explicit ScaleChannelDialog (ChannelID preselected_channel, std::set const& shown_channels, ChannelManager const& channel_manager, QWidget *parent = 0); bool autoScaling () const; bool physAutoScaling () const; float upperValue () const; float lowerValue () const; signals: private slots: void on_manualButton_toggled (bool checked); void on_autoButton_toggled (bool checked); void storeAccepted (); void on_upper_spinbox__valueChanged(double arg1); void on_lower_spinbox__valueChanged(double arg1); private: ChannelID selected_channel_; std::set const shown_channels_; ChannelManager const& channel_manager_; Ui::ScaleChannelDialog ui_; double last_min_; double last_max_; }; } #endif sigviewer-0.6.4/src/gui_impl/dialogs/scale_channel_dialog.ui000066400000000000000000000105421345753661000242140ustar00rootroot00000000000000 ScaleChannelDialog 0 0 426 238 Scale Channel 0 0 Scaling Auto Scaling true Manual Scaling Upper Value false Lower Value false -23.000000000000000 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() ScaleChannelDialog accept() 248 254 157 274 buttonBox rejected() ScaleChannelDialog reject() 316 260 286 274 manualButton toggled(bool) lower_spinbox_ setEnabled(bool) 135 39 201 98 manualButton toggled(bool) upper_spinbox_ setEnabled(bool) 135 39 201 67 sigviewer-0.6.4/src/gui_impl/event_table/000077500000000000000000000000001345753661000204235ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/event_table/event_table.pri000066400000000000000000000003241345753661000234260ustar00rootroot00000000000000HEADERS += \ $$PWD/event_table_view_model.h \ $$PWD/event_table_widget.h SOURCES += \ $$PWD/event_table_view_model.cpp \ $$PWD/event_table_widget.cpp FORMS += \ $$PWD/event_table_widget.ui sigviewer-0.6.4/src/gui_impl/event_table/event_table_view_model.cpp000066400000000000000000000021251345753661000256310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_table_view_model.h" #include "event_table_widget.h" namespace sigviewer { //----------------------------------------------------------------------------- EventTableViewModel::EventTableViewModel (EventTableWidget& event_table_widget) : EventView (false, false), event_table_widget_ (event_table_widget) { } //----------------------------------------------------------------------------- QSharedPointer EventTableViewModel::getEventManager () const { return event_table_widget_.getEventManager (); } //----------------------------------------------------------------------------- QSharedPointer EventTableViewModel::getEventManager () { return event_table_widget_.getEventManager (); } //----------------------------------------------------------------------------- QList EventTableViewModel::getSelectedEvents () const { return event_table_widget_.getSelectedEvents (); } } sigviewer-0.6.4/src/gui_impl/event_table/event_table_view_model.h000066400000000000000000000026331345753661000253020ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TABLE_VIEW_MODEL_H #define EVENT_TABLE_VIEW_MODEL_H #include "gui/event_view.h" namespace sigviewer { class EventTableWidget; //----------------------------------------------------------------------------- class EventTableViewModel : public EventView { public: //------------------------------------------------------------------------- EventTableViewModel (EventTableWidget& event_table_widget); //------------------------------------------------------------------------- virtual void setShownEventTypes (std::set const& /*event_types*/) {} //------------------------------------------------------------------------- virtual std::set getShownEventTypes () const {return std::set ();} //------------------------------------------------------------------------- virtual QSharedPointer getEventManager () const; //------------------------------------------------------------------------- virtual QSharedPointer getEventManager (); //------------------------------------------------------------------------- virtual QList getSelectedEvents () const; private: EventTableWidget& event_table_widget_; }; } #endif // EVENT_TABLE_VIEW_MODEL_H sigviewer-0.6.4/src/gui_impl/event_table/event_table_widget.cpp000066400000000000000000000161241345753661000247660ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_table_widget.h" #include "base/math_utils.h" #include "gui/gui_action_factory.h" #include #include #include namespace sigviewer { class EventTableItem : public QTableWidgetItem { public: EventTableItem (float32 number, int precision = 0) : QTableWidgetItem (QString::number(number, 'f', precision)) {} virtual bool operator< (QTableWidgetItem const& other) const { return other.text().toFloat() < text().toFloat(); } }; //------------------------------------------------------------------------- EventTableWidget::EventTableWidget (QSharedPointer tab_context, QSharedPointer event_manager, ChannelManager const& channel_manager, QWidget *parent) : QWidget(parent), precision_ (MathUtils_::sampleRateToDecimalPrecision(event_manager->getSampleRate())), tab_context_ (tab_context), event_manager_ (event_manager), channel_manager_ (channel_manager) { ui_.setupUi(this); connect (event_manager_.data(), SIGNAL(eventCreated(QSharedPointer)), SLOT(addToTable(QSharedPointer))); connect (event_manager_.data(), SIGNAL(eventRemoved(EventID)), SLOT(removeFromTable(EventID))); connect (event_manager_.data(), SIGNAL(eventChanged(EventID)), SLOT(updateEventEntry(EventID))); buildTable(); ui_.event_table_->sortByColumn (POSITION_INDEX_); ui_.event_table_->hideColumn (ID_INDEX_); QToolBar* toolbar = new QToolBar (this); toolbar->setToolButtonStyle (Qt::ToolButtonTextUnderIcon); toolbar->setOrientation (Qt::Vertical); toolbar->addAction (GuiActionFactory::getInstance()->getQAction ("Delete")); toolbar->addAction (GuiActionFactory::getInstance()->getQAction ("Import Events...")); toolbar->addAction (GuiActionFactory::getInstance()->getQAction ("Export Events to CSV...")); toolbar->addAction (GuiActionFactory::getInstance()->getQAction ("Export Events to EVT...")); ui_.horizontalLayout->addWidget (toolbar); } //------------------------------------------------------------------------- EventTableWidget::~EventTableWidget() { qDebug () << "EventTableWidget::~EventTableWidget"; } //------------------------------------------------------------------------- QList EventTableWidget::getSelectedEvents () const { QSet selected_events; foreach (QTableWidgetItem* item, ui_.event_table_->selectedItems ()) selected_events.insert (item->data(Qt::UserRole).toInt()); return selected_events.values(); } //------------------------------------------------------------------------- QSharedPointer EventTableWidget::getEventView () { if (event_table_view_model_.isNull()) event_table_view_model_ = QSharedPointer (new EventTableViewModel(*this)); return event_table_view_model_; } //------------------------------------------------------------------------- void EventTableWidget::addToTable (QSharedPointer event) { int row = ui_.event_table_->rowCount (); ui_.event_table_->insertRow (row); QTableWidgetItem* position_item = new EventTableItem (event->getPositionInSec(), precision_); QTableWidgetItem* duration_item = new EventTableItem (event->getDurationInSec(), precision_); QTableWidgetItem* channel_item = new QTableWidgetItem (channel_manager_.getChannelLabel(event->getChannel(), event->getStream())); QTableWidgetItem* type_item = new QTableWidgetItem (event_manager_->getNameOfEvent(event->getId())); QTableWidgetItem* id_item = new EventTableItem (event->getId()); position_item->setData (Qt::UserRole, event->getId()); duration_item->setData (Qt::UserRole, event->getId()); channel_item->setData (Qt::UserRole, event->getId()); type_item->setData (Qt::UserRole, event->getId()); id_item->setData (Qt::UserRole, event->getId()); ui_.event_table_->setItem (row, POSITION_INDEX_, position_item); row = ui_.event_table_->row (position_item); ui_.event_table_->setItem (row, DURATION_INDEX_, duration_item); row = ui_.event_table_->row (duration_item); ui_.event_table_->setItem (row, CHANNEL_INDEX_, channel_item); row = ui_.event_table_->row (channel_item); ui_.event_table_->setItem (row, TYPE_INDEX_, type_item); row = ui_.event_table_->row (type_item); ui_.event_table_->setItem (row, ID_INDEX_, id_item); } //------------------------------------------------------------------------- void EventTableWidget::removeFromTable (EventID event) { qDebug () << "EventTableWidget::removeFromTable " << event; QList rows_to_remove; for (int row = 0; row < ui_.event_table_->rowCount(); row++) if (ui_.event_table_->item(row, ID_INDEX_)->text().toInt() == event) rows_to_remove.prepend (row); foreach (int row, rows_to_remove) ui_.event_table_->removeRow (row); } //------------------------------------------------------------------------- void EventTableWidget::updateEventEntry (EventID event_id) { QSharedPointer event = event_manager_->getEvent (event_id); bool updated = false; for (int row = 0; (row < ui_.event_table_->rowCount()) && (!updated); row++) { QTableWidgetItem* id_item = ui_.event_table_->item (row, ID_INDEX_); if (id_item->text().toInt() == event_id) { ui_.event_table_->item (row, CHANNEL_INDEX_)->setText (channel_manager_.getChannelLabel (event->getChannel(), event->getStream())); ui_.event_table_->item (row, POSITION_INDEX_)->setText (QString::number (event->getPositionInSec(), 'f', precision_)); ui_.event_table_->item (row, DURATION_INDEX_)->setText (QString::number (event->getDurationInSec(), 'f', precision_)); ui_.event_table_->item (row, TYPE_INDEX_)->setText (event_manager_->getNameOfEvent (event_id)); updated = true; } } } //------------------------------------------------------------------------- void EventTableWidget::on_event_table__itemSelectionChanged () { if (ui_.event_table_->selectedItems().size()) { qDebug () << "EventTableWidget::on_event_table__itemSelectionChanged"; tab_context_->setSelectionState (TAB_STATE_EVENT_SELECTED_ALL_CHANNELS); } else tab_context_->setSelectionState (TAB_STATE_NO_EVENT_SELECTED); } //------------------------------------------------------------------------- void EventTableWidget::showEvent (QShowEvent* /*event*/) { on_event_table__itemSelectionChanged (); } //------------------------------------------------------------------------- void EventTableWidget::buildTable () { foreach (EventID event_id, event_manager_->getAllEvents ()) addToTable (event_manager_->getEvent (event_id)); } } sigviewer-0.6.4/src/gui_impl/event_table/event_table_widget.h000066400000000000000000000047251345753661000244370ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TABLE_WIDGET_H #define EVENT_TABLE_WIDGET_H #include "ui_event_table_widget.h" #include "file_handling/event_manager.h" #include "gui/event_view.h" #include "file_handling/channel_manager.h" #include "event_table_view_model.h" #include "tab_context.h" #include namespace sigviewer { namespace Tests_ { class EventTableWidgetTests;} //----------------------------------------------------------------------------- class EventTableWidget : public QWidget { friend class sigviewer::Tests_::EventTableWidgetTests; Q_OBJECT public: //------------------------------------------------------------------------- EventTableWidget (QSharedPointer tab_context, QSharedPointer event_manager, ChannelManager const& channel_manager, QWidget *parent = 0); //------------------------------------------------------------------------- virtual ~EventTableWidget (); //------------------------------------------------------------------------- virtual QList getSelectedEvents () const; //------------------------------------------------------------------------- QSharedPointer getEventManager () const {return event_manager_;} //------------------------------------------------------------------------- QSharedPointer getEventManager () {return event_manager_;} //------------------------------------------------------------------------- QSharedPointer getEventView (); private slots: void addToTable (QSharedPointer event); void removeFromTable (EventID event); void updateEventEntry (EventID event_id); void on_event_table__itemSelectionChanged (); private: void showEvent (QShowEvent* event); void buildTable (); static int const ID_INDEX_ = 0; static int const POSITION_INDEX_ = 1; static int const DURATION_INDEX_ = 2; static int const CHANNEL_INDEX_ = 3; static int const TYPE_INDEX_ = 4; int precision_; Ui::EventTableWidget ui_; QSharedPointer tab_context_; QSharedPointer event_manager_; QSharedPointer event_table_view_model_; ChannelManager const& channel_manager_; }; } #endif // EVENT_TABLE_WIDGET_H sigviewer-0.6.4/src/gui_impl/event_table/event_table_widget.ui000066400000000000000000000036261345753661000246240ustar00rootroot00000000000000 EventTableWidget 0 0 653 450 Form 400 0 QAbstractItemView::NoEditTriggers QAbstractItemView::MultiSelection QAbstractItemView::SelectRows QAbstractItemView::ScrollPerPixel QAbstractItemView::ScrollPerPixel true true ID Position Duration Channel Type sigviewer-0.6.4/src/gui_impl/gui_helper_functions.cpp000066400000000000000000000225211345753661000230540ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "gui_impl/gui_helper_functions.h" #include "dialogs/channel_selection_dialog.h" #include "select_shown_channels_dialog.h" #include "dialogs/event_types_selection_dialog.h" #include "application_context_impl.h" #include #include #include #include #include #include #include namespace sigviewer { namespace GuiHelper { //----------------------------------------------------------------------------- void animateProperty (QObject* target, QByteArray const& property_name, QVariant const& start_value, QVariant const& end_value, QObject* call_back_object, char const* call_back_slot) { QSettings settings; settings.beginGroup("Animations"); bool animations_activated = settings.value("activated", false).toBool(); int animation_duration = settings.value("duration", 200).toInt(); settings.endGroup(); animations_activated = false; if (animations_activated) { QPropertyAnimation* animation = new QPropertyAnimation (target, property_name); animation->setDuration (animation_duration); animation->setStartValue (start_value); animation->setEasingCurve(QEasingCurve::InOutCubic); animation->setEndValue (end_value); if (call_back_object && call_back_slot) { call_back_object->connect (animation, SIGNAL(finished()), call_back_slot); } animation->start (animation->DeleteWhenStopped); } else { target->setProperty (property_name, end_value); if (call_back_object && call_back_slot) { QAction dummy_action (call_back_object); call_back_object->connect(&dummy_action, SIGNAL(triggered()), call_back_slot); dummy_action.trigger(); } } } //----------------------------------------------------------------------------- QList > getSelectedEvents (QSharedPointer event_view) { qDebug () << "getSelectedEvents: " << event_view.isNull(); QList ids = getSelectedEventIDs (event_view); QList > events; if (ids.size() == 0) return events; QSharedPointer event_manager = event_view->getEventManager(); foreach (EventID id, ids) events.append (event_manager->getEvent (id)); return events; } //----------------------------------------------------------------------------- QList getSelectedEventIDs (QSharedPointer event_view) { QList event_ids; qDebug () << "getSelectedEventIDs: " << event_view.isNull(); if (event_view.isNull()) return event_ids; return event_view->getSelectedEvents (); } //----------------------------------------------------------------------------- EventType selectEventType (EventType preselected_type, QSharedPointer signal_visualisation_model) { EventType new_type = UNDEFINED_EVENT_TYPE; QSharedPointer event_manager = signal_visualisation_model->getEventManager(); std::set types = signal_visualisation_model->getShownEventTypes (); QStringList event_type_list; int32 current_item = 0; for (std::set::const_iterator it = types.begin(); it != types.end(); it++) { if (preselected_type == *it) current_item = event_type_list.size(); QString event_name = event_manager->getNameOfEventType (*it); event_type_list.append (event_name + " " + QString("(%1)") .arg(*it,4, 16) .replace(' ', '0')); } bool ok = false; QString res = QInputDialog::getItem(0, QObject::tr("Change Type"), QObject::tr("Select new Type:"), event_type_list, current_item, false, &ok); if (ok) new_type = res.right(5).left(4).toUShort(0, 16); return new_type; } //----------------------------------------------------------------------------- std::set selectEventTypes (std::set const& preselected_type, QSharedPointer event_manager, QSharedPointer color_manager) { std::set selected_types; if (event_manager.isNull()) return selected_types; selected_types = preselected_type; EventTypesSelectionDialog dialog (QObject::tr("Select Event Types"), event_manager, preselected_type, color_manager, 0); if (dialog.exec() == QDialog::Accepted) { selected_types = dialog.getSelectedTypes (); dialog.storeColors (); return selected_types; } return selected_types; } //----------------------------------------------------------------------------- ChannelID selectChannel (ChannelID preselected_channel_id, QSharedPointer signal_visualisation_model) { int32 current_item = 0; QStringList channel_list; channel_list.append (QObject::tr("All Channels")); ChannelManager const& channel_manager = signal_visualisation_model->getChannelManager(); std::set shown_channels = signal_visualisation_model->getShownChannels (); for (std::set::iterator channel_iter = shown_channels.begin(); channel_iter != shown_channels.end(); ++channel_iter) { if (*channel_iter == preselected_channel_id) current_item = channel_list.size(); channel_list.append( QString("(%1) ").arg(*channel_iter + 1) + channel_manager.getChannelLabel (*channel_iter)); } bool ok = false; QString res = QInputDialog::getItem(0, QObject::tr("Change Channel"), QObject::tr("Select New Channel:"), channel_list, current_item, false, &ok); ChannelID new_channel = res.replace(')', '(').section('(', 1, 1).toInt() - 1; if (ok) return new_channel; else return preselected_channel_id; } //----------------------------------------------------------------------------- std::set selectShownChannels (ChannelID hide_channel, QSharedPointer vis_model) { std::set channels = vis_model->getShownChannels (); channels.erase (hide_channel); SelectShownChannelsDialog dialog (QObject::tr("Copy Event to Channels"), channels, vis_model->getChannelManager()); dialog.exec (); return dialog.getSelectedChannels (); } //----------------------------------------------------------------------------- std::set selectChannels (ChannelManager const& channel_manager, QSharedPointer color_manager, QSharedPointer header, QSharedPointer vis_model) { ChannelSelectionDialog channel_dialog (channel_manager, header, color_manager); std::set pre_selected_channels; if (!vis_model.isNull()) pre_selected_channels = vis_model->getShownChannels (); bool empty_selection = (pre_selected_channels.size () == 0); foreach (ChannelID channel_id, channel_manager.getChannels()) { bool show_channel = (empty_selection || (pre_selected_channels.count(channel_id) > 0)); channel_dialog.setSelected (channel_id, show_channel); } channel_dialog.exec(); if (channel_dialog.result() == QDialog::Rejected) return pre_selected_channels; std::set selected_channels; foreach (ChannelID channel_id, channel_manager.getChannels()) { if (channel_dialog.isSelected (channel_id)) selected_channels.insert (channel_id); } return selected_channels; } //----------------------------------------------------------------------------- QString getFilePathFromSaveAsDialog (QString const& path, QString const& extensions, QString const& file_type_description) { QString extension_selection = file_type_description + QObject::tr(" (%1)").arg(extensions); QStringList ext_list = extensions.split (" "); for (QStringList::iterator it = ext_list.begin(); it != ext_list.end(); it++) { extension_selection += ";; " + *it +" (" + *it + ")"; } extension_selection += ";; *.* (*.*)"; return QFileDialog::getSaveFileName (0, QObject::tr("Save"), path, extension_selection); } } } sigviewer-0.6.4/src/gui_impl/gui_helper_functions.h000066400000000000000000000057621345753661000225310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef GUI_HELPER_FUNCTIONS_H #define GUI_HELPER_FUNCTIONS_H #include "base/sigviewer_user_types.h" #include "file_handling/channel_manager.h" #include "file_handling/basic_header.h" #include "gui/signal_visualisation_model.h" #include "gui/color_manager.h" #include namespace sigviewer { namespace GuiHelper { //----------------------------------------------------------------------------- void animateProperty (QObject* target, QByteArray const& property_name, QVariant const& start_value, QVariant const& end_value, QObject* call_back_object = 0, char const* call_back_slot = 0); //----------------------------------------------------------------------------- QList > getSelectedEvents (QSharedPointer event_view); //----------------------------------------------------------------------------- QList getSelectedEventIDs (QSharedPointer event_view); //----------------------------------------------------------------------------- EventType selectEventType (EventType preselected_type, QSharedPointer signal_visualisation_model); //----------------------------------------------------------------------------- std::set selectEventTypes (std::set const& preselected_type, QSharedPointer event_manager, QSharedPointer color_manager); //----------------------------------------------------------------------------- ChannelID selectChannel (ChannelID preselected_channel, QSharedPointer signal_visualisation_model); //----------------------------------------------------------------------------- std::set selectShownChannels (ChannelID hide_channel, QSharedPointer vis_model); //----------------------------------------------------------------------------- std::set selectChannels (ChannelManager const& channel_manager, QSharedPointer color_manager, QSharedPointer header, QSharedPointer vis_model = QSharedPointer(0)); //----------------------------------------------------------------------------- QString getFilePathFromSaveAsDialog (QString const& path, QString const& extensions, QString const& file_type_description); } } #endif // GUI_HELPER_FUNCTIONS_H sigviewer-0.6.4/src/gui_impl/gui_impl.pri000066400000000000000000000013311345753661000204520ustar00rootroot00000000000000HEADERS += \ $$PWD/gui_helper_functions.h \ $$PWD/main_window.h \ $$PWD/main_window_model_impl.h \ $$PWD/processed_signal_channel_manager.h \ $$PWD/signal_browser_mouse_handling.h \ $$PWD/select_shown_channels_dialog.h SOURCES += \ $$PWD/gui_helper_functions.cpp \ $$PWD/main_window.cpp \ $$PWD/main_window_model_impl.cpp \ $$PWD/processed_signal_channel_manager.cpp \ $$PWD/select_shown_channels_dialog.cpp \ $$PWD/signal_browser_mouse_handling.cpp FORMS += \ $$PWD/info_widgets/power_spectrum_info_widget.ui include($$PWD/commands/commands.pri) include($$PWD/dialogs/dialogs.pri) include($$PWD/event_table/event_table.pri) include($$PWD/signal_browser/signal_browser.pri) sigviewer-0.6.4/src/gui_impl/info_widgets/000077500000000000000000000000001345753661000206145ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/info_widgets/power_spectrum_info_widget.ui000066400000000000000000000005641345753661000266140ustar00rootroot00000000000000 Form 0 0 323 68 Form sigviewer-0.6.4/src/gui_impl/main_window.cpp000066400000000000000000000316131345753661000211560ustar00rootroot00000000000000// Copyright (c) 2017 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "main_window.h" #include "gui/background_processes.h" #include "gui_impl/commands/open_file_gui_command.h" #include #include #include #include #include #include namespace sigviewer { //---------------------------------------------------------------------------- MainWindow::MainWindow(QSharedPointer application_context) : QMainWindow(0) { setWindowTitle(tr("SigViewer")); setAcceptDrops(true); setWindowIcon(QIcon(":images/sigviewer128.png")); initStatusBar(); initToolBars(); initMenus(application_context); setUnifiedTitleAndToolBarOnMac (true); QSettings settings; resize(settings.value("MainWindow/size", QSize(1200, 800)).toSize()); setMinimumSize(900, 800); restoreGeometry(settings.value("geometry").toByteArray()); //restore geometry and window state (full screen etc.) restoreState(settings.value("windowState").toByteArray()); } //----------------------------------------------------------------------------- void MainWindow::initStatusBar() { connect (&BackgroundProcesses::instance(), SIGNAL(newProcess(QString,int)), SLOT(addBackgroundProcessToStatusBar(QString,int))); connect (&BackgroundProcesses::instance(), SIGNAL(processChangedState(QString,int)), SLOT(updateBackgroundProcessonStatusBar(QString,int))); connect (&BackgroundProcesses::instance(), SIGNAL(processRemoved(QString)), SLOT(removeBackgroundProcessFromStatusBar(QString))); QStatusBar* status_bar = statusBar(); //status_bar->showMessage(tr("Ready")); status_bar_signal_length_label_ = new QLabel (this); status_bar_nr_channels_label_ = new QLabel (this); status_bar_signal_length_label_->setAlignment(Qt::AlignHCenter); status_bar_nr_channels_label_->setAlignment(Qt::AlignHCenter); status_bar->addPermanentWidget(status_bar_signal_length_label_); status_bar->addPermanentWidget(status_bar_nr_channels_label_); QSettings settings; status_bar->setVisible (settings.value ("MainWindow/statusbar", true).toBool()); } //----------------------------------------------------------------------------- void MainWindow::initToolBars() { view_toolbar_views_menu_ = new QMenu (tr("Toolbars"), this); file_toolbar_ = addToolBar(tr("File")); file_toolbar_->setObjectName("File"); file_toolbar_->setMovable(false); view_toolbar_views_menu_->addAction (file_toolbar_->toggleViewAction()); file_toolbar_->addAction (action("Open...")); file_toolbar_->addAction (action("Save")); file_toolbar_->addAction (action("Info...")); file_toolbar_->addAction (action("Undo")); file_toolbar_->addAction (action("Redo")); // file_toolbar_->addAction (action("Close")); mouse_mode_toolbar_ = addToolBar(tr("Mode")); mouse_mode_toolbar_->setObjectName("Mode"); mouse_mode_toolbar_->setMovable(false); view_toolbar_views_menu_->addAction (mouse_mode_toolbar_->toggleViewAction()); mouse_mode_toolbar_->addAction (action("New Event")); mouse_mode_toolbar_->addAction (action("Edit Event")); mouse_mode_toolbar_->addAction (action("Scroll")); mouse_mode_toolbar_->addAction (action("View Options")); view_toolbar_ = addToolBar(tr("View")); view_toolbar_->setObjectName("View"); view_toolbar_->setMovable(false); view_toolbar_views_menu_->addAction (view_toolbar_->toggleViewAction()); view_toolbar_->addAction(action("Events...")); view_toolbar_->addAction(action("Channels...")); view_toolbar_->addAction(action("Scale All...")); view_toolbar_->addAction(action("Zoom In Vertical")); view_toolbar_->addAction(action("Zoom Out Vertical")); view_toolbar_->addAction(action("Zoom In Horizontal")); view_toolbar_->addAction(action("Zoom Out Horizontal")); view_toolbar_views_menu_->addSeparator (); toggle_all_toolbars_ = new QAction (tr("Hide all Toolbars"), this); connect (toggle_all_toolbars_, SIGNAL(triggered()), SLOT(toggleAllToolbars())); toggle_all_toolbars_->setData (true); view_toolbar_views_menu_->addAction (toggle_all_toolbars_); } //------------------------------------------------------------------- void MainWindow::toggleStatusBar (bool visible) { statusBar()->setVisible (visible); QSettings settings; settings.setValue("MainWindow/statusbar", statusBar()->isVisible()); } //------------------------------------------------------------------- void MainWindow::toggleAllToolbars () { if (toggle_all_toolbars_->data().toBool()) { toggle_all_toolbars_->setData (false); toggle_all_toolbars_->setText(tr("Show all Toolbars")); foreach (QAction* toggle_action, view_toolbar_views_menu_->actions()) if (toggle_action->isCheckable() && toggle_action->isChecked()) toggle_action->trigger (); } else { toggle_all_toolbars_->setData (true); toggle_all_toolbars_->setText(tr("Hide all Toolbars")); foreach (QAction* toggle_action, view_toolbar_views_menu_->actions()) if (toggle_action->isCheckable() && !toggle_action->isChecked()) toggle_action->trigger (); } } //----------------------------------------------------------------------------- void MainWindow::addBackgroundProcessToStatusBar (QString name, int max) { QProgressBar* progress_bar = new QProgressBar (this); progress_bar->setMinimum (0); progress_bar->setMaximum (max); progress_bar->setValue (0); background_processes_progressbars_[name] = progress_bar; background_processes_labels_[name] = new QLabel (name, this); statusBar()->insertPermanentWidget (0, progress_bar); statusBar()->insertPermanentWidget (0, background_processes_labels_[name]); } //----------------------------------------------------------------------------- void MainWindow::updateBackgroundProcessonStatusBar (QString name, int value) { if (!background_processes_progressbars_.contains (name)) return; background_processes_progressbars_[name]->setValue (value); } //----------------------------------------------------------------------------- void MainWindow::removeBackgroundProcessFromStatusBar (QString name) { if (!background_processes_progressbars_.contains (name)) return; statusBar()->removeWidget (background_processes_progressbars_[name]); delete background_processes_progressbars_[name]; background_processes_progressbars_.remove (name); statusBar()->removeWidget (background_processes_labels_[name]); delete background_processes_labels_[name]; background_processes_labels_.remove (name); } //----------------------------------------------------------------------------- void MainWindow::initMenus (QSharedPointer application_context) { file_recent_files_menu_ = new QMenu(tr("Open &Recent"), this); connect(file_recent_files_menu_, SIGNAL(aboutToShow()), SIGNAL(recentFileMenuAboutToShow())); connect(file_recent_files_menu_, SIGNAL(triggered(QAction*)), SIGNAL(recentFileActivated(QAction*))); file_menu_ = menuBar()->addMenu(tr("&File")); file_menu_->addAction(action("Open...")); file_menu_->addMenu (file_recent_files_menu_); file_menu_->addAction (action("Save")); file_menu_->addAction (action("Save as...")); file_menu_->addAction (action("Info...")); file_menu_->addAction (action("Close")); file_menu_->addSeparator (); file_menu_->addAction (action("Import Events...")); file_menu_->addAction (action("Export Events to CSV...")); file_menu_->addAction (action("Export Events to EVT...")); // file_menu_->addAction (action("Export to GDF...")); file_menu_->addSeparator (); file_menu_->addAction (action("Exit")); edit_menu_ = menuBar()->addMenu(tr("&Edit")); edit_menu_->addAction (action("Undo")); edit_menu_->addAction (action("Redo")); edit_menu_->addSeparator (); edit_menu_->addAction (action("To all Channels")); edit_menu_->addAction (action("Copy to Channels...")); edit_menu_->addAction (action("Delete")); edit_menu_->addAction (action("Change Channel...")); edit_menu_->addAction (action("Change Type...")); edit_menu_->addSeparator (); edit_menu_->addAction (action("Insert Over")); mouse_mode_menu_ = menuBar()->addMenu(tr("&Mode")); mouse_mode_menu_->addAction (action("New Event")); mouse_mode_menu_->addAction (action("Edit Event")); mouse_mode_menu_->addAction (action("Scroll")); mouse_mode_menu_->addAction (action("View Options")); QSettings settings; QAction* toggle_status_bar = new QAction (tr("Statusbar"), this); toggle_status_bar->setCheckable (true); toggle_status_bar->setChecked (settings.value ("MainWindow/statusbar", true).toBool()); connect (toggle_status_bar, SIGNAL(toggled(bool)), this, SLOT(toggleStatusBar(bool))); view_menu_ = menuBar()->addMenu(tr("&View")); view_menu_->addMenu (view_toolbar_views_menu_); view_menu_->addAction(toggle_status_bar); view_menu_->addSeparator(); view_menu_->addAction(action("Events...")); view_menu_->addAction(action("Channels...")); view_menu_->addAction(action("Scale All...")); view_menu_->addSeparator(); view_menu_->addAction(action("Zoom In Vertical")); view_menu_->addAction(action("Zoom Out Vertical")); view_menu_->addAction(action("Zoom In Horizontal")); view_menu_->addAction(action("Zoom Out Horizontal")); view_menu_->addSeparator(); view_menu_->addAction(action("Go to...")); view_menu_->addSeparator(); view_menu_->addAction(action("Goto and Select Next Event")); view_menu_->addAction(action("Goto and Select Previous Event")); view_menu_->addSeparator(); view_menu_->addAction(action("Fit View to Selected Event")); view_menu_->addAction(action("Hide Events of other Type")); view_menu_->addAction(action("Show all Events")); tools_menu_ = menuBar()->addMenu(tr("&Tools")); tools_menu_->addActions(GuiActionFactory::getInstance()->getQActions("Signal Processing")); help_menu_ = menuBar()->addMenu(tr("&Help")); if (application_context->modeActivated (APPLICATION_TEST_MODE)) { help_menu_->addAction (action("Run Tests...")); help_menu_->addSeparator(); } help_menu_->addAction (action("About")); } //----------------------------------------------------------------------------- void MainWindow::closeEvent (QCloseEvent* event) { QSettings settings; settings.setValue("geometry", saveGeometry()); settings.setValue("windowState", saveState()); GuiActionFactory::getInstance()->getQAction("Exit")->trigger(); event->ignore (); } //----------------------------------------------------------------------------- void MainWindow::dropEvent (QDropEvent* event) { if (event->mimeData()->hasUrls()) { QString localPath(event->mimeData()->urls().first().toLocalFile()); event->acceptProposedAction(); OpenFileGuiCommand::openFile (localPath); } else if (event->mimeData()->hasText()) { QString localPath(event->mimeData()->text()); event->acceptProposedAction(); OpenFileGuiCommand::openFile (localPath); } } //----------------------------------------------------------------------------- void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasText() || event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } //----------------------------------------------------------------------------- void MainWindow::resizeEvent (QResizeEvent* event) { QSettings settings; settings.setValue("MainWindow/size", event->size()); } //----------------------------------------------------------------------------- void MainWindow::setRecentFiles(const QStringList& recent_file_list) { file_recent_files_menu_->clear(); for (QStringList::const_iterator it = recent_file_list.begin(); it != recent_file_list.end(); it++) { file_recent_files_menu_->addAction(*it); } } //----------------------------------------------------------------------------- void MainWindow::setStatusBarSignalLength(float64 length) { if (length > 0) status_bar_signal_length_label_->setText (tr("Length: ") + QString::number(length, 'f', 1) + "s"); status_bar_signal_length_label_->setVisible (length > 0); } //----------------------------------------------------------------------------- void MainWindow::setStatusBarNrChannels(int32 nr_channels) { if (nr_channels > 0) status_bar_nr_channels_label_->setText (tr("Channels: ") + QString::number(nr_channels)); status_bar_nr_channels_label_->setVisible (nr_channels > 0); } //----------------------------------------------------------------------------- QAction* MainWindow::action (QString const& action_id) { return GuiActionFactory::getInstance()->getQAction (action_id); } } sigviewer-0.6.4/src/gui_impl/main_window.h000066400000000000000000000042331345753661000206210ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H #include "gui/application_context.h" #include #include class QAction; class QComboBox; class QMenu; class QLabel; namespace sigviewer { // main window class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow (QSharedPointer application_context); virtual ~MainWindow () {} void setStatusBarSignalLength(float64 length); void setStatusBarNrChannels(int32 nr_channels); void setRecentFiles(const QStringList& recent_file_list); signals: void recentFileActivated(QAction* recent_file_action); void recentFileMenuAboutToShow(); protected: virtual void closeEvent(QCloseEvent* close_event); virtual void dropEvent (QDropEvent* event); virtual void dragEnterEvent(QDragEnterEvent *event); virtual void resizeEvent (QResizeEvent* event); private slots: void toggleStatusBar (bool visible); void toggleAllToolbars (); void addBackgroundProcessToStatusBar (QString name, int max); void updateBackgroundProcessonStatusBar (QString name, int value); void removeBackgroundProcessFromStatusBar (QString name); private: QAction* action (QString const& action_id); MainWindow(const MainWindow&); const MainWindow& operator=(const MainWindow&); void initActions(); void initToolBars(); void initMenus (QSharedPointer application_context); void initStatusBar(); QMenu* file_menu_; QMenu* file_recent_files_menu_; QMenu* edit_menu_; QMenu* mouse_mode_menu_; QMenu* view_menu_; QMenu* view_toolbar_views_menu_; QMenu* tools_menu_; QMenu* help_menu_; QToolBar* file_toolbar_; QToolBar* mouse_mode_toolbar_; QToolBar* view_toolbar_; QLabel* status_bar_signal_length_label_; QLabel* status_bar_nr_channels_label_; QAction* toggle_all_toolbars_; QMap background_processes_progressbars_; QMap background_processes_labels_; }; } #endif sigviewer-0.6.4/src/gui_impl/main_window_model_impl.cpp000066400000000000000000000245401345753661000233600ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "main_window_model_impl.h" #include "main_window.h" #include "gui_impl/commands/open_file_gui_command.h" #include "gui_impl/signal_browser/signal_browser_model_4.h" #include "gui_impl/signal_browser/signal_browser_view.h" #include "gui_impl/event_table/event_table_widget.h" #include #include namespace sigviewer { int const MainWindowModelImpl::NUMBER_RECENT_FILES_ = 8; //----------------------------------------------------------------------------- MainWindowModelImpl::MainWindowModelImpl (QSharedPointer application_context) : application_context_ (application_context), main_window_ (new MainWindow (application_context)), tab_widget_ (0) { connect (main_window_, SIGNAL(recentFileActivated(QAction*)), SLOT(recentFileActivated(QAction*))); connect (main_window_, SIGNAL(recentFileMenuAboutToShow()), SLOT(recentFileMenuAboutToShow())); main_window_->show(); loadSettings(); } //----------------------------------------------------------------------------- MainWindowModelImpl::~MainWindowModelImpl () { qDebug () << "deleting MainWindowModelImpl"; } //----------------------------------------------------------------------------- void MainWindowModelImpl::loadSettings() { QSettings settings; settings.beginGroup("MainWindowModelImpl"); int size = settings.beginReadArray("recent_file"); for (int i = 0; i < size; i++) { settings.setArrayIndex(i); recent_file_list_.append(settings.value("name").toString()); } settings.endArray(); settings.endGroup(); } //----------------------------------------------------------------------------- void MainWindowModelImpl::saveSettings() { QSettings settings; settings.beginGroup("MainWindowModelImpl"); settings.beginWriteArray("recent_file"); for (int i = 0; i < recent_file_list_.size(); i++) { settings.setArrayIndex(i); settings.setValue("name", recent_file_list_.at(i)); } settings.endArray(); settings.endGroup(); } //----------------------------------------------------------------------------- void MainWindowModelImpl::tabChanged (int tab_index) { if (tab_contexts_.find(tab_index) != tab_contexts_.end ()) { application_context_->setCurrentTabContext (tab_contexts_[tab_index]); tab_contexts_[tab_index]->gotActive (); } } //----------------------------------------------------------------------------- void MainWindowModelImpl::closeTab (int tab_index) { if ((tab_index == 0) | (tab_index == 1)) // first two tabs are not closeable return; QWidget* widget = tab_widget_->widget (tab_index); browser_models_.erase (tab_index); tab_widget_->removeTab (tab_index); delete widget; int models_count = browser_models_.size(); if (models_count >= tab_index) { for (int index = tab_index + 1; index < models_count; index++) browser_models_[index - 1] = browser_models_[index]; } int event_views_count = event_views_.size(); if (event_views_count >= tab_index) { for (int index = tab_index + 1; index < event_views_count; index++) if (event_views_.contains (index)) event_views_[index - 1] = event_views_[index]; } } //----------------------------------------------------------------------------- void MainWindowModelImpl::recentFileMenuAboutToShow() { main_window_->setRecentFiles(recent_file_list_); } //----------------------------------------------------------------------------- void MainWindowModelImpl::recentFileActivated(QAction* recent_file_action) { OpenFileGuiCommand::openFile (recent_file_action->text()); } //----------------------------------------------------------------------------- void MainWindowModelImpl::storeAndInitTabContext (QSharedPointer context, int tab_index) { tab_contexts_[tab_index] = context; application_context_->setCurrentTabContext (context); context->setSelectionState (TAB_STATE_NO_EVENT_SELECTED); context->setEditState (TAB_STATE_NO_REDO_NO_UNDO); } //------------------------------------------------------------------------- QSharedPointer MainWindowModelImpl::createSignalVisualisation (QString const& title, ChannelManager const& channel_manager) { int tab_index = createSignalVisualisationImpl (channel_manager, QSharedPointer(0)); tab_widget_->setTabText(tab_index, title); tab_widget_->setCurrentIndex(tab_index); return browser_models_[tab_index]; } //----------------------------------------------------------------------------- QSharedPointer MainWindowModelImpl::createSignalVisualisationOfFile (QSharedPointer file_ctx) { // waldesel: // --begin // to be replaced as soon as multi file support is implemented if (!(application_context_->getCurrentFileContext().isNull())) GuiActionFactory::getInstance()->getQAction("Close")->trigger(); // --end if (!tab_widget_) { tab_widget_ = new QTabWidget (main_window_); if (!connect (tab_widget_, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)))) throw (Exception ("MainWindowModelImpl::createSignalVisualisationOfFile failed: connect (tab_widget_, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)))")); connect (tab_widget_, SIGNAL(tabCloseRequested(int)), SLOT(closeTab(int))); tab_widget_->setTabsClosable (true); } recent_file_list_.removeAll (file_ctx->getFilePathAndName()); if (recent_file_list_.size() == NUMBER_RECENT_FILES_) recent_file_list_.pop_back(); recent_file_list_.push_front (file_ctx->getFilePathAndName()); saveSettings(); // waldesel: // --begin // to be replaced as soon as new zooming is implemented main_window_->setStatusBarSignalLength (file_ctx->getChannelManager().getDurationInSec()); // --end main_window_->setStatusBarNrChannels (file_ctx->getChannelManager().getNumberChannels()); resetCurrentFileName (file_ctx->getFileName()); connect (file_ctx.data(), SIGNAL(fileNameChanged(QString const&)), SLOT(resetCurrentFileName(QString const&))); int tab_index = createSignalVisualisationImpl (file_ctx->getChannelManager(), file_ctx->getEventManager()); QString tab_title ("Signal Data"); main_window_->setCentralWidget(tab_widget_); tab_widget_->show(); tab_widget_->setTabText(tab_index, tab_title); tab_widget_->tabBar()->setTabButton(0, QTabBar::RightSide, 0); tab_widget_->tabBar()->setTabButton(0, QTabBar::LeftSide, 0); file_ctx->setMainVisualisationModel (browser_models_[tab_index]); return browser_models_[tab_index]; } //----------------------------------------------------------------------------- void MainWindowModelImpl::closeCurrentFileTabs () { // waldesel: // --begin // to be refactored as soon as multi file support is implemented main_window_->setCentralWidget (0); tab_widget_ = 0; tab_contexts_.clear (); // --end main_window_->setStatusBarSignalLength(-1); main_window_->setStatusBarNrChannels(-1); resetCurrentFileName (""); } //----------------------------------------------------------------------------- QSharedPointer MainWindowModelImpl::getCurrentSignalVisualisationModel () { if (!tab_widget_) return QSharedPointer(0); return browser_models_[tab_widget_->currentIndex()]; } //------------------------------------------------------------------------- QSharedPointer MainWindowModelImpl::getCurrentEventView () { if (!tab_widget_) return QSharedPointer(0); if (!event_views_.contains (tab_widget_->currentIndex())) return QSharedPointer(0); return event_views_[tab_widget_->currentIndex()]; } //------------------------------------------------------------------------- void MainWindowModelImpl::resetCurrentFileName (QString const& file_name) { if (file_name.size() == 0) main_window_->setWindowTitle (tr("SigViewer")); else main_window_->setWindowTitle (file_name + tr(" - SigViewer")); } //------------------------------------------------------------------------- int MainWindowModelImpl::createSignalVisualisationImpl (ChannelManager const& channel_manager, QSharedPointer event_manager) { QSharedPointer tab_context (new TabContext); QSharedPointer model (new SignalBrowserModel (event_manager, channel_manager, tab_context, application_context_->getEventColorManager())); SignalBrowserView* view = new SignalBrowserView (model, event_manager, tab_context, main_window_->rect(), tab_widget_); int tab_index = tab_widget_->addTab (view, tr("Signal")); model->setSignalBrowserView (view); browser_models_[tab_index] = model; event_views_[tab_index] = model; if (!event_manager.isNull()) { EventTableWidget* event_table_widget = new EventTableWidget (tab_context, event_manager, channel_manager); int event_tab_index = tab_widget_->addTab (event_table_widget, tr("Events")); browser_models_[event_tab_index] = QSharedPointer(0); event_views_[event_tab_index] = event_table_widget->getEventView(); tab_contexts_[event_tab_index] = tab_context; model->connect (event_manager.data(), SIGNAL(eventCreated(QSharedPointer)), SLOT(addEventItem(QSharedPointer))); model->connect (event_manager.data(), SIGNAL(eventRemoved(EventID)), SLOT(removeEventItem(EventID))); model->connect (event_manager.data(), SIGNAL(eventChanged(EventID)), SLOT(updateEvent(EventID))); tab_widget_->tabBar()->setTabButton(1, QTabBar::RightSide, 0); tab_widget_->tabBar()->setTabButton(1, QTabBar::LeftSide, 0); } storeAndInitTabContext (tab_context, tab_index); return tab_index; } } sigviewer-0.6.4/src/gui_impl/main_window_model_impl.h000066400000000000000000000071611345753661000230250ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef MAIN_WINDOW_MODEL_IMPL_H #define MAIN_WINDOW_MODEL_IMPL_H #include "gui/application_context.h" #include #include #include class QAction; namespace sigviewer { class MainWindow; //------------------------------------------------------------------------- class MainWindowModelImpl : public QObject, public MainWindowModel { Q_OBJECT public: //------------------------------------------------------------------------- MainWindowModelImpl (QSharedPointer application_context); //------------------------------------------------------------------------- virtual ~MainWindowModelImpl (); //------------------------------------------------------------------------- virtual QSharedPointer createSignalVisualisation (QString const& title, ChannelManager const& channel_manager); //------------------------------------------------------------------------- virtual QSharedPointer createSignalVisualisationOfFile (QSharedPointer file_ctx); //------------------------------------------------------------------------- virtual void closeCurrentFileTabs (); //------------------------------------------------------------------------- virtual QSharedPointer getCurrentSignalVisualisationModel (); //------------------------------------------------------------------------- virtual QSharedPointer getCurrentEventView (); public slots: //------------------------------------------------------------------------- void tabChanged (int tab_index); //------------------------------------------------------------------------- void closeTab (int tab_index); private slots: //------------------------------------------------------------------------- void recentFileActivated(QAction* recent_file_action); //------------------------------------------------------------------------- void recentFileMenuAboutToShow(); //------------------------------------------------------------------------- void resetCurrentFileName (QString const& file_name); private: //------------------------------------------------------------------------- void loadSettings(); //------------------------------------------------------------------------- void saveSettings(); //------------------------------------------------------------------------- int createSignalVisualisationImpl (ChannelManager const& channel_manager, QSharedPointer event_manager); //------------------------------------------------------------------------- void storeAndInitTabContext (QSharedPointer context, int tab_index); static int const NUMBER_RECENT_FILES_; QSharedPointer application_context_; MainWindow* main_window_; QTabWidget* tab_widget_; QStringList recent_file_list_; std::map > browser_models_; QMap > event_views_; std::map > tab_contexts_; //------------------------------------------------------------------------- // not allowed MainWindowModelImpl(const MainWindowModelImpl&); const MainWindowModelImpl& operator=(const MainWindowModelImpl&); }; } #endif sigviewer-0.6.4/src/gui_impl/processed_signal_channel_manager.cpp000066400000000000000000000064101345753661000253460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "processed_signal_channel_manager.h" #include namespace sigviewer { //------------------------------------------------------------------------- ProcessedSignalChannelManager::ProcessedSignalChannelManager(float64 sample_rate, unsigned length, QObject* parent) : QObject (parent), sample_rate_ (sample_rate), length_ (length) { // nothing to do here } //------------------------------------------------------------------------- void ProcessedSignalChannelManager::addChannel (ChannelID id, QSharedPointer data_block, QString const& label, QString const& y_unit_string) { channels_[id] = data_block; channel_labels_[id] = label; y_unit_strings_[id] = y_unit_string; } //------------------------------------------------------------------------- ChannelID ProcessedSignalChannelManager::addExtraChannel (ChannelID id, QSharedPointer data_block, QString const& label, QString const& y_unit_string) { id += 0.1f; channels_[id] = data_block; channel_labels_[id] = label; y_unit_strings_[id] = y_unit_string; return id; } //------------------------------------------------------------------------- std::set ProcessedSignalChannelManager::getChannels () const { std::set channels; foreach (ChannelID id, channels_.keys()) channels.insert(id); return channels; } //------------------------------------------------------------------------- uint32 ProcessedSignalChannelManager::getNumberChannels () const { return channels_.size (); } //------------------------------------------------------------------------- QString ProcessedSignalChannelManager::getChannelLabel (ChannelID id) const { return channel_labels_[id]; } //------------------------------------------------------------------------- QString ProcessedSignalChannelManager::getChannelYUnitString (ChannelID id) const { return y_unit_strings_[id]; } //------------------------------------------------------------------------- QSharedPointer ProcessedSignalChannelManager::getData (ChannelID id, unsigned start_pos, unsigned length) const { return channels_[id]->createSubBlock (start_pos, length); } //------------------------------------------------------------------------- float64 ProcessedSignalChannelManager::getDurationInSec() const { return static_cast(length_) / sample_rate_; } //------------------------------------------------------------------------- size_t ProcessedSignalChannelManager::getNumberSamples() const { return length_; } //------------------------------------------------------------------------- float64 ProcessedSignalChannelManager::getSampleRate() const { return sample_rate_; } //!Inherited, should not be called.---------------------------------------- QString ProcessedSignalChannelManager::getChannelLabel(ChannelID id, int streamNumber) const { qDebug() << "id: " << id << "stream: " << streamNumber; return ""; } } sigviewer-0.6.4/src/gui_impl/processed_signal_channel_manager.h000066400000000000000000000053741345753661000250230ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef PROCESSED_SIGNAL_CHANNEL_MANAGER_H #define PROCESSED_SIGNAL_CHANNEL_MANAGER_H #include "file_handling/channel_manager.h" #include #include namespace sigviewer { class ProcessedSignalChannelManager : public ChannelManager, public QObject { public: //------------------------------------------------------------------------- ProcessedSignalChannelManager(float64 sample_rate, unsigned length, QObject* parent); //------------------------------------------------------------------------- void addChannel (ChannelID id, QSharedPointer data_block, QString const& label, QString const& y_unit_string); //------------------------------------------------------------------------- ChannelID addExtraChannel (ChannelID id, QSharedPointer data_block, QString const& label, QString const& y_unit_string); //------------------------------------------------------------------------- virtual ~ProcessedSignalChannelManager () {} //------------------------------------------------------------------------- virtual std::set getChannels () const; //------------------------------------------------------------------------- virtual uint32 getNumberChannels () const; //------------------------------------------------------------------------- virtual QString getChannelLabel (ChannelID id) const; //------------------------------------------------------------------------- virtual QString getChannelYUnitString (ChannelID id) const; //------------------------------------------------------------------------- virtual QSharedPointer getData (ChannelID id, unsigned start_pos, unsigned length) const; //------------------------------------------------------------------------- virtual float64 getDurationInSec() const; //------------------------------------------------------------------------- virtual size_t getNumberSamples() const; //------------------------------------------------------------------------- virtual float64 getSampleRate() const; private: virtual QString getChannelLabel (ChannelID id, int streamNumber) const; /*!< Inherited, should not be called. */ float32 sample_rate_; unsigned length_; QMap > channels_; QMap channel_labels_; QMap y_unit_strings_; }; } #endif // PROCESSED_SIGNAL_CHANNEL_MANAGER_H sigviewer-0.6.4/src/gui_impl/select_shown_channels_dialog.cpp000066400000000000000000000052321345753661000245300ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "select_shown_channels_dialog.h" #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- SelectShownChannelsDialog::SelectShownChannelsDialog (QString const& dialog_title, std::set const& channels, ChannelManager const& channel_manager) : channels_ (channels) { setWindowTitle (dialog_title); QVBoxLayout* top_layout = new QVBoxLayout(this); top_layout->setMargin(10); top_layout->setSpacing(10); channel_list_widget_ = new QListWidget(this); channel_list_widget_->setSelectionMode(QAbstractItemView::ExtendedSelection); for (std::set::const_iterator channel_iter = channels_.begin(); channel_iter != channels_.end (); ++channel_iter) { QString label = channel_manager.getChannelLabel(*channel_iter); channel_list_widget_->addItem(QString("(%1) %2").arg (*channel_iter + 1) .arg(label)); } top_layout->addWidget (channel_list_widget_); QHBoxLayout* button_layout = new QHBoxLayout(this); button_layout->setMargin(10); button_layout->addStretch(1); ok_button_ = new QPushButton(tr("OK"), this); button_layout->addWidget(ok_button_); cancel_button_ = new QPushButton(tr("Cancel"), this); button_layout->addWidget(cancel_button_); button_layout->addStretch(1); top_layout->addLayout(button_layout); top_layout->activate(); connect(ok_button_, SIGNAL(clicked()), this, SLOT(accept())); connect(cancel_button_, SIGNAL(clicked()), this, SLOT(reject())); } //----------------------------------------------------------------------------- std::set SelectShownChannelsDialog::getSelectedChannels () const { QList find_list; std::set selected_channels; for (std::set::const_iterator channel_iter = channels_.begin(); channel_iter != channels_.end (); ++channel_iter) { find_list = channel_list_widget_ ->findItems(QString("(%1)").arg(*channel_iter + 1), Qt::MatchStartsWith); if (find_list.size() > 0 && channel_list_widget_->isItemSelected(find_list[0])) selected_channels.insert (*channel_iter); } return selected_channels; } } sigviewer-0.6.4/src/gui_impl/select_shown_channels_dialog.h000066400000000000000000000021261345753661000241740ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SELECT_SHOWN_CHANNELS_DIALOG_H #define SELECT_SHOWN_CHANNELS_DIALOG_H #include "base/sigviewer_user_types.h" #include "file_handling/channel_manager.h" #include #include class QListWidget; class QPushButton; namespace sigviewer { class SelectShownChannelsDialog : public QDialog { Q_OBJECT public: SelectShownChannelsDialog (QString const& dialog_title, std::set const& channels, ChannelManager const& channel_manager); std::set getSelectedChannels () const; private: SelectShownChannelsDialog (); SelectShownChannelsDialog (const SelectShownChannelsDialog&); const SelectShownChannelsDialog& operator= (const SelectShownChannelsDialog&); std::set channels_; QListWidget* channel_list_widget_; QPushButton* ok_button_; QPushButton* cancel_button_; }; } #endif // SELECT_SHOWN_CHANNELS_DIALOG_H sigviewer-0.6.4/src/gui_impl/signal_browser/000077500000000000000000000000001345753661000211535ustar00rootroot00000000000000sigviewer-0.6.4/src/gui_impl/signal_browser/adapt_browser_view_widget.cpp000066400000000000000000000246441345753661000271220ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "adapt_browser_view_widget.h" #include "gui/gui_action_factory.h" #include "base/exception.h" #include "base/math_utils.h" #include "gui_impl/gui_helper_functions.h" #include #include #include #include #include namespace sigviewer { //------------------------------------------------------------------------- AdaptBrowserViewWidget::AdaptBrowserViewWidget (SignalVisualisationView const* signal_visualisation_view, QSharedPointer setting, YAxisWidget *yAxisWidget, XAxisWidget *xAxisWidget, LabelWidget *labelWidget, QWidget *parent) : QWidget (parent), signal_visualisation_view_ (signal_visualisation_view), settings_ (setting), self_updating_ (false), updating_values_ (false), x_axis_widget_ (xAxisWidget), y_axis_widget_ (yAxisWidget), label_widget_ (labelWidget) { ui_.setupUi (this); if (!connect (ui_.x_axis_checkbox_, SIGNAL(toggled(bool)), SIGNAL(xAxisVisibilityChanged(bool)))) throw (Exception ("connect failed: x_axis_checkbox_")); if (!connect (ui_.y_axis_checkbox_, SIGNAL(toggled(bool)), SIGNAL(yAxisVisibilityChanged(bool)))) throw (Exception ("connect failed: y_axis_checkbox_")); if (!connect (ui_.labels_checkbox_, SIGNAL(toggled(bool)), SIGNAL(labelsVisibilityChanged(bool)))) throw (Exception ("connect failed: labels_checkbox_")); offset_centered_ = GuiActionFactory::getInstance()->getQAction("Zero Line Centered"); offset_fitted_ = GuiActionFactory::getInstance()->getQAction("Zero Line Fitted"); ui_.channelsPerPageSpinbox->setMaximum (setting->getChannelManager().getNumberChannels()); ui_.secsPerPageSpinbox->setMaximum (settings_->getChannelManager().getDurationInSec()); connect(ui_.offsetCheckBox, SIGNAL(stateChanged(int)), SLOT(on_offsetCheckBox_stateChanged(int))); connect (settings_.data(), SIGNAL(channelHeightChanged()), SLOT(updateValues())); connect (settings_.data(), SIGNAL(gridFragmentationChanged()), SLOT(updateValues())); connect (settings_.data(), SIGNAL(pixelsPerSampleChanged()), SLOT(updateValues())); QSettings settings; settings.beginGroup("SignalBrowserModel"); ui_.xGridCheckbox->setChecked(settings.value("show_x_grid", false).toBool()); ui_.yGridCheckbox->setChecked(settings.value("show_y_grid", false).toBool()); ui_.border_checkBox_->setChecked(settings.value("show_separator", false).toBool()); settings.endGroup(); y_axis_widget_->enableSeparator(ui_.border_checkBox_->checkState()); label_widget_->enableSeparator(ui_.border_checkBox_->checkState()); settings_->separatorEnabled(ui_.border_checkBox_->checkState()); //Zero line fitted mode should always be default ui_.offsetCheckBox->setChecked(true); ui_.yGridSlider->setToolTip("Slide to change the density of Y grids"); ui_.colors_groupbox->hide(); //currently the color button is immature, hide it temporarily ui_.color_checkBox->hide(); } AdaptBrowserViewWidget::~AdaptBrowserViewWidget() { QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_x_grid", ui_.xGridCheckbox->checkState()); settings.setValue("show_y_grid", ui_.yGridCheckbox->checkState()); settings.setValue("show_separator", ui_.border_checkBox_->checkState()); settings.endGroup(); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::showEvent (QShowEvent*) { updateValues (); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::on_channelOverlappingSlider_valueChanged (int value) { if (updating_values_) return; settings_->setChannelOverlapping (static_cast(value) / 100.0); if (value > 0) ui_.border_checkBox_->setEnabled(false); else ui_.border_checkBox_->setEnabled(true); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::on_yGridSlider_valueChanged (int value) { if (updating_values_) return; settings_->setGridFragmentation (Qt::Vertical, value); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::on_channelsPerPageSpinbox_valueChanged (int value) { if (updating_values_) return; self_updating_ = true; int new_channel_height = round(signal_visualisation_view_->getViewportHeight() / (double)value); GuiHelper::animateProperty (settings_.data(), "channelHeight", settings_->getChannelHeight(), new_channel_height, this, SLOT(selfUpdatingFinished())); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::on_secsPerPageSpinbox_valueChanged (double value) { if (updating_values_) return; self_updating_ = true; float new_pixels_per_sample = signal_visualisation_view_->getViewportWidth() / (value * settings_->getChannelManager().getSampleRate()); GuiHelper::animateProperty (settings_.data(), "pixelsPerSample", settings_->getPixelsPerSample(), new_pixels_per_sample, this, SLOT(selfUpdatingFinished())); } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::updateValues () { if ((!isVisible()) || self_updating_) return; updating_values_ = true; ui_.x_axis_checkbox_->setChecked (signal_visualisation_view_->getXAxisVisibility ()); ui_.y_axis_checkbox_->setChecked (signal_visualisation_view_->getYAxisVisibility ()); ui_.labels_checkbox_->setChecked (signal_visualisation_view_->getLabelsVisibility ()); ui_.yGridSlider->setValue (settings_->getGridFragmentation(Qt::Vertical)); //ui_.xGridSlider->setValue (settings_->getGridFragmentation(Qt::Horizontal)); ui_.channelsPerPageSpinbox->setValue (round(signal_visualisation_view_->getViewportHeight() / (double)settings_->getChannelHeight())); ui_.secsPerPageSpinbox->setValue ((signal_visualisation_view_->getViewportWidth() / settings_->getPixelsPerSample()) / settings_->getChannelManager().getSampleRate()); updating_values_ = false; } //------------------------------------------------------------------------- void AdaptBrowserViewWidget::selfUpdatingFinished () { self_updating_ = false; } } void sigviewer::AdaptBrowserViewWidget::on_offsetCheckBox_stateChanged(int checkState) { if (checkState == Qt::Unchecked) { offset_centered_->activate(QAction::Trigger); } else if (checkState == Qt::Checked) { offset_fitted_->activate(QAction::Trigger); } } void sigviewer::AdaptBrowserViewWidget::on_xGridCheckbox_stateChanged(int checkState) { if (checkState == Qt::Unchecked) //cancel X Grid { emit settings_->enableXGrid(false); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_x_grid", ui_.xGridCheckbox->checkState()); settings.endGroup(); } else if (checkState == Qt::Checked) { emit settings_->enableXGrid(true); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_x_grid", ui_.xGridCheckbox->checkState()); settings.endGroup(); } } void sigviewer::AdaptBrowserViewWidget::on_yGridCheckbox_stateChanged(int checkState) { if (checkState == Qt::Unchecked) //cancel Y Grid { ui_.yGridSlider->setDisabled(true); emit settings_->enableYGrid(false); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_y_grid", ui_.yGridCheckbox->checkState()); settings.endGroup(); } else if (checkState == Qt::Checked) { ui_.yGridSlider->setEnabled(true); emit settings_->enableYGrid(true); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_y_grid", ui_.yGridCheckbox->checkState()); settings.endGroup(); } } void sigviewer::AdaptBrowserViewWidget::on_border_checkBox__stateChanged(int checkState) { if (checkState == Qt::Unchecked) //cancel borders { y_axis_widget_->enableSeparator(false); label_widget_->enableSeparator(false); emit settings_->separatorEnabled(false); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_separator", ui_.border_checkBox_->checkState()); settings.endGroup(); } else if (checkState == Qt::Checked) { y_axis_widget_->enableSeparator(true); label_widget_->enableSeparator(true); emit settings_->separatorEnabled(true); QSettings settings; settings.beginGroup("SignalBrowserModel"); settings.setValue("show_separator", ui_.border_checkBox_->checkState()); settings.endGroup(); } } void sigviewer::AdaptBrowserViewWidget::on_grid_color_button_clicked() { QColorDialog colorPicker; colorPicker.setOption(QColorDialog::ShowAlphaChannel); if (colorPicker.exec() == QDialog::Accepted) { QColor gridColor = colorPicker.selectedColor(); emit settings_->gridColorChanged(gridColor); } } void sigviewer::AdaptBrowserViewWidget::on_label_color_button_clicked() { QColorDialog colorPicker; colorPicker.setOption(QColorDialog::ShowAlphaChannel); if (colorPicker.exec() == QDialog::Accepted) { QColor labelColor = colorPicker.selectedColor(); y_axis_widget_->changeLabelColor(labelColor); label_widget_->changeLabelColor(labelColor); x_axis_widget_->changeLabelColor(labelColor); emit settings_->labelColorChanged(labelColor); } } void sigviewer::AdaptBrowserViewWidget::on_color_checkBox_stateChanged(int checkState) { if (checkState == Qt::Checked) { ui_.colors_groupbox->show(); } else { ui_.colors_groupbox->hide(); } } sigviewer-0.6.4/src/gui_impl/signal_browser/adapt_browser_view_widget.h000066400000000000000000000072071345753661000265630ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef ADAPT_BROWSER_VIEW_WIDGET_H #define ADAPT_BROWSER_VIEW_WIDGET_H #include "gui/signal_visualisation_view.h" #include "gui/signal_view_settings.h" #include "ui_adapt_browser_view_widget.h" #include "y_axis_widget_4.h" #include "x_axis_widget_4.h" #include "label_widget.h" #include "gui/signal_visualisation_model.h" #include #include namespace sigviewer { //------------------------------------------------------------------------- class AdaptBrowserViewWidget : public QWidget { Q_OBJECT public: //------------------------------------------------------------------------- explicit AdaptBrowserViewWidget (SignalVisualisationView const* signal_visualisation_view, QSharedPointer settings_, YAxisWidget* yAxisWidget, XAxisWidget* xAxisWidget, LabelWidget* labelWidget, QWidget *parent = 0); ~AdaptBrowserViewWidget(); double getSecsPerPage() {return ui_.secsPerPageSpinbox->value();} signals: //------------------------------------------------------------------------- void xAxisVisibilityChanged (bool visible); //------------------------------------------------------------------------- void yAxisVisibilityChanged (bool visible); //------------------------------------------------------------------------- void labelsVisibilityChanged (bool visible); private slots: //------------------------------------------------------------------------- void on_channelOverlappingSlider_valueChanged (int value); //------------------------------------------------------------------------- void on_yGridSlider_valueChanged (int value); //------------------------------------------------------------------------- void on_channelsPerPageSpinbox_valueChanged (int value); //------------------------------------------------------------------------- void on_secsPerPageSpinbox_valueChanged (double value); //------------------------------------------------------------------------- void updateValues (); //------------------------------------------------------------------------- void selfUpdatingFinished (); //------------------------------------------------------------------------- void on_xGridCheckbox_stateChanged(int checkState); //------------------------------------------------------------------------- void on_yGridCheckbox_stateChanged(int checkState); //------------------------------------------------------------------------- void on_offsetCheckBox_stateChanged(int checkState); //------------------------------------------------------------------------- void on_border_checkBox__stateChanged(int checkState); void on_grid_color_button_clicked(); void on_label_color_button_clicked(); void on_color_checkBox_stateChanged(int checkState); private: //------------------------------------------------------------------------- virtual void showEvent (QShowEvent* event); SignalVisualisationView const* signal_visualisation_view_; QSharedPointer settings_; Ui::AdaptBrowserViewWidget ui_; bool self_updating_; bool updating_values_; QAction* offset_centered_; QAction* offset_fitted_; XAxisWidget* x_axis_widget_; YAxisWidget* y_axis_widget_; LabelWidget* label_widget_; }; } #endif // ADAPT_BROWSER_VIEW_WIDGET_H sigviewer-0.6.4/src/gui_impl/signal_browser/adapt_browser_view_widget.ui000066400000000000000000000171371345753661000267540ustar00rootroot00000000000000 AdaptBrowserViewWidget 0 0 1068 125 0 0 Form Grids true X-Grid true true 0 0 Y-Grid true 30 1 Qt::Horizontal false QSlider::NoTicks Colors 0 0 Grid Color Label Color Options X-Axis true Channels true Y-Axis true Color Setting Page Settings Channels: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Seconds: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 1 0.100000000000000 Channel Settings Auto-Centering true Separators Overlap 100 Qt::Horizontal sigviewer-0.6.4/src/gui_impl/signal_browser/event_context_menu.cpp000066400000000000000000000130401345753661000255660ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_context_menu.h" #include "signal_browser_model_4.h" #include "gui/gui_action_factory.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- EventContextMenu::EventContextMenu (SignalVisualisationModel& browser_model, QSharedPointer event_manager) : browser_model_ (browser_model), event_manager_ (event_manager) { // nothing to do here } //----------------------------------------------------------------------------- EventContextMenu::~EventContextMenu () { } //------------------------------------------------------------------------- void EventContextMenu::addEvent (EventID event) { QVector::iterator it = sub_menus_.begin(); while (it != sub_menus_.end()) { (*it)->clear(); delete (*it); ++it; } sub_menus_.clear(); clear(); QObject::disconnect(this, 0); event_ids_.append (event); } //------------------------------------------------------------------------- unsigned EventContextMenu::getNumberOfEvents () const { return event_ids_.size(); } //------------------------------------------------------------------------- void EventContextMenu::finaliseAndShowContextMenu (QGraphicsSceneContextMenuEvent* context_event, QMenu* channel_menu) { QVector::iterator it = event_ids_.begin(); if (event_ids_.size() > 1) { while (it != event_ids_.end()) { QString text (event_manager_->getNameOfEvent(*it)); QMenu* submenu = new QMenu (text); sub_menus_.append(submenu); // context-menu actions addActionsToMenu (*submenu, *it); QAction* action = addMenu (submenu); action->activate(QAction::Hover); action->setData(*it); addAction(action); ++it; } } else if (event_ids_.size() == 1) { QAction* title = addAction (event_manager_->getNameOfEvent(*it)); title->setEnabled (false); addActionsToMenu (*this, *(event_ids_.begin ())); browser_model_.selectEvent (*it); } event_ids_.clear(); QObject::connect(this, SIGNAL(hovered(QAction*)), this, SLOT(selectEvent(QAction*))); if (channel_menu) { addSeparator (); addMenu (channel_menu); } exec (context_event->screenPos()); } //------------------------------------------------------------------------- void EventContextMenu::finaliseAndShowSelectionMenu (QGraphicsSceneMouseEvent* event) { QVector::iterator it = event_ids_.begin(); if (event_ids_.size() > 1) { while (it != event_ids_.end()) { QString text (event_manager_->getNameOfEvent (*it)); QAction* action = addAction(text); //action->activate(QAction::Hover); action->setData(*it); //addAction(action); ++it; } QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(selectEvent(QAction*))); exec (event->screenPos()); } else if (event_ids_.size() == 1) { browser_model_.selectEvent (*it); } event_ids_.clear(); } //------------------------------------------------------------------------- void EventContextMenu::selectEvent (QAction* q) { bool ok = false; int32 event_id = q->data().toInt(&ok); if (q->data().isValid()) browser_model_.selectEvent (event_id); } //------------------------------------------------------------------------- void EventContextMenu::addActionsToMenu (QMenu& menu, EventID event) { QList actions; if (event_manager_->getEvent(event)->getChannel() != UNDEFINED_CHANNEL) { actions.append (GuiActionFactory::getInstance()->getQAction("To all Channels")); actions.append (GuiActionFactory::getInstance()->getQAction("Copy to Channels...")); } actions.append (GuiActionFactory::getInstance()->getQAction("Delete")); actions.append (GuiActionFactory::getInstance()->getQAction("Change Channel...")); actions.append (GuiActionFactory::getInstance()->getQAction("Change Type...")); actions.append (new QAction (this)); actions.last()->setSeparator(true); actions.append (GuiActionFactory::getInstance()->getQAction("Insert Over")); actions.append (new QAction (this)); actions.last()->setSeparator(true); if (event_manager_->getNextEventOfSameType (event) != UNDEFINED_EVENT_ID) actions.append (GuiActionFactory::getInstance()->getQAction("Goto and Select Next Event")); if (event_manager_->getPreviousEventOfSameType (event) != UNDEFINED_EVENT_ID) actions.append (GuiActionFactory::getInstance()->getQAction("Goto and Select Previous Event")); if (!actions.last()->isSeparator()) { actions.append (new QAction (this)); actions.last()->setSeparator(true); } if (browser_model_.getShownEventTypes().size() > 1) actions.append (GuiActionFactory::getInstance()->getQAction("Hide Events of other Type")); else actions.append (GuiActionFactory::getInstance()->getQAction("Show all Events")); actions.append (GuiActionFactory::getInstance()->getQAction("Fit View to Selected Event")); foreach (QAction* action, actions) menu.addAction (action); } } sigviewer-0.6.4/src/gui_impl/signal_browser/event_context_menu.h000066400000000000000000000045571345753661000252500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_CONTEXT_MENU_H #define EVENT_CONTEXT_MENU_H #include "event_graphics_item.h" #include "file_handling/event_manager.h" #include "gui/signal_visualisation_model.h" #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// /// EventContextMenu /// /// enables editing of events... allows selection of events class EventContextMenu : public QMenu { Q_OBJECT public: //------------------------------------------------------------------------- EventContextMenu (SignalVisualisationModel& browser_model, QSharedPointer event_manager); //------------------------------------------------------------------------- virtual ~EventContextMenu (); //------------------------------------------------------------------------- void addEvent (EventID event); //------------------------------------------------------------------------- unsigned getNumberOfEvents () const; //------------------------------------------------------------------------- void finaliseAndShowContextMenu (QGraphicsSceneContextMenuEvent* context_event, QMenu* channel_menu = 0); //------------------------------------------------------------------------- void finaliseAndShowSelectionMenu (QGraphicsSceneMouseEvent* context_event); private: //------------------------------------------------------------------------- void addActionsToMenu (QMenu& menu, EventID event); QVector event_ids_; QVector sub_menus_; SignalVisualisationModel& browser_model_; QSharedPointer event_manager_; //------------------------------------------------------------------------- /// copy-constructor disabled EventContextMenu (EventContextMenu const &); //------------------------------------------------------------------------- /// assignment-operator disabled EventContextMenu& operator= (EventContextMenu const &); //signals: // void hovered (QAction* q); public slots: void selectEvent (QAction* q); }; } #endif // EVENT_CONTEXT_MENU_H sigviewer-0.6.4/src/gui_impl/signal_browser/event_creation_widget.cpp000066400000000000000000000105431345753661000262320ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_creation_widget.h" #include "file_handling_impl/xdf_reader.h" #include "event_editing_widget.h" //to sync the event type combobox #include namespace sigviewer { //----------------------------------------------------------------------------- EventCreationWidget::EventCreationWidget (QSharedPointer signal_visualisation_model, QSharedPointer event_manager, QWidget* parent) : QWidget(parent), signal_visualisation_model_ (signal_visualisation_model), event_manager_ (event_manager), self_updating_ (false) { ui_.setupUi (this); if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { ui_.lineEdit->setPlaceholderText("Customize Event Text"); customized_event_id_ = XDFdata->dictionary.size(); ui_.groupBox->setToolTip("Select or customize an event type then click anywhere on the signals to create new events"); } else //custom event seems doesn't work in files other than XDF { ui_.lineEdit->hide(); ui_.pushButton->hide(); ui_.groupBox->setToolTip("Select an event type then click anywhere on the signals to create new events"); } } //----------------------------------------------------------------------------- int EventCreationWidget::insertNewEventType() { if (ui_.lineEdit->text().compare("")) { //avoid same types being repeated for (int i = 0; i < ui_.type_combobox_->count(); i++) { if (ui_.lineEdit->text().compare(ui_.type_combobox_->itemText(i), Qt::CaseSensitive) == 0) { //if it already exists ui_.type_combobox_->setCurrentIndex (i); return 1; } } customized_text_ = ui_.lineEdit->text(); event_manager_->setEventName(customized_event_id_, customized_text_); ui_.type_combobox_->removeItem(customized_event_id_); ui_.type_combobox_->insertItem(customized_event_id_, customized_text_, QVariant (customized_event_id_)); ui_.type_combobox_->setCurrentIndex(customized_event_id_); customized_event_id_++; if (customized_event_id_ >= 254) //Sigviewer has only 255 slots for custom events customized_event_id_ = XDFdata->dictionary.size(); emit newEventType(event_manager_->getEventTypes()); } return 0; } //----------------------------------------------------------------------------- void EventCreationWidget::updateShownEventTypes (std::set const& shown_event_types) { setSelfUpdating (true); ui_.type_combobox_->clear (); int current_index = 0; foreach (EventType type, shown_event_types) { ui_.type_combobox_->addItem (event_manager_->getNameOfEventType (type), QVariant (type)); if (type == signal_visualisation_model_->getActualEventCreationType()) current_index = ui_.type_combobox_->count() - 1; } ui_.type_combobox_->setCurrentIndex (current_index); setSelfUpdating (false); } //----------------------------------------------------------------------------- void EventCreationWidget::on_type_combobox__currentIndexChanged (int combo_box_index) { if (isSelfUpdating ()) return; EventType event_type = ui_.type_combobox_->itemData(combo_box_index).toUInt(); signal_visualisation_model_->setActualEventCreationType (event_type); } //------------------------------------------------------------------- void EventCreationWidget::setSelfUpdating (bool self_updating) { QMutexLocker locker (&self_updating_mutex_); self_updating_ = self_updating; } //------------------------------------------------------------------- bool EventCreationWidget::isSelfUpdating () { QMutexLocker locker (&self_updating_mutex_); return self_updating_; } //------------------------------------------------------------------- void EventCreationWidget::on_pushButton_clicked() { insertNewEventType(); } //------------------------------------------------------------------- void EventCreationWidget::on_lineEdit_returnPressed() //same as push button clicked { insertNewEventType(); } } sigviewer-0.6.4/src/gui_impl/signal_browser/event_creation_widget.h000066400000000000000000000031151345753661000256740ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_CREATION_WIDGET_H #define EVENT_CREATION_WIDGET_H #include "base/sigviewer_user_types.h" #include "ui_event_creation_widget.h" #include "gui/signal_visualisation_model.h" #include "file_handling/event_manager.h" #include #include #include namespace sigviewer { class EventCreationWidget : public QWidget { Q_OBJECT public: explicit EventCreationWidget (QSharedPointer signal_visualisation_model, QSharedPointer event_manager, QWidget* parent = 0); //! When user customizes the event text, add the new event type to the combobox int insertNewEventType (); signals: //! User added new event type void newEventType(std::set); public slots: void updateShownEventTypes (std::set const& shown_event_types); private slots: void on_type_combobox__currentIndexChanged (int combo_box_index); void on_pushButton_clicked(); void on_lineEdit_returnPressed(); private: void setSelfUpdating (bool self_updating); bool isSelfUpdating (); QSharedPointer signal_visualisation_model_; QSharedPointer event_manager_; QMutex self_updating_mutex_; bool self_updating_; Ui::EventCreationWidget ui_; QString customized_text_; int customized_event_id_; }; } #endif // EVENT_CREATION_WIDGET_H sigviewer-0.6.4/src/gui_impl/signal_browser/event_creation_widget.ui000066400000000000000000000021741345753661000260660ustar00rootroot00000000000000 EventCreationWidget 0 0 679 119 Form Select Event Type Customize Event Type sigviewer-0.6.4/src/gui_impl/signal_browser/event_editing_widget.cpp000066400000000000000000000201701345753661000260460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_editing_widget.h" #include "gui/gui_action_factory.h" #include "editing_commands/change_type_undo_command.h" #include "editing_commands/resize_event_undo_command.h" #include "base/math_utils.h" #include "file_handling_impl/xdf_reader.h" #include #include namespace sigviewer { //----------------------------------------------------------------------------- EventEditingWidget::EventEditingWidget (QSharedPointer event_manager, QSharedPointer command_executer, QWidget *parent) : QWidget(parent), event_manager_ (event_manager), command_executer_ (command_executer), self_updating_ (false) { ui_.setupUi (this); ui_.previous_button_->setDefaultAction (GuiActionFactory::getInstance()->getQAction("Goto and Select Previous Event")); ui_.next_button_->setDefaultAction (GuiActionFactory::getInstance()->getQAction("Goto and Select Next Event")); ui_.fit_button_->setDefaultAction (GuiActionFactory::getInstance()->getQAction("Fit View to Selected Event")); unsigned precision = MathUtils_::sampleRateToDecimalPrecision(event_manager_->getSampleRate()); ui_.begin_spinbox_->setDecimals (precision); ui_.begin_spinbox_->setMaximum (static_cast(event_manager_->getMaxEventPosition()) / event_manager_->getSampleRate ()); ui_.duration_spinbox_->setDecimals (precision); ui_.label->hide(); ui_.label_2->hide(); if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { ui_.groupBox->setDisabled(true); ui_.groupBox_2->setDisabled(true); ui_.groupBox_3->setDisabled(true); ui_.fit_button_->hide(); //Fit button doesn't work in XDF file since XDF events has no durations ui_.groupBox->setToolTip(tr("Editing events is not allowed in XDF files")); ui_.groupBox_2->setToolTip(tr("Editing events is not allowed in XDF files")); ui_.groupBox_3->setToolTip(tr("Editing events is not allowed in XDF files")); } else { ui_.groupBox->setToolTip(tr("Click on any event block on the signals first then edit its type")); ui_.groupBox_2->setToolTip(tr("Click on any event block on the signals first then edit its starting position")); ui_.groupBox_3->setToolTip(tr("Click on any event block on the signals first then edit its duration")); } } //----------------------------------------------------------------------------- void EventEditingWidget::updateShownEventTypes (std::set const& shown_event_types) { setSelfUpdating (true); ui_.type_combobox_->clear (); foreach (EventType type, shown_event_types) ui_.type_combobox_->addItem (event_manager_->getNameOfEventType (type), QVariant (type)); setSelfUpdating (false); } //----------------------------------------------------------------------------- void EventEditingWidget::updateSelectedEventInfo (QSharedPointer selected_signal_event) { setSelfUpdating (true); selected_signal_event_ = selected_signal_event; if (selected_signal_event_.isNull()) ui_.selection_frame_->setDisabled (true); else if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { ui_.selection_frame_->setDisabled(true);//Editing events are not allowed in XDF files ui_.selection_frame_->setToolTip("Editing events are not allowed in XDF files"); } else { ui_.selection_frame_->setEnabled (true); ui_.type_combobox_->setCurrentIndex (ui_.type_combobox_->findData (QVariant(selected_signal_event_->getType()))); ui_.duration_spinbox_->setValue (selected_signal_event_->getDurationInSec ()); ui_.duration_spinbox_->setMaximum (static_cast(event_manager_->getMaxEventPosition () - selected_signal_event->getPosition()) / event_manager_->getSampleRate ()); ui_.begin_spinbox_->setValue (selected_signal_event_->getPositionInSec ()); bool has_no_previous_event = event_manager_->getPreviousEventOfSameType (selected_signal_event->getId ()) == UNDEFINED_EVENT_ID; bool has_no_next_event = event_manager_->getNextEventOfSameType (selected_signal_event->getId ()) == UNDEFINED_EVENT_ID; ui_.next_button_->setDisabled (has_no_next_event); ui_.previous_button_->setDisabled (has_no_previous_event); } setSelfUpdating (false); } //------------------------------------------------------------------- void EventEditingWidget::on_type_combobox__currentIndexChanged (int combo_box_index) { if (isSelfUpdating() || selected_signal_event_.isNull ()) return; EventType event_type = ui_.type_combobox_->itemData(combo_box_index).toUInt(); if (event_type != selected_signal_event_->getType()) { ChangeTypeUndoCommand* change_type_command = new ChangeTypeUndoCommand (event_manager_, selected_signal_event_->getId(), event_type); command_executer_->executeCommand (change_type_command); //keep up with XDF customized events if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { if (selected_signal_event_->getStream() == XDFdata->userAddedStream) { int index = selected_signal_event_->getId() - XDFdata->eventType.size(); XDFdata->userCreatedEvents[index].first = event_manager_->getNameOfEventType(event_type).toStdString(); } } } } //------------------------------------------------------------------- void EventEditingWidget::on_begin_spinbox__editingFinished () { if (isSelfUpdating () || selected_signal_event_.isNull()) return; unsigned new_begin = ui_.begin_spinbox_->value() * event_manager_->getSampleRate (); ResizeEventUndoCommand* resize_command = new ResizeEventUndoCommand (event_manager_, selected_signal_event_->getId(), new_begin, selected_signal_event_->getDuration()); command_executer_->executeCommand (resize_command); //keep up with XDF customized events if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { if (selected_signal_event_->getStream() == XDFdata->userAddedStream) { int index = selected_signal_event_->getId() - XDFdata->eventType.size(); XDFdata->userCreatedEvents[index].second = event_manager_->getEvent(selected_signal_event_->getId())->getPositionInSec() + XDFdata->minTS; } } } //------------------------------------------------------------------- void EventEditingWidget::on_duration_spinbox__editingFinished () { if (isSelfUpdating () || selected_signal_event_.isNull()) return; unsigned new_duration = ui_.duration_spinbox_->value() * event_manager_->getSampleRate (); ResizeEventUndoCommand* resize_command = new ResizeEventUndoCommand (event_manager_, selected_signal_event_->getId(), selected_signal_event_->getPosition(), new_duration); command_executer_->executeCommand (resize_command); } //------------------------------------------------------------------- void EventEditingWidget::setSelfUpdating (bool self_updating) { QMutexLocker locker (&self_updating_mutex_); self_updating_ = self_updating; } //------------------------------------------------------------------- bool EventEditingWidget::isSelfUpdating () { QMutexLocker locker (&self_updating_mutex_); return self_updating_; } } sigviewer-0.6.4/src/gui_impl/signal_browser/event_editing_widget.h000066400000000000000000000031121345753661000255100ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_EDITING_WIDGET_H #define EVENT_EDITING_WIDGET_H #include "base/sigviewer_user_types.h" #include "file_handling/event_manager.h" #include "command_executer.h" #include "ui_event_editing_widget.h" //#include "gui_impl\signal_browser\event_creation_widget.h" #include #include #include namespace sigviewer { class EventEditingWidget : public QWidget { Q_OBJECT // friend class EventCreationWidget; public: explicit EventEditingWidget (QSharedPointer event_manager, QSharedPointer command_executer, QWidget *parent = 0); signals: public slots: void updateShownEventTypes (std::set const& shown_event_types); void updateSelectedEventInfo (QSharedPointer selected_signal_event); private slots: void on_type_combobox__currentIndexChanged (int combo_box_index); void on_begin_spinbox__editingFinished (); void on_duration_spinbox__editingFinished (); private: void setSelfUpdating (bool self_updating); bool isSelfUpdating (); QSharedPointer event_manager_; QSharedPointer command_executer_; QSharedPointer selected_signal_event_; QMutex self_updating_mutex_; bool self_updating_; Ui::EventEditingWidget ui_; }; } #endif // EVENT_EDITING_WIDGET_H sigviewer-0.6.4/src/gui_impl/signal_browser/event_editing_widget.ui000066400000000000000000000123521345753661000257040ustar00rootroot00000000000000 EventEditingWidget true 0 0 1182 113 Form false QFrame::NoFrame 0 0 0 0 0 Begin Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Duration Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Edit Event Type 0 0 Begin s 0 0 Duration s 0 0 Actions 22 22 false 22 22 false 22 22 sigviewer-0.6.4/src/gui_impl/signal_browser/event_graphics_item.cpp000066400000000000000000000321201345753661000256740ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_graphics_item.h" #include "signal_browser_model_4.h" #include "editing_commands/resize_event_undo_command.h" #include "event_context_menu.h" #include "base/signal_event.h" #include "gui_impl/signal_browser_mouse_handling.h" #include #include #include #include #include #include #include #include #include #include namespace sigviewer { // move mouse range int EventGraphicsItem::move_mouse_range_ = 5; QMutex EventGraphicsItem::event_handling_mutex_; QMutex EventGraphicsItem::context_menu_mutex_; EventContextMenu* EventGraphicsItem::context_menu_ = 0; //----------------------------------------------------------------------------- EventGraphicsItem::EventGraphicsItem (SignalBrowserModel& model, QSharedPointer signal_view_settings, QSharedPointer signal_event, QSharedPointer event_manager, QSharedPointer command_executer, QSharedPointer color_manager) : signal_browser_model_ (model), signal_view_settings_ (signal_view_settings), event_manager_ (event_manager), command_executer_ (command_executer), state_ (STATE_NONE), is_selected_ (false), signal_event_ (signal_event), color_manager_ (color_manager) { // nothing to do here } //----------------------------------------------------------------------------- EventGraphicsItem::~EventGraphicsItem () { // nothing to do here } //----------------------------------------------------------------------------- int32 EventGraphicsItem ::getId() const { return signal_event_->getId(); } //----------------------------------------------------------------------------- void EventGraphicsItem::setSelected (bool selected) { state_ = STATE_NONE; is_selected_ = selected; if (scene ()) scene()->update(pos().x() - 5, pos().y() - 5, width_ + 10, height_ + 10); } //----------------------------------------------------------------------------- QSharedPointer EventGraphicsItem::getSignalEvent () const { return signal_event_; } //----------------------------------------------------------------------------- bool EventGraphicsItem::displayContextMenu (QGraphicsSceneContextMenuEvent* event, QMenu* channel_menu) { context_menu_mutex_.lock(); bool menu_shown = false; if (!context_menu_) menu_shown = false; else if (context_menu_->getNumberOfEvents()) { context_menu_->finaliseAndShowContextMenu (event, channel_menu); menu_shown = true; } context_menu_mutex_.unlock(); return menu_shown; } //----------------------------------------------------------------------------- bool EventGraphicsItem::displaySelectionMenu (QGraphicsSceneMouseEvent* event) { context_menu_mutex_.lock(); bool menu_shown = false; if (!context_menu_) { menu_shown = false; } else if (context_menu_->getNumberOfEvents()) { context_menu_->finaliseAndShowSelectionMenu(event); menu_shown = true; } context_menu_mutex_.unlock(); return menu_shown; } //----------------------------------------------------------------------------- void EventGraphicsItem::updateToSignalEvent () { float64 pixel_per_sample = signal_view_settings_->getPixelsPerSample(); QRectF old_rect; if (scene ()) old_rect = this->sceneBoundingRect(); width_ = pixel_per_sample * signal_event_->getDuration() + 0.5; if (width_ < 2) width_ = 2; int32 x_pos = pixel_per_sample * signal_event_->getPosition(); int32 y_pos = 0; if (signal_event_->getChannel() == UNDEFINED_CHANNEL) { height_ = (signal_view_settings_->getChannelHeight()) * signal_browser_model_.getShownChannels().size(); //if channels are overlapping, adapt the event rectangle accordingly if (signal_view_settings_->getChannelOverlapping()) { height_ = (height_ + (height_ * (signal_browser_model_.getShownChannels().size() - 1) * (1.0 - signal_view_settings_->getChannelOverlapping()))) / signal_browser_model_.getShownChannels().size(); } } else { height_ = signal_view_settings_->getChannelHeight(); y_pos = signal_browser_model_.getYPosOfChannel(signal_event_->getChannel()); } color_ = color_manager_->getEventColor(signal_event_->getType()); /// FIXXME: REMOVE MAGIC NUMBER setZValue (5 + signal_event_->getType() / 100000.0); setPos (x_pos, y_pos); if (scene()) scene()->update(old_rect); update (); } //----------------------------------------------------------------------------- QRectF EventGraphicsItem::boundingRect () const { return QRectF (0, 0, width_, height_); } //----------------------------------------------------------------------------- void EventGraphicsItem::paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget*) { QRect clip (option->exposedRect.toRect()); if (is_selected_) { painter->drawRect(boundingRect()); } painter->fillRect(clip, color_); } //----------------------------------------------------------------------------- void EventGraphicsItem::mousePressEvent (QGraphicsSceneMouseEvent * event) { event_handling_mutex_.lock(); if (state_ != STATE_NONE) { event_handling_mutex_.unlock(); return; } switch(getMousePressAction(event)) { case ACTION_NONE: event->ignore(); state_ = STATE_NONE; break; case ACTION_MOVE_BEGIN: state_ = STATE_MOVE_BEGIN; setCursor(QCursor(Qt::SizeHorCursor)); emit mouseMoving (true); break; case ACTION_MOVE_END: state_ = STATE_MOVE_END; setCursor(QCursor(Qt::SizeHorCursor)); emit mouseMoving (true); break; case ACTION_SELECT: { addContextMenuEntry (); event->ignore(); } break; default: break; } event_handling_mutex_.unlock(); } //----------------------------------------------------------------------------- void EventGraphicsItem::mouseMoveEvent (QGraphicsSceneMouseEvent* mouse_event) { float32 pixel_per_sample = signal_view_settings_->getPixelsPerSample(); int32 mouse_pos_rounded = 0.5 + (mouse_event->scenePos().x() / pixel_per_sample); mouse_pos_rounded *= pixel_per_sample; switch(state_) { case STATE_NONE: break; case STATE_MOVE_BEGIN: { int32 old_pos = pos().x(); int32 new_pos = mouse_pos_rounded; width_ = width_ - (new_pos - old_pos); if (width_ < 0) width_ = 0; setPos (new_pos, pos().y()); emit mouseAtSecond (static_cast(pos().x()) / (pixel_per_sample * event_manager_->getSampleRate())); } break; case STATE_MOVE_END: { int32 old_pos_end = pos().x() + width_; int32 diff = mouse_pos_rounded - old_pos_end; width_ = width_ + diff; if (width_ < 0) width_ = 0; if (diff > 0) scene()->update (pos().x() + width_ - diff - 10, pos().y(), diff + 20, height_); else scene()->update (pos().x() + width_ - 10, pos().y(), 20 - diff, height_); emit mouseAtSecond (static_cast(pos().x() + width_) / (pixel_per_sample * event_manager_->getSampleRate())); } break; default: break; } } //----------------------------------------------------------------------------- void EventGraphicsItem::mouseReleaseEvent (QGraphicsSceneMouseEvent*) { float32 pixel_per_sample = signal_view_settings_->getPixelsPerSample(); switch(state_) { case STATE_MOVE_BEGIN: { int32 sample_pos = (static_cast(pos().x()) / pixel_per_sample) + 0.5; int32 dur = (static_cast(width_) / pixel_per_sample) + 0.5; ResizeEventUndoCommand* command = new ResizeEventUndoCommand (event_manager_, signal_event_->getId(), sample_pos, dur); command_executer_->executeCommand (command); } break; case STATE_MOVE_END: { int32 dur = (static_cast(width_) / pixel_per_sample) + 0.5; ResizeEventUndoCommand* command = new ResizeEventUndoCommand (event_manager_, signal_event_->getId(), signal_event_->getPosition(), dur); command_executer_->executeCommand (command); } break; default: break; } setCursor(QCursor(Qt::ArrowCursor)); state_ = STATE_NONE; emit mouseMoving (false); } //----------------------------------------------------------------------------- void EventGraphicsItem::contextMenuEvent (QGraphicsSceneContextMenuEvent * event) { if (signal_browser_model_.getMode() != MODE_VIEW_OPTIONS) addContextMenuEntry (); event->ignore(); } //----------------------------------------------------------------------------- EventGraphicsItem::Action EventGraphicsItem::getMousePressAction(QGraphicsSceneMouseEvent* e) { EventGraphicsItem* old_selected_item = signal_browser_model_.getSelectedEventItem(); QPoint mouse_pos (e->scenePos().x(), e->scenePos().y()); SignalVisualisationMode mode = signal_browser_model_.getMode(); switch (SignalBrowserMouseHandling::getAction(e, mode)) { case SignalBrowserMouseHandling::SELECT_RESIZE_EVENT_ACTION: { // select event if (!old_selected_item) { return ACTION_SELECT; } QRectF old_rect = old_selected_item->sceneBoundingRect(); int32 tmp = std::min(static_cast(old_rect.width() / 2), move_mouse_range_); // move event end QRect move_end_rect(old_rect.right() - tmp, old_rect.top(), tmp + move_mouse_range_, old_rect.height()); if (signal_event_->getId() == old_selected_item->signal_event_->getId() && move_end_rect.contains(mouse_pos)) { return ACTION_MOVE_END; } // move event begin QRect move_begin_rect(old_rect.left() - move_mouse_range_, old_rect.top(), tmp + move_mouse_range_, old_rect.height()); if (signal_event_->getId() == old_selected_item->signal_event_->getId() && move_begin_rect.contains(mouse_pos)) { return ACTION_MOVE_BEGIN; } return ACTION_SELECT; } break; case SignalBrowserMouseHandling::SHIFT_EVENT_TO_CHANNEL_ACTION: if (this == old_selected_item && old_selected_item->boundingRect().contains(mouse_pos) && signal_event_->getChannel() != UNDEFINED_CHANNEL) { return ACTION_SHIFT_TO_CHANNEL; } break; case SignalBrowserMouseHandling::COPY_EVENT_TO_CHANNEL_ACTION: if (this == old_selected_item && old_selected_item->boundingRect().contains(mouse_pos) && signal_event_->getChannel() != UNDEFINED_CHANNEL) { return ACTION_COPY_SHIFT_TO_CHANNEL; } break; default: break; } return ACTION_NONE; } //----------------------------------------------------------------------------- void EventGraphicsItem::addContextMenuEntry () { context_menu_mutex_.lock(); if (!context_menu_) context_menu_ = new EventContextMenu (signal_browser_model_, event_manager_); else { if (context_menu_->getNumberOfEvents() == 0) { delete context_menu_; context_menu_ = new EventContextMenu (signal_browser_model_, event_manager_); } } context_menu_->addEvent(signal_event_->getId()); context_menu_mutex_.unlock(); } } sigviewer-0.6.4/src/gui_impl/signal_browser/event_graphics_item.h000066400000000000000000000066741345753661000253600ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_GRAPHICS_ITEM_H #define EVENT_GRAPHICS_ITEM_H #include "base/sigviewer_user_types.h" #include "base/signal_event.h" #include "command_executer.h" #include "file_handling/event_manager.h" #include "gui/color_manager.h" #include "gui/signal_view_settings.h" #include #include #include #include #include #include class QMutex; namespace sigviewer { class SignalBrowserModel; class EventContextMenu; class EventGraphicsItem : public QGraphicsObject { Q_OBJECT Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) #if QT_VERSION >= 0x040600 Q_INTERFACES(QGraphicsItem) #endif public: EventGraphicsItem(SignalBrowserModel& model, QSharedPointer signal_view_settings, QSharedPointer signal_event, QSharedPointer event_manager, QSharedPointer command_executer, QSharedPointer color_manager); virtual ~EventGraphicsItem (); int32 getId() const; void setSelected (bool selected); QSharedPointer getSignalEvent () const; static bool displayContextMenu (QGraphicsSceneContextMenuEvent* event, QMenu* channel_menu); static bool displaySelectionMenu (QGraphicsSceneMouseEvent* event); public slots: void updateToSignalEvent (); signals: void mouseAtSecond (float64 sec); void mouseMoving (bool mouse_is_moving); private: virtual QRectF boundingRect () const; virtual void mouseMoveEvent (QGraphicsSceneMouseEvent * mouse_event); virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event); enum Action { ACTION_NONE, ACTION_MOVE_BEGIN, ACTION_MOVE_END, ACTION_SHIFT_TO_CHANNEL, ACTION_COPY_SHIFT_TO_CHANNEL, ACTION_SELECT }; enum State { STATE_NONE, STATE_MOVE_BEGIN, STATE_MOVE_END, STATE_SHIFT_TO_CHANNEL }; //----------------------------------------------------------------------------- virtual void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); virtual void mousePressEvent ( QGraphicsSceneMouseEvent * event ); virtual void contextMenuEvent (QGraphicsSceneContextMenuEvent * event); //----------------------------------------------------------------------------- Action getMousePressAction(QGraphicsSceneMouseEvent* e); //----------------------------------------------------------------------------- void addContextMenuEntry (); SignalBrowserModel& signal_browser_model_; QSharedPointer signal_view_settings_; QSharedPointer event_manager_; QSharedPointer command_executer_; QColor color_; State state_; int32 height_; int32 width_; bool is_selected_; QSharedPointer signal_event_; QSharedPointer color_manager_; static int move_mouse_range_; static QMutex event_handling_mutex_; static QMutex context_menu_mutex_; static EventContextMenu* context_menu_; }; } #endif // EVENT_GRAPHICS_ITEM_H sigviewer-0.6.4/src/gui_impl/signal_browser/label_widget.cpp000066400000000000000000000112261345753661000243030ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "label_widget.h" #include "gui/gui_action_factory.h" namespace sigviewer { //----------------------------------------------------------------------------- LabelWidget::LabelWidget (QSharedPointer signal_view_settings) : signal_view_settings_ (signal_view_settings), y_start_ (0), enable_separator_ (true), label_color_ (Qt::black) { // nothing to do here } //----------------------------------------------------------------------------- void LabelWidget::changeYStart (int32 y_start) { y_start_ = y_start; update (); } //----------------------------------------------------------------------------- void LabelWidget::enableSeparator(bool enable) { enable_separator_ = enable; update(); } void LabelWidget::changeLabelColor(QColor labelColor) { label_color_ = labelColor; update(); } //----------------------------------------------------------------------------- void LabelWidget::paintEvent(QPaintEvent*) { bool channel_overlapping = signal_view_settings_->getChannelOverlapping(); float64 signal_height = signal_view_settings_->getChannelHeight(); if (channel_overlapping) signal_height = (signal_height + (signal_height * (channel_nr2label_.size() - 1) * (1.0 - signal_view_settings_->getChannelOverlapping()))) / channel_nr2label_.size(); int32 y_end = y_start_ + height(); if (signal_height < 1) return; QPainter painter(this); painter.translate(0, -y_start_); painter.setPen(label_color_); // painter.setPen(QColor(0, 43, 130)); // painter.drawLine(0, y_start_, 0, y_end); // painter.setPen(Qt::black); // labels float64 float_y_start = y_start_;//floor(static_cast(y_start) / intervall) * intervall; float64 float_y_end = y_end;//ceil(y_end / intervall) * intervall; QMap::iterator iter = channel_nr2label_.begin(); for (float32 float_y = signal_height / 2; float_y < float_y_end && iter != channel_nr2label_.end(); float_y += signal_height, iter++) { if (float_y > float_y_start) { int32 y = (int32)(float_y + 0.5); painter.drawText(5, (int32)(y - signal_height /2) , width() - 10, (int32)signal_height, Qt::AlignHCenter | Qt::AlignVCenter, iter.value()); } } if (channel_overlapping) return; if (enable_separator_) { for (float32 float_y = 0; float_y <= signal_height * channel_nr2label_.size(); float_y += signal_height) { painter.drawLine(0, float_y, width() - 1, float_y); } } } //----------------------------------------------------------------------------- void LabelWidget::contextMenuEvent (QContextMenuEvent* event) { QMenu menu; menu.addAction(GuiActionFactory::getInstance()->getQAction("Channels per Page...")); menu.addSeparator(); QAction* visibility_action = menu.addAction("Labels"); visibility_action->setCheckable (true); visibility_action->setChecked (true); connect (visibility_action, SIGNAL(triggered(bool)), SLOT(setVisible(bool))); menu.exec (event->globalPos()); } //----------------------------------------------------------------------------- void LabelWidget::addChannel(ChannelID channel_nr, const QString& label) { channel_nr2label_[channel_nr] = label; QPixmap dummy(1,1); QPainter painter(&dummy); QRect bounding = painter.boundingRect(0, 0, 500, 500, Qt::AlignHCenter | Qt::AlignVCenter, label); int32 max_width = minimumWidth() - 10; max_width = bounding.width() > max_width ? bounding.width() : max_width; setMinimumWidth(10 + max_width); } //----------------------------------------------------------------------------- void LabelWidget::removeChannel(ChannelID channel_nr) { channel_nr2label_.erase(channel_nr2label_.find(channel_nr)); int32 max_width = -1; QPixmap dummy(1,1); QPainter p(&dummy); for (QMap::iterator iter = channel_nr2label_.begin(); iter != channel_nr2label_.end(); iter++) { QRect bounding = p.boundingRect(0, 0, 200, p.font().pixelSize(), Qt::AlignHCenter | Qt::AlignVCenter, iter.value()); max_width = max_width < bounding.width() ? bounding.width() : max_width; } setMinimumWidth(10 + max_width); } } sigviewer-0.6.4/src/gui_impl/signal_browser/label_widget.h000066400000000000000000000022001345753661000237400ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef LABEL_WIDGET_H #define LABEL_WIDGET_H #include "base/sigviewer_user_types.h" #include "gui/signal_view_settings.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- class LabelWidget : public QWidget { Q_OBJECT public: LabelWidget (QSharedPointer signal_view_settings); void addChannel(ChannelID channel_nr, const QString& label); void removeChannel(ChannelID channel_nr); public slots: void changeYStart (int32 y_start); void enableSeparator(bool enable); void changeLabelColor(QColor labelColor); protected: void paintEvent(QPaintEvent* pe); virtual void contextMenuEvent (QContextMenuEvent* event); private: QSharedPointer signal_view_settings_; QMap channel_nr2label_; int32 y_start_; bool enable_separator_; QColor label_color_; }; } #endif sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser.pri000066400000000000000000000020141345753661000247040ustar00rootroot00000000000000HEADERS += \ $$PWD/adapt_browser_view_widget.h \ $$PWD/event_context_menu.h \ $$PWD/event_creation_widget.h \ $$PWD/event_editing_widget.h \ $$PWD/event_graphics_item.h \ $$PWD/label_widget.h \ $$PWD/signal_browser_graphics_view.h \ $$PWD/signal_browser_model_4.h \ $$PWD/signal_browser_view.h \ $$PWD/signal_graphics_item.h \ $$PWD/signal_grid_graphics_item.h \ $$PWD/x_axis_widget_4.h \ $$PWD/y_axis_widget_4.h SOURCES += \ $$PWD/adapt_browser_view_widget.cpp \ $$PWD/event_context_menu.cpp \ $$PWD/event_creation_widget.cpp \ $$PWD/event_editing_widget.cpp \ $$PWD/event_graphics_item.cpp \ $$PWD/label_widget.cpp \ $$PWD/signal_browser_model_4.cpp \ $$PWD/signal_browser_view.cpp \ $$PWD/signal_graphics_item.cpp \ $$PWD/signal_grid_graphics_item.cpp \ $$PWD/x_axis_widget_4.cpp \ $$PWD/y_axis_widget_4.cpp FORMS += \ $$PWD/adapt_browser_view_widget.ui \ $$PWD/event_creation_widget.ui \ $$PWD/event_editing_widget.ui sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser_graphics_view.h000066400000000000000000000015711345753661000272620ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_BROWSER_GRAPHICS_VIEW_H #define SIGNAL_BROWSER_GRAPHICS_VIEW_H #include #include #include namespace sigviewer { class SignalBrowserGraphicsView : public QGraphicsView { Q_OBJECT public: SignalBrowserGraphicsView (QGraphicsScene* scene, QWidget* parent = 0) : QGraphicsView (scene, parent) {} protected: virtual void resizeEvent (QResizeEvent* event) {emit resized (event);} //virtual void mouseMoveEvent (QMouseEvent* event) {this->moveEvent(event);}//event->ignore();}//emit sceneMouseMoved (mapToScene (event->pos()));} signals: void resized (QResizeEvent*); void sceneMouseMoved (QPointF scene_pos); }; } #endif // SIGNAL_BROWSER_GRAPHICS_VIEW_H sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser_model_4.cpp000066400000000000000000000434631345753661000263140ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_browser_model_4.h" #include "file_handling/event_manager.h" #include "file_handling/channel_manager.h" #include "signal_browser_view.h" #include "signal_graphics_item.h" #include "gui/color_manager.h" #include "gui/progress_bar.h" #include "base/signal_event.h" #include "base/math_utils.h" #include "gui_impl/gui_helper_functions.h" #include #include #include #include #include #include #include #include namespace sigviewer { namespace LayoutFunctions_ { unsigned getSceneHeight (unsigned num_channels, unsigned channel_height, float channel_overlapping) { if (num_channels == 0) return 0; return channel_height + (channel_height * (num_channels - 1) * (1.0 - channel_overlapping)); } } //----------------------------------------------------------------------------- SignalBrowserModel::SignalBrowserModel(QSharedPointer event_manager, ChannelManager const& channel_manager, QSharedPointer tab_context, QSharedPointer color_manager) : SignalVisualisationModel (std::set (), channel_manager), channel_manager_ (channel_manager), event_manager_ (event_manager), tab_context_ (tab_context), color_manager_ (color_manager), signal_browser_view_ (0), selected_event_item_ (0), x_grid_pixel_intervall_(0), initialized_ (false) { if (!event_manager_.isNull ()) { QList event_ids = event_manager_->getAllEvents(); if (id2event_item_.size() == 0) { for (QList::const_iterator event_id_iter = event_ids.begin (); event_id_iter != event_ids.end (); ++event_id_iter) { id2event_item_[*event_id_iter] = new EventGraphicsItem ( *this, getSignalViewSettings(), event_manager_->getEvent (*event_id_iter), event_manager_, tab_context_, color_manager_); } } } connect (getSignalViewSettings().data(), SIGNAL(pixelsPerSampleChanged()), SLOT(update())); connect (getSignalViewSettings().data(), SIGNAL(channelHeightChanged()), SLOT(update())); connect (getSignalViewSettings().data(), SIGNAL(channelOverlappingChanged()), SLOT(update())); } //----------------------------------------------------------------------------- SignalBrowserModel::~SignalBrowserModel() { } //----------------------------------------------------------------------------- SignalVisualisationView const* SignalBrowserModel::view () const { return signal_browser_view_; } //----------------------------------------------------------------------------- QMap SignalBrowserModel::getChannelToSignalItem() { return channel2signal_item_; } // set signal browser view----------------------------------------------------- void SignalBrowserModel::setSignalBrowserView (SignalBrowserView* signal_browser_view) { signal_browser_view_ = signal_browser_view; if (!event_manager_.isNull()) setShownEventTypes (event_manager_->getEventTypes()); } //----------------------------------------------------------------------------- void SignalBrowserModel::setShownChannels (std::set const& new_shown_channels) { unsigned new_channel_height = getSignalViewSettings()->getChannelHeight(); new_channel_height = signal_browser_view_->getViewportHeight() / new_shown_channels.size(); foreach (ChannelID channel, channel2signal_item_.keys()) if (new_shown_channels.count (channel) == 0) removeChannel (channel); getSignalViewSettings()->setChannelHeight (std::max(120, new_channel_height)); foreach (ChannelID channel, new_shown_channels) { ProgressBar::instance().increaseValue (1, tr("Creating view...")); if (channel2signal_item_.count (channel) == 0) addChannel (channel); } foreach (SignalGraphicsItem* channel, channel2signal_item_.values()) channel->autoScale (getAutoScaleMode()); if (!initialized_) goToSample (0); initialized_ = true; } //----------------------------------------------------------------------------- void SignalBrowserModel::addChannel (ChannelID channel_id) { SignalGraphicsItem* signal_item = new SignalGraphicsItem (getSignalViewSettings(), event_manager_, tab_context_, channel_manager_, color_manager_, channel_id, *this); signal_item->connect (getSignalViewSettings().data(), SIGNAL(channelHeightChanged(uint)), SLOT(setHeight(uint))); channel2signal_item_[channel_id] = signal_item; signal_browser_view_->addSignalGraphicsItem (channel_id, signal_item, channel_manager_.getChannelLabel(channel_id)); } //----------------------------------------------------------------------------- void SignalBrowserModel::removeChannel (ChannelID channel_id) { SignalGraphicsItemMap::iterator sig_iter; sig_iter = channel2signal_item_.find (channel_id); if (sig_iter == channel2signal_item_.end()) return; disconnect (sig_iter.value()); signal_browser_view_->removeSignalGraphicsItem (channel_id, sig_iter.value()); delete sig_iter.value(); channel2signal_item_.erase (sig_iter); } //----------------------------------------------------------------------------- std::set SignalBrowserModel::getShownChannels () const { std::set shown_channels; for (SignalGraphicsItemMap::const_iterator sig_iter = channel2signal_item_.begin(); sig_iter != channel2signal_item_.end(); ++sig_iter) { shown_channels.insert(sig_iter.key()); } return shown_channels; } //----------------------------------------------------------------------------- int32 SignalBrowserModel::getYPosOfChannel (uint32 channel_nr) const { Int2IntMap::const_iterator y_iter = channel2y_pos_.find(channel_nr); if (y_iter != channel2y_pos_.end()) return y_iter->second; else return 0; } //----------------------------------------------------------------------------- // zoom in all void SignalBrowserModel::zoomInAll() { SignalGraphicsItemMap::iterator iter; for (iter = channel2signal_item_.begin(); iter != channel2signal_item_.end(); iter++) { iter.value()->zoomIn(); } signal_browser_view_->updateWidgets(); } //----------------------------------------------------------------------------- // zoom out all void SignalBrowserModel::zoomOutAll() { SignalGraphicsItemMap::iterator iter; for (iter = channel2signal_item_.begin(); iter != channel2signal_item_.end(); iter++) { iter.value()->zoomOut(); } signal_browser_view_->updateWidgets(); } //----------------------------------------------------------------------------- void SignalBrowserModel::update() { int32 width = channel_manager_.getNumberSamples() * getSignalViewSettings()->getPixelsPerSample(); int32 height = LayoutFunctions_::getSceneHeight (channel2signal_item_.size(), getSignalViewSettings()->getChannelHeight(), getSignalViewSettings()->getChannelOverlapping()); signal_browser_view_->resizeScene (width, height); double pixel_per_sec = getSignalViewSettings()->getPixelsPerSample() * channel_manager_.getSampleRate(); x_grid_pixel_intervall_ = pixel_per_sec * MathUtils_::round125 (100.0 / pixel_per_sec); channel2y_pos_.clear(); channel2y_pos_[UNDEFINED_CHANNEL] = 0; int32 y_pos = 0; SignalGraphicsItemMap::iterator signal_iter; for (signal_iter = channel2signal_item_.begin(); signal_iter != channel2signal_item_.end(); signal_iter++, y_pos += getSignalViewSettings()->getChannelHeight() * (1.0 - getSignalViewSettings()->getChannelOverlapping())) { channel2y_pos_[signal_iter.key()] = y_pos; signal_iter.value()->setHeight (getSignalViewSettings()->getChannelHeight()); signal_iter.value()->setPos (0, y_pos); signal_iter.value()->setZValue(SIGNAL_Z); signal_iter.value()->updateYGridIntervall(); //// signal_iter.value()->enableYGrid(show_y_grid_); // signal_iter.value()->enableXGrid(show_x_grid_); signal_iter.value()->setXGridInterval (x_grid_pixel_intervall_); signal_iter.value()->show(); } updateEventItemsImpl (); signal_browser_view_->update(); signal_browser_view_->updateWidgets(); } //------------------------------------------------------------------------- void SignalBrowserModel::scaleChannel (ChannelID id, float32 lower_value, float32 upper_value) { if (id == UNDEFINED_CHANNEL) { QProgressDialog progress; progress.setMaximum (channel2signal_item_.size()); progress.setMinimum (0); progress.setModal (true); progress.setLabelText (tr("Scaling...")); progress.show (); for (SignalGraphicsItemMap::iterator it = channel2signal_item_.begin(); it != channel2signal_item_.end(); ++it) { it.value()->scale (lower_value, upper_value); progress.setValue (progress.value() + 1); } progress.setValue (progress.maximum ()); } else channel2signal_item_[id]->scale (lower_value, upper_value); } //------------------------------------------------------------------------- void SignalBrowserModel::scaleChannel (ChannelID id) { if (id == UNDEFINED_CHANNEL) { QProgressDialog progress; progress.setMaximum (channel2signal_item_.size()); progress.setMinimum (0); progress.setModal (true); progress.setLabelText (tr("Scaling...")); progress.show (); for (SignalGraphicsItemMap::iterator it = channel2signal_item_.begin(); it != channel2signal_item_.end(); ++it) { it.value()->autoScale (getAutoScaleMode()); progress.setValue (progress.value() + 1); } progress.setValue (progress.maximum ()); } else channel2signal_item_[id]->autoScale (getAutoScaleMode()); signal_browser_view_->updateWidgets(); } //------------------------------------------------------------------------- ChannelManager const& SignalBrowserModel::getChannelManager () const { return channel_manager_; } //------------------------------------------------------------------------- QSharedPointer SignalBrowserModel::getEventManager () const { return event_manager_; } //------------------------------------------------------------------------- QSharedPointer SignalBrowserModel::getEventManager () { return event_manager_; } //------------------------------------------------------------------------- unsigned SignalBrowserModel::getShownPosition () const { return signal_browser_view_->getVisibleX () / getSignalViewSettings()->getPixelsPerSample(); } //------------------------------------------------------------------------- void SignalBrowserModel::goToSample(unsigned sample) { float64 position = 0; while (position < getSignalViewSettings()->getPixelsPerSample() * sample) position += getSignalViewSettings()->getPixelsPerSample(); position -= getSignalViewSettings()->getPixelsPerSample(); signal_browser_view_->goTo (position); } //------------------------------------------------------------------------- QList SignalBrowserModel::getSelectedEvents () const { if (selected_event_item_) return QList () << selected_event_item_->getId (); else return QList (); } //------------------------------------------------------------------- void SignalBrowserModel::updateEventItems () { updateEventItemsImpl (); signal_browser_view_->update (); } //------------------------------------------------------------------- void SignalBrowserModel::selectEvent (EventID id) { Int2EventGraphicsItemPtrMap::iterator event_iter = id2event_item_.find (id); if (event_iter == id2event_item_.end()) { selected_event_item_ = 0; emit eventSelected (QSharedPointer(0)); tab_context_->setSelectionState(TAB_STATE_NO_EVENT_SELECTED); return; } EventGraphicsItem* item = event_iter->second; if (selected_event_item_) selected_event_item_->setSelected (false); selected_event_item_ = item; selected_event_item_->setSelected (true); emit eventSelected(item->getSignalEvent()); if (event_manager_->getEvent(id)->getChannel() == UNDEFINED_CHANNEL) tab_context_->setSelectionState(TAB_STATE_EVENT_SELECTED_ALL_CHANNELS); else tab_context_->setSelectionState (TAB_STATE_EVENT_SELECTED_ONE_CHANNEL); } //------------------------------------------------------------------- void SignalBrowserModel::unselectEvent () { tab_context_->setSelectionState (TAB_STATE_NO_EVENT_SELECTED); if (selected_event_item_) selected_event_item_->setSelected (false); selected_event_item_ = 0; emit eventSelected (QSharedPointer(0)); } //------------------------------------------------------------------- void SignalBrowserModel::shownEventTypesChangedImpl () { updateEventItemsImpl (); } //------------------------------------------------------------------- void SignalBrowserModel::modeChangedImpl (SignalVisualisationMode mode) { bool tooltips = (mode == MODE_INFO || mode == MODE_POINTER); foreach (SignalGraphicsItem* signal_item, channel2signal_item_.values()) signal_item->setAcceptHoverEvents (tooltips); } //----------------------------------------------------------------------------- void SignalBrowserModel::updateEventItemsImpl () { Int2EventGraphicsItemPtrMap::iterator event_iter; for (event_iter = id2event_item_.begin(); event_iter != id2event_item_.end(); event_iter++) { QSharedPointer event = event_manager_->getEvent(event_iter->first); if (!event) { continue; } Int2IntMap::iterator y_pos_iter; y_pos_iter = channel2y_pos_.find(event->getChannel()); std::set shown_event_types = getShownEventTypes (); if (!shown_event_types.count(event->getType()) || y_pos_iter == channel2y_pos_.end()) { event_iter->second->hide(); if (event_iter->second == selected_event_item_) { selected_event_item_->setSelected(false); selected_event_item_ = 0; tab_context_->setSelectionState (TAB_STATE_NO_EVENT_SELECTED); } } else { event_iter->second->updateToSignalEvent (); if (!(event_iter->second->scene())) signal_browser_view_->addEventGraphicsItem(event_iter->second); event_iter->second->show(); } } } //----------------------------------------------------------------------------- void SignalBrowserModel::addEventItem (QSharedPointer event) { EventGraphicsItem* event_item = new EventGraphicsItem( *this, getSignalViewSettings(), event, event_manager_, tab_context_, color_manager_); id2event_item_[event->getId()] = event_item; signal_browser_view_->addEventGraphicsItem(event_item); event_item->updateToSignalEvent(); event_item->show(); } //----------------------------------------------------------------------------- void SignalBrowserModel::removeEventItem (EventID id) { if (id2event_item_.find (id) == id2event_item_.end()) return; EventGraphicsItem* event_item = id2event_item_[id]; if (selected_event_item_ == event_item) unselectEvent (); id2event_item_.erase (id); items_to_delete_.push_back (event_item); GuiHelper::animateProperty (event_item, "opacity", 1.0, 0.0, this, SLOT(removeEventItemImpl())); } //----------------------------------------------------------------------------- void SignalBrowserModel::removeEventItemImpl () { EventGraphicsItem* event_item = items_to_delete_.front(); items_to_delete_.pop_front(); signal_browser_view_->removeEventGraphicsItem (event_item); delete event_item; } //----------------------------------------------------------------------------- // set event changed void SignalBrowserModel::updateEvent (EventID id) { if (id2event_item_.find (id) == id2event_item_.end()) return; EventGraphicsItem* event_item = id2event_item_[id]; event_item->updateToSignalEvent (); if (selected_event_item_) if (selected_event_item_->getId() == id) { if (selected_event_item_->getSignalEvent()->getChannel() == UNDEFINED_CHANNEL) tab_context_->setSelectionState (TAB_STATE_EVENT_SELECTED_ALL_CHANNELS); else tab_context_->setSelectionState (TAB_STATE_EVENT_SELECTED_ONE_CHANNEL); emit eventSelected (event_item->getSignalEvent()); } } //----------------------------------------------------------------------------- // get selected event item EventGraphicsItem* SignalBrowserModel::getSelectedEventItem() { return selected_event_item_; } } sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser_model_4.h000066400000000000000000000125461345753661000257570ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_BROWSER_MODEL_H_q4 #define SIGNAL_BROWSER_MODEL_H_q4 #include "tab_context.h" #include "file_handling/channel_manager.h" #include "file_handling/event_manager.h" #include "gui/signal_visualisation_modes.h" #include "gui/signal_visualisation_model.h" #include "gui/color_manager.h" #include "event_graphics_item.h" #include #include #include #include #include #include #include namespace sigviewer { class SignalBrowserView; class SignalGraphicsItem; //----------------------------------------------------------------------------- /// SignalBrowserModel class SignalBrowserModel : public SignalVisualisationModel { Q_OBJECT public: //------------------------------------------------------------------------- SignalBrowserModel(QSharedPointer event_manager, ChannelManager const& channel_manager, QSharedPointer tab_context, QSharedPointer color_manager); //------------------------------------------------------------------------- virtual ~SignalBrowserModel(); //------------------------------------------------------------------------- virtual void scaleChannel (ChannelID id, float32 lower_value, float32 upper_value); //------------------------------------------------------------------------- virtual void scaleChannel (ChannelID id); //------------------------------------------------------------------------- virtual ChannelManager const& getChannelManager () const; //------------------------------------------------------------------------- virtual QSharedPointer getEventManager () const; //------------------------------------------------------------------------- virtual QSharedPointer getEventManager (); //------------------------------------------------------------------------- /// see base class virtual unsigned getShownPosition () const; //------------------------------------------------------------------------- /// see base class virtual void goToSample (unsigned sample); //------------------------------------------------------------------------- /// see base class virtual QList getSelectedEvents () const; //------------------------------------------------------------------------- virtual SignalVisualisationView const* view () const; //------------------------------------------------------------------------- virtual QMap getChannelToSignalItem(); void setSignalBrowserView(SignalBrowserView* signal_browser_view); void loadSettings(); void saveSettings(); virtual void setShownChannels (std::set const& shown_channels); virtual std::set getShownChannels () const; int32 getYPosOfChannel (uint32 channel_nr) const; void zoomInAll(); void zoomOutAll(); EventGraphicsItem* getSelectedEventItem(); void updateEventItems (); public slots: //------------------------------------------------------------------------- virtual void update (); //------------------------------------------------------------------------- /// adds the given event virtual void addEventItem (QSharedPointer event); //------------------------------------------------------------------------- /// removes the given event virtual void removeEventItem (EventID id); void updateEvent (EventID id); virtual void selectEvent (EventID id); void unselectEvent (); signals: void eventSelected (QSharedPointer selected_event); protected: virtual void shownEventTypesChangedImpl (); virtual void modeChangedImpl (SignalVisualisationMode mode); private slots: //------------------------------------------------------------------------- /// implementation of removeEventItem which really deletes the item void removeEventItemImpl (); private: //------------------------------------------------------------------------- void addChannel (ChannelID channel_nr); //------------------------------------------------------------------------- void removeChannel (ChannelID channel_nr); //------------------------------------------------------------------------- void updateEventItemsImpl (); //------------------------------------------------------------------------- static uint8 const SIGNAL_Z = 4; ChannelManager const& channel_manager_; QSharedPointer event_manager_; QSharedPointer tab_context_; QSharedPointer color_manager_; SignalBrowserView* signal_browser_view_; typedef QMap SignalGraphicsItemMap; typedef std::map Int2EventGraphicsItemPtrMap; typedef std::map Int2IntMap; SignalGraphicsItemMap channel2signal_item_; Int2EventGraphicsItemPtrMap id2event_item_; Int2IntMap channel2y_pos_; EventGraphicsItem* selected_event_item_; float64 x_grid_pixel_intervall_; bool initialized_; QList items_to_delete_; }; } #endif sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser_view.cpp000066400000000000000000000444471345753661000257460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_browser_view.h" #include "signal_graphics_item.h" #include "event_graphics_item.h" #include "y_axis_widget_4.h" #include "x_axis_widget_4.h" #include "label_widget.h" #include "event_creation_widget.h" #include "event_editing_widget.h" #include "adapt_browser_view_widget.h" #include #include #include #include #include #include #include #include #include #include /* round */ namespace sigviewer { //----------------------------------------------------------------------------- // constructor SignalBrowserView::SignalBrowserView (QSharedPointer signal_browser_model, QSharedPointer event_manager, QSharedPointer command_executer, QRect const& initial_size, QWidget* parent) : QFrame (parent), model_ (signal_browser_model), empty_widget_ (new QWidget) { resize (initial_size.width(), initial_size.height()); graphics_scene_ = new QGraphicsScene (0,0,initial_size.width(), initial_size.height(), this); graphics_view_ = new SignalBrowserGraphicsView (graphics_scene_); graphics_view_->setAcceptDrops (false); graphics_view_->scroll(0,0); graphics_view_->horizontalScrollBar()->hide(); graphics_view_->verticalScrollBar()->hide(); graphics_view_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); graphics_view_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); graphics_view_->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); graphics_view_->setDragMode(QGraphicsView::ScrollHandDrag); initWidgets (event_manager, command_executer); graphics_view_->setFrameStyle(QFrame::NoFrame); // setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); createLayout(); connect (graphics_view_, SIGNAL(resized(QResizeEvent*)), SLOT(graphicsViewResized(QResizeEvent*))); horizontal_scrollbar_->setValue(0); horizontal_scrollbar_->setSingleStep(80); } //----------------------------------------------------------------------------- void SignalBrowserView::resizeScene (int32 width, int32 height) { QPointF left_upper_corner = graphics_view_->mapToScene (0, 0); left_upper_corner.setY (left_upper_corner.y() * height / graphics_scene_->height()); left_upper_corner.setX (left_upper_corner.x() * width / graphics_scene_->width()); graphics_scene_->setSceneRect (0, 0, width, height); QPointF center = left_upper_corner; center.setX (center.x () + static_cast(graphics_view_->width()) / 2.0); center.setY (center.y () + static_cast(graphics_view_->height()) / 2.0); graphics_view_->centerOn (center); emit visibleXChanged (graphics_view_->mapToScene (0, 0).x()); emit visibleYChanged (graphics_view_->mapToScene(0, 0).y()); } //----------------------------------------------------------------------------- void SignalBrowserView::addSignalGraphicsItem (ChannelID channel_nr, SignalGraphicsItem* graphics_item, QString const& label) { graphics_scene_->addItem (graphics_item); y_axis_widget_->addChannel (channel_nr, graphics_item); label_widget_->addChannel (channel_nr, label); connect (graphics_item, SIGNAL(updatedYGrid(ChannelID)), y_axis_widget_, SLOT(updateChannel(ChannelID))); connect (graphics_item, SIGNAL(shifting(ChannelID)), y_axis_widget_, SLOT(updateChannel(ChannelID))); connect (graphics_item, SIGNAL(mouseAtSecond(float64)), x_axis_widget_, SLOT(changeHighlightTime(float64))); connect (graphics_item, SIGNAL(mouseMoving(bool)), x_axis_widget_, SLOT(enableHighlightTime(bool))); } //----------------------------------------------------------------------------- void SignalBrowserView::removeSignalGraphicsItem (ChannelID channel_nr, SignalGraphicsItem* graphics_item) { disconnect (graphics_item, 0, x_axis_widget_, 0); disconnect (graphics_item, 0, y_axis_widget_, 0); y_axis_widget_->removeChannel(channel_nr); label_widget_->removeChannel(channel_nr); graphics_scene_->removeItem (graphics_item); graphics_view_->update (); } //----------------------------------------------------------------------------- void SignalBrowserView::addEventGraphicsItem (EventGraphicsItem* event_graphics_item) { graphics_scene_->addItem(event_graphics_item); graphics_view_->update(); connect (event_graphics_item, SIGNAL(mouseAtSecond(float64)), x_axis_widget_, SLOT(changeHighlightTime(float64))); connect (event_graphics_item, SIGNAL(mouseMoving(bool)), x_axis_widget_, SLOT(enableHighlightTime(bool))); } //----------------------------------------------------------------------------- void SignalBrowserView::removeEventGraphicsItem (EventGraphicsItem* event_graphics_item) { qDebug () << "SignalBrowserView::removeEventGraphicsItem " << event_graphics_item->getId(); graphics_view_->update(); qDebug () << "SignalBrowserView::removeEventGraphicsItem " << event_graphics_item->getId() << " finished"; } //----------------------------------------------------------------------------- int32 SignalBrowserView::getVisibleX () const { return graphics_view_->mapToScene(0,0).x(); } //----------------------------------------------------------------------------- void SignalBrowserView::goTo (float32 x) { double y = graphics_view_->mapToScene(0, 0).y(); x += graphics_view_->width() / 2; y += static_cast(graphics_view_->height()) / 2.0; graphics_view_->centerOn(x, y); graphics_scene_->update(0, 0, graphics_scene_->width(), graphics_scene_->height()); } //----------------------------------------------------------------------------- void SignalBrowserView::updateWidgets (bool update_view) { if (update_view) graphics_view_->viewport()->update(); x_axis_widget_->update(); y_axis_widget_->update(); label_widget_->update(); emit visibleYChanged (graphics_view_->mapToScene(0,0).y()); } //----------------------------------------------------------------------------- QSharedPointer SignalBrowserView::renderVisibleScene () const { QSharedPointer image (new QImage(graphics_view_->viewport()->width(), graphics_view_->viewport()->height(), QImage::Format_ARGB32)); image->fill (Qt::white); QPainter painter (image.data()); graphics_view_->render (&painter, graphics_view_->viewport()->rect(), graphics_view_->viewport()->rect()); return image; } //----------------------------------------------------------------------------- bool SignalBrowserView::getXAxisVisibility () const { return x_axis_widget_->isVisible (); } //----------------------------------------------------------------------------- bool SignalBrowserView::getYAxisVisibility () const { return y_axis_widget_->isVisible (); } //----------------------------------------------------------------------------- bool SignalBrowserView::getLabelsVisibility () const { return label_widget_->isVisible (); } //----------------------------------------------------------------------------- int SignalBrowserView::getViewportHeight () const { return graphics_view_->viewport()->height(); } //----------------------------------------------------------------------------- int SignalBrowserView::getViewportWidth () const { return graphics_view_->viewport()->width(); } //----------------------------------------------------------------------------- void SignalBrowserView::setMode (SignalVisualisationMode mode) { double channelHeight = model_->getSignalViewSettings()->getChannelHeight(); double oldCentralWidgetHeight = graphics_view_->height(); if (current_info_widget_) { layout_->removeWidget (current_info_widget_); current_info_widget_->hide(); } switch (mode) { case MODE_NEW: current_info_widget_ = event_creation_widget_; graphics_view_->setDragMode(QGraphicsView::NoDrag); break; case MODE_POINTER: current_info_widget_ = event_editing_widget_; graphics_view_->setDragMode(QGraphicsView::NoDrag); break; case MODE_HAND: graphics_view_->setDragMode(QGraphicsView::ScrollHandDrag); current_info_widget_ = empty_widget_; break; case MODE_VIEW_OPTIONS: current_info_widget_ = adapt_browser_view_widget_; graphics_view_->setDragMode(QGraphicsView::NoDrag); break; case MODE_INFO: current_info_widget_ = model_->infoWidget (); graphics_view_->setDragMode(QGraphicsView::NoDrag); break; default: current_info_widget_ = empty_widget_; break; } if (current_info_widget_) { layout_->addWidget (current_info_widget_, 1, 2); current_info_widget_->show(); } double factor = graphics_view_->height() / oldCentralWidgetHeight; model_->getSignalViewSettings()->setChannelHeight(round(channelHeight * factor)); } //----------------------------------------------------------------------------- void SignalBrowserView::graphicsViewResized (QResizeEvent* event) { unsigned channel_height = model_->getSignalViewSettings()->getChannelHeight(); if (!channel_height) return; if (event->size().height() < 1 || event->oldSize().height() < 1) return; channel_height *= static_cast(event->size().height()) / event->oldSize().height(); if (channel_height < 10) return; model_->getSignalViewSettings()->setChannelHeight (channel_height); // float32 pixel_per_sample = model_->getSignalViewSettings()->getPixelsPerSample(); // float32 new_pixel_per_sample = std::min (pixel_per_sample * ZOOM_FACTOR_, // maxPixelPerSample() ); // double secsPerPageSpinbox = adapt_browser_view_widget_->getSecsPerPage(); // float new_pixels_per_sample = this->getViewportWidth() / // (secsPerPageSpinbox * model_->getSignalViewSettings()-> // getChannelManager().getSampleRate()); // GuiHelper::animateProperty (model_->getSignalViewSettings().data(), "pixelsPerSample", // pixel_per_sample, new_pixels_per_sample, // this, SLOT(evaluateEnabledness())); // GuiHelper::animateProperty (model_->getSignalViewSettings().data(), "pixelsPerSample", // model_->getSignalViewSettings()->getPixelsPerSample(), // new_pixels_per_sample, this, SLOT(selfUpdatingFinished())); } /*! * \brief Toggle X Widget * \param A boolean value on whether to enable X widget * * y_axis_widget_, label_widget_ and graphics_view_ (The main widget which * shows signals) needs to be turned off first then turned on again, to avoid * overlapping with x_axis_widget_ (usually the last channel). */ void SignalBrowserView::toggleXWidget(bool enabled) { double channelHeight = model_->getSignalViewSettings()->getChannelHeight(); y_axis_widget_->hide(); label_widget_->hide(); graphics_view_->hide(); horizontal_scrollbar_->hide(); x_axis_widget_->setVisible(enabled); y_axis_widget_->show(); label_widget_->show(); graphics_view_->show(); horizontal_scrollbar_->show(); if (model_->getSignalViewSettings()->getChannelHeight() != channelHeight) model_->getSignalViewSettings()->setChannelHeight(channelHeight); } //----------------------------------------------------------------------------- void SignalBrowserView::verticalSrollbarMoved(int) { label_widget_->update(); qreal y = graphics_view_->mapToScene(0,0).y(); if (y < 0) y = 0; emit visibleYChanged (y); } //----------------------------------------------------------------------------- void SignalBrowserView::horizontalSrollbarMoved(int) { emit visibleXChanged (graphics_view_->mapToScene(0,0).x()); } //----------------------------------------------------------------------------- void SignalBrowserView::horizontalScrollBarRangeChaned (int min, int max) { horizontal_scrollbar_->setRange(min, max); horizontal_scrollbar_->setPageStep(graphics_view_->horizontalScrollBar()->pageStep()); emit visibleXChanged (graphics_view_->mapToScene(0,0).x()); } //----------------------------------------------------------------------------- void SignalBrowserView::verticalScrollBarRangeChaned (int min, int max) { label_widget_->update (); y_axis_widget_->update(); vertical_scrollbar_->setRange(min, max); vertical_scrollbar_->setPageStep(graphics_view_->verticalScrollBar()->pageStep()); qreal y = graphics_view_->mapToScene(0,0).y(); if (y < 0) y = 0; emit visibleYChanged (y); } //----------------------------------------------------------------------------- void SignalBrowserView::dropEvent (QDropEvent* event) { event->ignore(); } //----------------------------------------------------------------------------- void SignalBrowserView::dragEnterEvent(QDragEnterEvent *event) { event->ignore(); } //----------------------------------------------------------------------------- void SignalBrowserView::initWidgets (QSharedPointer event_manager, QSharedPointer command_executer) { y_axis_widget_ = new YAxisWidget (this, model_->getSignalViewSettings()); y_axis_widget_->resize(70, height()); y_axis_widget_->setMinimumSize(70, 0); x_axis_widget_ = new XAxisWidget (model_->getSignalViewSettings(), this); x_axis_widget_->resize(width()-300, 30); x_axis_widget_->setMinimumSize(0, 30); horizontal_scrollbar_ = new QScrollBar (Qt::Horizontal, this); vertical_scrollbar_ = new QScrollBar (Qt::Vertical, this); label_widget_ = new LabelWidget (model_->getSignalViewSettings()); current_info_widget_ = empty_widget_; if (event_manager.isNull()) { event_creation_widget_ = 0; event_editing_widget_ = 0; } else { event_creation_widget_ = new EventCreationWidget (model_, event_manager); event_editing_widget_ = new EventEditingWidget (event_manager, command_executer); event_creation_widget_->connect (model_.data(), SIGNAL(shownEventTypesChanged(std::set const&)), SLOT(updateShownEventTypes (std::set const&))); event_editing_widget_->connect (model_.data(), SIGNAL(shownEventTypesChanged(std::set const&)), SLOT(updateShownEventTypes (std::set const&))); event_editing_widget_->connect (model_.data(), SIGNAL(eventSelected(QSharedPointer)), SLOT(updateSelectedEventInfo(QSharedPointer))); } adapt_browser_view_widget_ = new AdaptBrowserViewWidget (this, model_->getSignalViewSettings(), y_axis_widget_, x_axis_widget_, label_widget_); connect (adapt_browser_view_widget_, SIGNAL(xAxisVisibilityChanged(bool)), SLOT(toggleXWidget(bool))); y_axis_widget_->connect (adapt_browser_view_widget_, SIGNAL(yAxisVisibilityChanged(bool)), SLOT(setVisible(bool))); label_widget_->connect (adapt_browser_view_widget_, SIGNAL(labelsVisibilityChanged(bool)), SLOT(setVisible(bool))); connect(horizontal_scrollbar_, SIGNAL(valueChanged(int)), graphics_view_->horizontalScrollBar(), SLOT(setValue(int))); connect(graphics_view_->horizontalScrollBar(), SIGNAL(valueChanged(int)), horizontal_scrollbar_, SLOT(setValue(int))); connect(graphics_view_->horizontalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(horizontalScrollBarRangeChaned(int,int))); connect(horizontal_scrollbar_, SIGNAL(valueChanged(int)), this, SLOT(horizontalSrollbarMoved(int))); connect(vertical_scrollbar_, SIGNAL(valueChanged(int)), graphics_view_->verticalScrollBar(), SLOT(setValue(int))); connect(graphics_view_->verticalScrollBar(), SIGNAL(valueChanged(int)), vertical_scrollbar_, SLOT(setValue(int))); connect(graphics_view_->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(verticalScrollBarRangeChaned(int,int))); connect(vertical_scrollbar_, SIGNAL(valueChanged(int)), this, SLOT(verticalSrollbarMoved(int))); //! To sync event creation widget and editing widget connect(event_creation_widget_, SIGNAL(newEventType(std::set)), event_editing_widget_, SLOT(updateShownEventTypes(std::set))); connect(this, SIGNAL(visibleXChanged(int32)), x_axis_widget_, SLOT(changeXStart(int32))); connect(model_->getSignalViewSettings().data(), SIGNAL(pixelsPerSampleChanged()), x_axis_widget_, SLOT(update())); label_widget_->connect (this, SIGNAL(visibleYChanged(int32)), SLOT(changeYStart (int32))); y_axis_widget_->connect (this, SIGNAL(visibleYChanged(int32)), SLOT(changeYStart (int32))); // connect(this, SIGNAL(visibleYChanged(int32)), y_axis_widget_, SLOT(changeYStart(int32))); connect(model_->getSignalViewSettings().data(), SIGNAL(channelHeightChanged(uint)), y_axis_widget_, SLOT(changeSignalHeight(uint))); connect(model_.data(), SIGNAL(modeChanged(SignalVisualisationMode)), SLOT(setMode(SignalVisualisationMode))); } //----------------------------------------------------------------------------- void SignalBrowserView::createLayout() { layout_ = new QGridLayout(this); layout_->setMargin(0); layout_->setSpacing(0); layout_->setVerticalSpacing(0); layout_->setHorizontalSpacing(0); //set vertical size policy of graphics_view_ to adjust size //when other widgets are toggled on and off graphics_view_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); y_axis_widget_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); label_widget_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); layout_->addWidget(current_info_widget_, 1, 1, 1, 3); layout_->addWidget(y_axis_widget_, 2, 1); layout_->addWidget(graphics_view_, 2, 2); layout_->addWidget(x_axis_widget_, 3, 2); layout_->addWidget(horizontal_scrollbar_, 4, 2); layout_->addWidget(label_widget_, 2, 3); layout_->addWidget(vertical_scrollbar_, 2, 4); graphics_view_->setAlignment(Qt::AlignVCenter); } } sigviewer-0.6.4/src/gui_impl/signal_browser/signal_browser_view.h000066400000000000000000000065421345753661000254050ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_BROWSER_VIEW_H #define SIGNAL_BROWSER_VIEW_H #include "base/sigviewer_user_types.h" #include "command_executer.h" #include "gui/signal_visualisation_model.h" #include "gui/signal_visualisation_view.h" #include "file_handling/event_manager.h" #include "signal_browser_graphics_view.h" #include #include #include #include #include #include class QGridLayout; class QScrollBar; class QCursor; namespace sigviewer { class LabelWidget; class YAxisWidget; class XAxisWidget; class SignalGraphicsItem; class EventGraphicsItem; class EventEditingWidget; class EventCreationWidget; class AdaptBrowserViewWidget; // signal browser view class SignalBrowserView : public QFrame, public SignalVisualisationView { Q_OBJECT public: SignalBrowserView (QSharedPointer signal_browser_model, QSharedPointer event_manager, QSharedPointer command_executer, QRect const& initial_size, QWidget* parent = 0); virtual ~SignalBrowserView () {} void addSignalGraphicsItem (ChannelID channel_nr, SignalGraphicsItem* graphics_item, QString const& label); void removeSignalGraphicsItem (ChannelID channel_nr, SignalGraphicsItem* graphics_item); void addEventGraphicsItem (EventGraphicsItem* event_graphics_item); void removeEventGraphicsItem (EventGraphicsItem* event_graphics_item); void resizeScene (int32 width, int32 height); int32 getVisibleX () const; void goTo (float32 x); void updateWidgets (bool update_view = true); virtual QSharedPointer renderVisibleScene () const; virtual bool getXAxisVisibility () const; virtual bool getYAxisVisibility () const; virtual bool getLabelsVisibility () const; virtual int getViewportHeight () const; virtual int getViewportWidth () const; public slots: void setMode (SignalVisualisationMode mode); signals: void visibleXChanged (int32 new_x); void visibleYChanged (int32 new_y); private slots: void verticalSrollbarMoved(int); void horizontalSrollbarMoved(int); void horizontalScrollBarRangeChaned (int min, int max); void verticalScrollBarRangeChaned (int min, int max); virtual void dropEvent (QDropEvent* event); virtual void dragEnterEvent(QDragEnterEvent *event); void graphicsViewResized (QResizeEvent* event); void toggleXWidget(bool enabled); private: void initWidgets (QSharedPointer event_manager, QSharedPointer command_executer); void createLayout (); QSharedPointer model_; QGraphicsScene* graphics_scene_; SignalBrowserGraphicsView* graphics_view_; YAxisWidget* y_axis_widget_; XAxisWidget* x_axis_widget_; QScrollBar* horizontal_scrollbar_; QScrollBar* vertical_scrollbar_; LabelWidget* label_widget_; EventEditingWidget* event_editing_widget_; EventCreationWidget* event_creation_widget_; AdaptBrowserViewWidget* adapt_browser_view_widget_; QWidget* current_info_widget_; QWidget* empty_widget_; QGridLayout* layout_; }; } #endif // SIGNAL_BROWSER_VIEW_H sigviewer-0.6.4/src/gui_impl/signal_browser/signal_graphics_item.cpp000066400000000000000000000547601345753661000260460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_graphics_item.h" #include "signal_browser_model_4.h" #include "editing_commands/new_event_undo_command.h" #include "base/math_utils.h" #include "gui_impl/signal_browser_mouse_handling.h" #include "gui/gui_action_factory.h" #include "file_handling_impl/xdf_reader.h" #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- SignalGraphicsItem::SignalGraphicsItem (QSharedPointer signal_view_settings, QSharedPointer event_manager, QSharedPointer command_executor, ChannelManager const& channel_manager, QSharedPointer color_manager, ChannelID id, SignalBrowserModel& model) : signal_view_settings_ (signal_view_settings), event_manager_ (event_manager), command_executor_ (command_executor), channel_manager_ (channel_manager), color_manager_ (color_manager), id_ (id), signal_browser_model_(model), minimum_ (channel_manager_.getMinValue (id_)), maximum_ (channel_manager_.getMaxValue (id_)), y_zoom_ (1), y_offset_ (0), height_ (signal_view_settings->getChannelHeight()), width_ (0), shifting_ (false), new_event_ (false), created_event_item_ (0), hand_tool_on_ (false), grid_color_ (QColor(220, 220, 220, 50)), //set the default grid color label_color_ (Qt::black) { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); setAcceptHoverEvents(false); connect(signal_view_settings.data(), SIGNAL(gridFragmentationChanged()), SLOT(updateYGridIntervall())); connect(signal_view_settings.data(), SIGNAL(enableXGrid(bool)), SLOT(toggleXGrid(bool))); connect(signal_view_settings.data(), SIGNAL(enableYGrid(bool)), SLOT(toggleYGrid(bool))); connect(signal_view_settings.data(), SIGNAL(separatorEnabled(bool)), SLOT(enableSeparator(bool))); connect(signal_view_settings.data(), SIGNAL(gridColorChanged(QColor)), SLOT(updateGridColor(QColor))); connect(signal_view_settings.data(), SIGNAL(labelColorChanged(QColor)), SLOT(updateLabelColor(QColor))); QSettings settings; settings.beginGroup("SignalBrowserModel"); draw_x_grid_ = settings.value("show_x_grid", false).toBool(); draw_y_grid_ = settings.value("show_y_grid", false).toBool(); draw_separator = settings.value("show_separator", false).toBool(); settings.endGroup(); } //----------------------------------------------------------------------------- SignalGraphicsItem::~SignalGraphicsItem () { } //----------------------------------------------------------------------------- void SignalGraphicsItem::setHeight (unsigned height) { this->prepareGeometryChange(); y_zoom_ = y_zoom_ * height / height_; y_offset_ = y_offset_* height / height_; height_ = height; width_ = channel_manager_.getNumberSamples() * signal_view_settings_->getPixelsPerSample(); updateYGridIntervall (); } //----------------------------------------------------------------------------- void SignalGraphicsItem::setXGridInterval (unsigned interval) { x_grid_interval_ = interval; } //----------------------------------------------------------------------------- void SignalGraphicsItem::toggleXGrid(bool enable) { draw_x_grid_ = enable; update (); } //----------------------------------------------------------------------------- void SignalGraphicsItem::toggleYGrid(bool enable) { draw_y_grid_ = enable; update (); } //----------------------------------------------------------------------------- void SignalGraphicsItem::enableSeparator(bool enable) { draw_separator = enable; update(); } //----------------------------------------------------------------------------- void SignalGraphicsItem::updateGridColor(QColor gridColor) { grid_color_ = gridColor; update(); } void SignalGraphicsItem::updateLabelColor(QColor labelColor) { label_color_ = labelColor; update(); } //----------------------------------------------------------------------------- QRectF SignalGraphicsItem::boundingRect () const { return QRectF (0, 0, width_, height_); } //----------------------------------------------------------------------------- float64 SignalGraphicsItem::getYZoom() const { return y_zoom_; } //----------------------------------------------------------------------------- float64 SignalGraphicsItem::getYOffset() const { return y_offset_; } //----------------------------------------------------------------------------- float64 SignalGraphicsItem::getYGridPixelIntervall() const { return y_grid_pixel_intervall_; } //----------------------------------------------------------------------------- double SignalGraphicsItem::getValueRangeFragment() const { return value_range_fragment_; } //----------------------------------------------------------------------------- QString SignalGraphicsItem::getPhysicalDimensionString () const { return channel_manager_.getChannelYUnitString (id_); } //----------------------------------------------------------------------------- void SignalGraphicsItem::zoomIn() { double mid_line_value = (maximum_ + minimum_) / 2; scaleImpl ((mid_line_value + minimum_) / 2.0, (maximum_ + mid_line_value) / 2.0); } //----------------------------------------------------------------------------- void SignalGraphicsItem::zoomOut() { double mid_line_value = (maximum_ + minimum_) / 2; scaleImpl ((2 * minimum_) - mid_line_value, (2 * maximum_) - mid_line_value); } //----------------------------------------------------------------------------- void SignalGraphicsItem::scale (double lower_value, double upper_value) { scaleImpl (lower_value, upper_value); } //----------------------------------------------------------------------------- void SignalGraphicsItem::autoScale (ScaleMode auto_zoom_type) { minimum_ = channel_manager_.getMinValue (id_); maximum_ = channel_manager_.getMaxValue (id_); double max = maximum_; double min = minimum_; if (auto_zoom_type == MAX_TO_MAX) { if (fabs(max) >= fabs (min)) min = max; else max = min; if (min > 0) min *= -1; if (max < 0) max *= -1; } scaleImpl (min, max); } //----------------------------------------------------------------------------- void SignalGraphicsItem::scaleImpl (double min, double max) { minimum_ = min; maximum_ = max; float64 new_y_zoom = height_ / (max - min); float64 new_y_offset = ((max + min) / 2) * new_y_zoom; if (y_zoom_ != new_y_zoom || y_offset_ != new_y_offset) { y_zoom_ = new_y_zoom; y_offset_ = new_y_offset; updateYGridIntervall (); } signal_browser_model_.update (); } //----------------------------------------------------------------------------- void SignalGraphicsItem::paint (QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*) { if (option->exposedRect.width() < 1) return; bool channel_overlapping = signal_view_settings_->getChannelOverlapping(); if (draw_separator && !channel_overlapping) // painter->drawRect(boundingRect()); { //draw only upper and lower border, no verdical borders painter->setPen(label_color_); painter->drawLine(0, 0, width_, 0); painter->drawLine(0, height_, width_, height_); } if (new_event_) painter->fillRect(new_signal_event_->getPosition(), 0, new_signal_event_->getDuration(), height_, new_event_color_); QRectF clip (option->exposedRect); double pixel_per_sample = signal_view_settings_->getPixelsPerSample(); double last_x = clip.x () - 10; if (last_x < 0) last_x = 0; unsigned start_sample = last_x / pixel_per_sample; if (start_sample > 0) start_sample--; unsigned length = ((clip.x() - start_sample * pixel_per_sample) + clip.width() + 20); if (last_x + length > width_) length = width_ - last_x; length /= pixel_per_sample; if (length < channel_manager_.getNumberSamples() - start_sample) length++; QSharedPointer data_block = channel_manager_.getData (id_, start_sample, length); last_x = start_sample * pixel_per_sample; float64 last_y = (*data_block)[0]; float64 new_y = 0; if (draw_x_grid_) drawXGrid (painter, option); if (draw_y_grid_) drawYGrid (painter, option); //You can't draw the lines here because it's after the clipping, thus the lower border is always //overwritten by the next channel, and the lower border of the last channel is never shown // if (draw_separator && !channel_overlapping) // { // painter->setPen(label_color_); // painter->drawLine(0, 0, width_, 0); // painter->drawLine(0, height_, width_, height_); // } painter->translate (0, height_ / 2.0f); painter->setPen (color_manager_->getChannelColor (id_)); for (int index = 0; index < static_cast(data_block->size()) - 1; index++) { new_y = (*data_block)[index+1]; //!Draw nothing if NAN if (!std::isnan(last_y) && !std::isnan(new_y)) { painter->drawLine(last_x, y_offset_ - (y_zoom_ * last_y), last_x + pixel_per_sample, y_offset_ - (y_zoom_ * new_y)); } last_x += pixel_per_sample; last_y = new_y; } return; } //----------------------------------------------------------------------------- void SignalGraphicsItem::updateYGridIntervall () { double value_range = (maximum_ - minimum_) ;/// y_zoom_; value_range_fragment_ = MathUtils_::round125 (value_range / signal_view_settings_->getGridFragmentation (Qt::Vertical)); // qDebug () << "y_zoom_ = " << y_zoom_ << "; value_range_fragment_ = " << value_range_fragment_; y_grid_pixel_intervall_ = static_cast(height_) * value_range_fragment_ / value_range; emit updatedYGrid (id_); update (); } //----------------------------------------------------------------------------- void SignalGraphicsItem::enableYGrid(bool enabled) { draw_y_grid_ = enabled; } //----------------------------------------------------------------------------- void SignalGraphicsItem::enableXGrid(bool enabled) { draw_x_grid_ = enabled; } //----------------------------------------------------------------------------- void SignalGraphicsItem::mouseMoveEvent (QGraphicsSceneMouseEvent* event) { QPoint p = event->screenPos(); if (shifting_) { int32 dy = p.y() - move_start_point_.y(); move_start_point_ = p; move_start_point_ = p; y_offset_ = y_offset_ + dy; signal_browser_model_.update(); emit shifting (id_); } else if (new_event_) { float64 pixel_per_sample = signal_view_settings_->getPixelsPerSample(); int32 sample_cleaned_pos = event->scenePos().x() / pixel_per_sample + 0.5; sample_cleaned_pos *= pixel_per_sample; int32 new_event_width = new_signal_event_->getDuration (); size_t old_pos = new_signal_event_->getPosition (); size_t old_width = new_signal_event_->getDuration (); if (sample_cleaned_pos < new_signal_event_reference_x_) { new_event_width = new_signal_event_reference_x_ - sample_cleaned_pos; new_signal_event_->setPosition (sample_cleaned_pos); } else { new_signal_event_->setPosition (new_signal_event_reference_x_); new_event_width = sample_cleaned_pos - new_signal_event_->getPosition(); } if (new_event_width < 0) new_event_width = 0; new_signal_event_->setDuration (new_event_width); int32 update_start = std::min(old_pos, new_signal_event_->getPosition()); int32 update_end = std::max(old_pos + old_width, new_event_width + new_signal_event_->getPosition ()); update (update_start, 0, update_end - update_start, height_); emit mouseAtSecond (sample_cleaned_pos / pixel_per_sample * channel_manager_.getSampleRate()); } else event->ignore(); } //----------------------------------------------------------------------------- void SignalGraphicsItem::hoverMoveEvent (QGraphicsSceneHoverEvent* event) { unsigned sample_pos = event->scenePos().x() / signal_view_settings_->getPixelsPerSample (); emit mouseMoving (true); emit mouseAtSecond (sample_pos / channel_manager_.getSampleRate()); if (event_manager_.isNull()) return; std::set events = event_manager_->getEventsAt (sample_pos, id_); std::set shown_types = signal_browser_model_.getShownEventTypes(); QString event_string; foreach (EventID event, events) { QSharedPointer signal_event = event_manager_->getEvent(event); if (shown_types.count(signal_event->getType())) { if (event_string.size()) event_string += "

"; event_string += "" + event_manager_->getNameOfEvent (event) + "
"; event_string += "Start: " + QString::number(signal_event->getPositionInSec()) + "s; "; event_string += "Duration: " + QString::number(signal_event->getDurationInSec()) + "s"; } } if (event_string.size()) { QToolTip::showText (event->screenPos(), event_string); setToolTip (event_string); } else { setToolTip (""); QToolTip::hideText(); } } //----------------------------------------------------------------------------- void SignalGraphicsItem::mousePressEvent (QGraphicsSceneMouseEvent * event ) { SignalVisualisationMode mode = signal_browser_model_.getMode(); switch (SignalBrowserMouseHandling::getAction(event, mode)) { case SignalBrowserMouseHandling::HAND_SCROLL_ACTION: hand_tool_on_ = true; event->ignore(); break; case SignalBrowserMouseHandling::SHIFT_CHANNEL_ACTION: shifting_ = true; setCursor(QCursor(Qt::SizeVerCursor)); move_start_point_ = event->screenPos(); break; case SignalBrowserMouseHandling::NEW_EVENT_ACTION: { if (signal_browser_model_.getShownEventTypes ().size() == 0) break; float32 pixel_per_sample = signal_view_settings_->getPixelsPerSample (); int32 sample_cleaned_pos = event->scenePos().x() / pixel_per_sample + 0.5; sample_cleaned_pos *= pixel_per_sample; new_event_ = true; if (event_manager_->getFileType().startsWith("XDF", Qt::CaseInsensitive)) { //If user added events in Sigviewer, we will create a new stream to store these events //and later store back to the XDF file if (!XDFdata->userAddedStream) { //check whether a user added stream has already been existing XDFdata->userAddedStream = XDFdata->streams.size(); XDFdata->streams.emplace_back(); time_t currentTime = time(nullptr); std::string timeString = asctime(localtime(¤tTime)); timeString.pop_back(); //we don't need '\n' at the end XDFdata->streams.back().streamHeader = "" "" "User Created Event Stream" "Events" "1" "0" "string" "User Added Events" "1" "" + timeString + "" "" "" "" "" ""; } new_signal_event_ = QSharedPointer (new SignalEvent(sample_cleaned_pos, signal_browser_model_.getActualEventCreationType(), event_manager_->getSampleRate(), XDFdata->userAddedStream, id_)); //Add the newly created event to the XDFdata object for later use QString eventName = event_manager_->getNameOfEventType(signal_browser_model_.getActualEventCreationType()); XDFdata->userCreatedEvents.emplace_back (eventName.toStdString(), (sample_cleaned_pos/event_manager_->getSampleRate()) + XDFdata->minTS); } else { new_signal_event_ = QSharedPointer (new SignalEvent(sample_cleaned_pos, signal_browser_model_.getActualEventCreationType(), event_manager_->getSampleRate(), -1, id_)); } new_event_color_ = color_manager_->getEventColor(signal_browser_model_.getActualEventCreationType()); new_signal_event_reference_x_ = sample_cleaned_pos; emit mouseMoving (true); break; } break; default: event->accept(); if (!EventGraphicsItem::displaySelectionMenu (event)) signal_browser_model_.unselectEvent (); } } //----------------------------------------------------------------------------- void SignalGraphicsItem::mouseReleaseEvent (QGraphicsSceneMouseEvent* event) { if (hand_tool_on_) event->ignore(); if (new_event_) { emit mouseMoving (false); NewEventUndoCommand* new_event_command = new NewEventUndoCommand (event_manager_, new_signal_event_, 1.0 / signal_view_settings_->getPixelsPerSample()); command_executor_->executeCommand (new_event_command); signal_browser_model_.selectEvent (new_event_command->getIDOfNewlyCreatedEvent()); } shifting_ = false; hand_tool_on_ = false; new_event_ = false; setCursor(QCursor()); } //----------------------------------------------------------------------------- void SignalGraphicsItem::contextMenuEvent (QGraphicsSceneContextMenuEvent * event) { signal_browser_model_.selectChannel (id_); QMenu* context_menu = new QMenu (channel_manager_.getChannelLabel(id_)); context_menu->addAction(GuiActionFactory::getInstance()->getQAction("Change Color...")); context_menu->addAction(GuiActionFactory::getInstance()->getQAction("Scale...")); if (signal_browser_model_.getShownChannels().size() > 1) { context_menu->addSeparator (); context_menu->addAction(GuiActionFactory::getInstance()->getQAction("Hide Channel")); } if (!EventGraphicsItem::displayContextMenu (event, context_menu)) context_menu->exec(event->screenPos()); else event->accept(); } //----------------------------------------------------------------------------- void SignalGraphicsItem::wheelEvent (QGraphicsSceneWheelEvent* event) { if (event->modifiers().testFlag(Qt::ControlModifier)) { if (event->delta() > 0) zoomIn(); else if (event->delta() < 0) zoomOut(); } else if (event->modifiers().testFlag(Qt::ShiftModifier)) { if (event->delta() > 0) signal_browser_model_.zoomInAll (); else if (event->delta() < 0) signal_browser_model_.zoomOutAll (); } else event->ignore(); } //----------------------------------------------------------------------------- void SignalGraphicsItem::drawYGrid (QPainter* painter, QStyleOptionGraphicsItem const* option) { if (y_grid_pixel_intervall_ < 1) return; QRectF clip (option->exposedRect); //painter->setPen (Qt::lightGray); // painter->setPen (QColor(220, 220, 220, 50)); // Qt::lightGray is still too dark and strong. painter->setPen(grid_color_); for (float64 y = y_offset_; y < height_ / 2; y += y_grid_pixel_intervall_) { if (y > -static_cast(height_ / 2)) { painter->drawLine (clip.x(), y, clip.x() + clip.width(), y); } } for (float64 y = y_offset_; y > -static_cast(height_ / 2); y -= y_grid_pixel_intervall_) { if (y < height_ / 2) { painter->drawLine (clip.x(), y, clip.x() + clip.width(), y); } } } //----------------------------------------------------------------------------- void SignalGraphicsItem::drawXGrid (QPainter* painter, QStyleOptionGraphicsItem const* option) { double pixel_per_sample = signal_view_settings_->getPixelsPerSample(); double pixel_per_sec_ = pixel_per_sample * signal_view_settings_->getSampleRate(); double interval_ = pixel_per_sec_ * MathUtils_::round125 (100.0 / pixel_per_sec_); if (interval_ < 1) return; QRectF clip (option->exposedRect); // painter->setPen (QColor(220, 220, 220, 50)); // Qt::lightGray is still too dark and strong. painter->setPen(grid_color_); if (clip.width() < 1) return; int32 x_start = clip.x(); int32 x_end = clip.x() + clip.width(); float64 float_x_start = floor((x_start + interval_ / 2) / interval_) * interval_; float64 float_x_end = ceil((x_end - interval_ / 2) / interval_) * interval_ + interval_ / 2; for (float32 float_x = float_x_start; float_x < float_x_end; float_x += interval_) { int32 x = (int32)(float_x + 0.5); painter->drawLine (x, 0, x, height_); } // for (int x = clip.x() - (static_cast(clip.x()) % x_grid_interval_); // x < clip.x() + clip.width(); x += x_grid_interval_) // painter->drawLine (x, 0, x, height_); } } sigviewer-0.6.4/src/gui_impl/signal_browser/signal_graphics_item.h000066400000000000000000000073101345753661000255000ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNALGRAPHICSITEM_H #define SIGNALGRAPHICSITEM_H #include "command_executer.h" #include "file_handling/event_manager.h" #include "gui/color_manager.h" #include "gui/signal_view_settings.h" #include class QPoint; namespace sigviewer { class SignalEvent; class SignalBrowserModel; class EventGraphicsItem; class SignalGraphicsItem : public QGraphicsObject { Q_OBJECT Q_INTERFACES(QGraphicsItem) public: SignalGraphicsItem(QSharedPointer signal_view_settings, QSharedPointer event_manager, QSharedPointer command_executor, ChannelManager const& channel_manager, QSharedPointer color_manager, ChannelID id, SignalBrowserModel& model); virtual ~SignalGraphicsItem (); virtual QRectF boundingRect () const; void enableYGrid(bool enabled); void enableXGrid(bool enabled); float64 getYZoom() const; float64 getYOffset() const; float64 getYGridPixelIntervall() const; double getValueRangeFragment () const; QString getPhysicalDimensionString () const; void zoomIn(); void zoomOut(); void scale (double lower_value, double upper_value); void autoScale (ScaleMode auto_zoom_type); public slots: void updateYGridIntervall(); void setHeight (unsigned height); void setXGridInterval (unsigned interval); void toggleXGrid(bool enable); void toggleYGrid(bool enable); void enableSeparator(bool enable); void updateGridColor(QColor gridColor); void updateLabelColor(QColor labelColor); signals: void mouseAtSecond (float64 sec); void mouseMoving (bool mouse_is_moving); void shifting (ChannelID channel_id); void updatedYGrid (ChannelID channel_id); private: void scaleImpl (double min, double max); virtual void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ); virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event ); virtual void mousePressEvent ( QGraphicsSceneMouseEvent * event ); virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event); virtual void contextMenuEvent (QGraphicsSceneContextMenuEvent * event); virtual void wheelEvent (QGraphicsSceneWheelEvent * event); void drawYGrid (QPainter* painter, QStyleOptionGraphicsItem const* option); void drawXGrid (QPainter* painter, QStyleOptionGraphicsItem const* option); QSharedPointer signal_view_settings_; QSharedPointer event_manager_; QSharedPointer command_executor_; ChannelManager const& channel_manager_; QSharedPointer color_manager_; ChannelID id_; SignalBrowserModel& signal_browser_model_; float64 minimum_; float64 maximum_; float64 y_zoom_; float64 y_grid_pixel_intervall_; double value_range_fragment_; bool draw_y_grid_; bool draw_x_grid_; bool draw_separator; float64 y_offset_; int32 height_; uint32 width_; unsigned x_grid_interval_; bool shifting_; bool new_event_; EventGraphicsItem* created_event_item_; bool hand_tool_on_; QPointF move_start_point_; QSharedPointer new_signal_event_; int32 new_signal_event_reference_x_; QColor new_event_color_; QColor grid_color_; QColor label_color_; }; } #endif // SIGNALGRAPHICSITEM_H sigviewer-0.6.4/src/gui_impl/signal_browser/signal_grid_graphics_item.cpp000066400000000000000000000004111345753661000270330ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_grid_graphics_item.h" namespace sigviewer { SignalGridGraphicsItem::SignalGridGraphicsItem() { } } sigviewer-0.6.4/src/gui_impl/signal_browser/signal_grid_graphics_item.h000066400000000000000000000005441345753661000265070ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_GRID_GRAPHICS_ITEM_H #define SIGNAL_GRID_GRAPHICS_ITEM_H namespace sigviewer { class SignalGridGraphicsItem { public: SignalGridGraphicsItem(); }; } #endif // SIGNAL_GRID_GRAPHICS_ITEM_H sigviewer-0.6.4/src/gui_impl/signal_browser/x_axis_widget_4.cpp000066400000000000000000000113151345753661000247410ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "x_axis_widget_4.h" #include "gui/gui_action_factory.h" #include "base/math_utils.h" #include #include #include #include #include #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- XAxisWidget::XAxisWidget (QSharedPointer signal_view_settings, QWidget* parent) : QWidget (parent), signal_view_settings_ (signal_view_settings), intervall_ (10), x_start_ (0), pixel_per_sec_ (2), length_in_sec_ (0), highlighting_enabled_ (false), time_to_highlight_ (0), label_color_ (Qt::black) { } //----------------------------------------------------------------------------- XAxisWidget::~XAxisWidget() { // nothing to do here } //----------------------------------------------------------------------------- QSize XAxisWidget::sizeHint () const { return QSize (100, 30); } //----------------------------------------------------------------------------- void XAxisWidget::changeXStart(int32 x_start) { x_start_ = x_start; update (); } //----------------------------------------------------------------------------- void XAxisWidget::changeHighlightTime (float64 time_to_highlight) { highlighting_enabled_ = true; time_to_highlight_ = time_to_highlight; update (); highlight_timer_ = startTimer (5000); } //----------------------------------------------------------------------------- void XAxisWidget::enableHighlightTime (bool highlighting_enabled) { highlighting_enabled_ = highlighting_enabled; update (); } //----------------------------------------------------------------------------- void XAxisWidget::changeLabelColor(QColor labelColor) { label_color_ = labelColor; update(); } //----------------------------------------------------------------------------- void XAxisWidget::paintEvent(QPaintEvent*) { pixel_per_sec_ = signal_view_settings_->getPixelsPerSample() * signal_view_settings_->getSampleRate(); intervall_ = pixel_per_sec_ * MathUtils_::round125 (100.0 / pixel_per_sec_); if (intervall_ < 1 ) { return; // invalid intervall } int32 x_end = x_start_ + width(); int32 font_height = height() - 5; QPainter p (this); p.setPen (Qt::black); p.translate(-x_start_, 0); p.setPen(label_color_); // p.drawLine(x_start_, 0, x_end, 0); float64 float_x_start = floor((x_start_ + intervall_ / 2) / intervall_) * intervall_; float64 float_x_end = ceil((x_end - intervall_ / 2) / intervall_) * intervall_ + intervall_ / 2; for (float32 float_x = float_x_start; float_x < float_x_end; float_x += intervall_) { int32 x = (int32)(float_x + 0.5); p.drawLine(x, 0, x, 5); p.drawText((int32)(x - intervall_ / 2), 5, (int32)intervall_, font_height, Qt::AlignHCenter | Qt::AlignVCenter, QString::number(float_x / pixel_per_sec_)); } if (highlighting_enabled_) { QFont font; font.setPointSizeF (font.pointSizeF() * 1.5); font.setBold (true); p.setFont (font); QRect bounding_rect = p.boundingRect (0, 0, 0, font.pixelSize(), Qt::AlignHCenter | Qt::AlignVCenter, QString::number(time_to_highlight_, 'f', 3)); bounding_rect.moveTo (time_to_highlight_ * pixel_per_sec_, 5); p.fillRect (bounding_rect, Qt::white); p.setPen (Qt::black); p.drawText (bounding_rect, Qt::AlignLeft | Qt::AlignTop, QString::number(time_to_highlight_, 'f', 2)); last_highlight_rect_ = bounding_rect; } } //----------------------------------------------------------------------------- void XAxisWidget::contextMenuEvent (QContextMenuEvent* event) { QMenu menu; menu.addAction(GuiActionFactory::getInstance()->getQAction("Scale X Axis")); menu.addSeparator(); QAction* visibility_action = menu.addAction("X Axis"); visibility_action->setCheckable (true); visibility_action->setChecked (true); connect (visibility_action, SIGNAL(triggered(bool)), SLOT(setVisible(bool))); menu.exec (event->globalPos()); } //----------------------------------------------------------------------------- void XAxisWidget::timerEvent (QTimerEvent* event) { if (event->timerId() == highlight_timer_) { highlighting_enabled_ = false; killTimer (highlight_timer_); highlight_timer_ = -1; } } } sigviewer-0.6.4/src/gui_impl/signal_browser/x_axis_widget_4.h000066400000000000000000000024371345753661000244130ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef X_AXIS_WIDGET_H #define X_AXIS_WIDGET_H #include "base/sigviewer_user_types.h" #include "gui/signal_view_settings.h" #include #include namespace sigviewer { class XAxisWidget : public QWidget { Q_OBJECT public: XAxisWidget (QSharedPointer signal_view_settings, QWidget* parent); virtual ~XAxisWidget(); virtual QSize sizeHint () const; public slots: void changeXStart (int32 x_start); void changeHighlightTime (float64 time_to_highlight); void enableHighlightTime (bool highlighting_enabled); void changeLabelColor(QColor labelColor); private: virtual void paintEvent(QPaintEvent*); virtual void contextMenuEvent (QContextMenuEvent* event); virtual void timerEvent (QTimerEvent* event); QSharedPointer signal_view_settings_; float64 intervall_; int32 x_start_; float64 pixel_per_sec_; float64 length_in_sec_; bool highlighting_enabled_; float64 time_to_highlight_; QRect last_highlight_rect_; int highlight_timer_; QColor label_color_; }; } #endif // X_AXIS_WIDGET_H sigviewer-0.6.4/src/gui_impl/signal_browser/y_axis_widget_4.cpp000066400000000000000000000210221345753661000247360ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "y_axis_widget_4.h" #include "signal_graphics_item.h" #include "gui/gui_action_factory.h" #include "base/math_utils.h" #include #include #include #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- YAxisWidget::YAxisWidget (QWidget* parent, QSharedPointer signal_view_settings) : QWidget (parent), channel_height_ (0), y_start_ (0), signal_view_settings_ (signal_view_settings), label_color_ (Qt::black) { // nothing to do here } //----------------------------------------------------------------------------- void YAxisWidget::addChannel(ChannelID channel_nr, SignalGraphicsItem const* const signal_item) { if (signal_item) channel_nr2signal_graphics_item_[channel_nr] = signal_item; } //----------------------------------------------------------------------------- void YAxisWidget::removeChannel(ChannelID channel_nr) { QMap::iterator it = channel_nr2signal_graphics_item_.find(channel_nr); if (it != channel_nr2signal_graphics_item_.end()) { channel_nr2signal_graphics_item_.erase(it); update (); } } //----------------------------------------------------------------------------- void YAxisWidget::changeSignalHeight (unsigned signal_height) { channel_height_ = signal_height; update (); } //----------------------------------------------------------------------------- void YAxisWidget::changeYStart(int32 y_start) { y_start_ = y_start; update (); } //----------------------------------------------------------------------------- void YAxisWidget::updateChannel (ChannelID) { update (); } //----------------------------------------------------------------------------- void YAxisWidget::enableSeparator(bool enable) { enable_separator = enable; update(); } //----------------------------------------------------------------------------- void YAxisWidget::changeLabelColor(QColor labelColor) { label_color_ = labelColor; update(); } //!this section is set to be consistent with label_widget.cpp---------------- void YAxisWidget::paintEvent(QPaintEvent*) { bool channel_overlapping = signal_view_settings_->getChannelOverlapping(); float64 signal_height = signal_view_settings_->getChannelHeight(); if (channel_overlapping) signal_height = (signal_height + (signal_height * (channel_nr2signal_graphics_item_.size() - 1) * (1.0 - signal_view_settings_->getChannelOverlapping()))) / channel_nr2signal_graphics_item_.size(); int32 y_end = y_start_ + height(); if (signal_height < 1) return; QPainter painter (this); painter.translate(0, -y_start_); painter.setPen(label_color_); // painter.setPen(QColor(0, 43, 130)); // painter.drawLine(width() - 1, y_start_, width() - 1, y_end); // painter.setPen(Qt::black); float64 float_y_end = y_end; auto iter = channel_nr2signal_graphics_item_.begin(); for (float32 float_y = signal_height / 2; float_y < float_y_end && iter != channel_nr2signal_graphics_item_.end(); float_y += signal_height, iter++) { paintYAxisLabels (&painter, iter.value()->getYOffset(), iter.value()->getYGridPixelIntervall(), iter.value()->getValueRangeFragment(), iter.value()->getPhysicalDimensionString(), signal_height); painter.translate (0, signal_height); } // this is the bottom line if (!channel_overlapping && enable_separator) painter.drawLine (0, 0, width() - 1, 0); // if (channel_overlapping) // return; // for (float32 float_y = 0; // float_y <= signal_height * channel_nr2signal_graphics_item_.size(); // float_y += signal_height) // { // painter.drawLine(0, float_y, width() - 1, float_y); // } } //----------------------------------------------------------------------------- void YAxisWidget::contextMenuEvent (QContextMenuEvent* event) { QMenu menu; menu.addAction(GuiActionFactory::getInstance()->getQAction("Channels per Page...")); menu.addSeparator(); QAction* visibility_action = menu.addAction("Y Axis"); visibility_action->setCheckable (true); visibility_action->setChecked (true); connect (visibility_action, SIGNAL(triggered(bool)), SLOT(setVisible(bool))); menu.exec (event->globalPos()); } //------------------------------------------------------------------- void YAxisWidget::paintYAxisLabels (QPainter* painter, float64 offset, float64 y_grid_pixel_intervall, double value_range_fragment, QString const& unit_string, float64 channelHeight) { //Below, 0 is the relative upper border of each channel. //despite being an absolute value, because the painter coordinates are readjusted //automatically every time it moves to a new channel, hence 0 is the //relative position of the upper border of each channel #define UPPER_BORDER 0 bool channel_overlapping = signal_view_settings_->getChannelOverlapping(); if (!channel_overlapping && enable_separator) { painter->drawLine (0, UPPER_BORDER, width() - 1, UPPER_BORDER); } paintYUnits (painter, unit_string, channelHeight); if (y_grid_pixel_intervall < 1) return; while (y_grid_pixel_intervall < 11) { y_grid_pixel_intervall *= 2; value_range_fragment *= 2; } double value = 0; //offset + channelHeight / 2 is the position where 0 is for each channel //However, 0 doesn't necessarily appear in the channel, if we are in //"zero line fitted" mode and if the mean is far from 0. //In the following for loop, we are still going to calculate from the position of 0 //even if 0 doesn't appear in the channel. Because in "view option" mode, the channel //can be scrolled up and down arbitrarily. for (float64 value_y = offset + channelHeight / 2; value_y < channelHeight; value_y += y_grid_pixel_intervall) { //But we only paint the calibration when they are within the channel height. //This can be dynamic if in the "view option" mode, since channels can be //scolled up and down. //Here, value starts with 0 means painter will draw 0 first, and subtract //value_range_fragment from value thereafter, so long as they are within channel //height from UPPER_BORDER if (value_y > UPPER_BORDER) { painter->drawLine (width () - 5, value_y, width () - 1, value_y); painter->drawText(0, value_y - 20, width () - 10, 40, Qt::AlignRight | Qt::AlignVCenter, QString::number (value)); } value -= value_range_fragment; } //We finished painting 0 and all negative numbers, now reset value to 0 value = 0; //Now paint the positive numbers for (float64 value_y = offset + channelHeight / 2 - y_grid_pixel_intervall; value_y > UPPER_BORDER; value_y -= y_grid_pixel_intervall) { value += value_range_fragment; //paint only if they position is within the range from UPPER_BORDER to //the bottom (UPPER_BORDER + channelHeight). This can be dynamic when //scrolling the channel. if (value_y < channelHeight) { painter->drawLine (width () - 5, value_y, width () - 1, value_y); painter->drawText(0, value_y - 20, width () - 10, 40, Qt::AlignRight | Qt::AlignVCenter, QString::number (value)); } } } //------------------------------------------------------------------- void YAxisWidget::paintYUnits (QPainter* painter, QString const& unit_string, float64 channelHeight) { if (unit_string.size() > 4) { painter->rotate(-90); painter->drawText (5, 0, width(), channelHeight, Qt::AlignLeft | Qt::AlignVCenter, unit_string); painter->rotate(90); } else painter->drawText (5, 0, width() - 10, channelHeight, Qt::AlignLeft | Qt::AlignVCenter, unit_string); } } sigviewer-0.6.4/src/gui_impl/signal_browser/y_axis_widget_4.h000066400000000000000000000033001345753661000244020ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef Y_AXIS_GRAPHICS_ITEM_H #define Y_AXIS_GRAPHICS_ITEM_H #include "base/sigviewer_user_types.h" #include "gui/signal_view_settings.h" #include #include namespace sigviewer { class SignalGraphicsItem; class YAxisWidget : public QWidget { Q_OBJECT public: YAxisWidget(QWidget* parent, QSharedPointer signal_view_settings); virtual ~YAxisWidget () {} void addChannel(ChannelID channel_nr, SignalGraphicsItem const* const signal_item); void removeChannel(ChannelID channel_nr); public slots: void changeSignalHeight (unsigned signal_height); void changeYStart (int32 y_start); void updateChannel (ChannelID channel_id); void enableSeparator(bool enable); void changeLabelColor(QColor labelColor); private: virtual void paintEvent (QPaintEvent* event = 0); virtual void contextMenuEvent (QContextMenuEvent* event); void paintYAxisLabels (QPainter* painter, float64 offset, float64 y_grid_pixel_intervall, double value_range_fragment, QString const& unit_string, float64 channelHeight); void paintYUnits (QPainter* painter, QString const& unit_string, float64 channelHeight); unsigned channel_height_; int32 y_start_; QMap channel_nr2signal_graphics_item_; QSharedPointer signal_view_settings_; bool enable_separator; QColor label_color_; }; } #endif // Y_AXIS_GRAPHICS_ITEM_H sigviewer-0.6.4/src/gui_impl/signal_browser_mouse_handling.cpp000066400000000000000000000031131345753661000247310ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "signal_browser_mouse_handling.h" #include #include #include namespace sigviewer { SignalBrowserMouseHandling::Action SignalBrowserMouseHandling::getAction(QGraphicsSceneMouseEvent* e, SignalVisualisationMode mode) { // hand scroll if ((e->button() == Qt::MidButton && e->modifiers() == Qt::NoModifier) || (mode == MODE_HAND && e->button() == Qt::LeftButton)) { return HAND_SCROLL_ACTION; } // shift channel if ((e->button() == Qt::MidButton && e->modifiers().testFlag(Qt::ShiftModifier)) || (mode == MODE_VIEW_OPTIONS && e->button() == Qt::LeftButton)) { return SHIFT_CHANNEL_ACTION; } // new event if (e->button() == Qt::LeftButton && mode == MODE_NEW) { return NEW_EVENT_ACTION; } // select or resize event if (e->button() == Qt::LeftButton && e->modifiers() == Qt::NoModifier && mode == MODE_POINTER) { return SELECT_RESIZE_EVENT_ACTION; } // shift event to channel if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ShiftModifier && mode == MODE_POINTER) { return SHIFT_EVENT_TO_CHANNEL_ACTION; } // copy event to channel if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ControlModifier && mode == MODE_POINTER) { return COPY_EVENT_TO_CHANNEL_ACTION; } return NO_ACTION; } } sigviewer-0.6.4/src/gui_impl/signal_browser_mouse_handling.h000066400000000000000000000016161345753661000244040ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef SIGNAL_BROWSER_MOUSE_HANDLING_H #define SIGNAL_BROWSER_MOUSE_HANDLING_H class QMouseEvent; class QWheelEvent; #include "gui/signal_visualisation_modes.h" class QGraphicsSceneMouseEvent; namespace sigviewer { // signal browser mouse action class SignalBrowserMouseHandling { public: enum Action { NO_ACTION, HAND_SCROLL_ACTION, ZOOM_WINDOW_ACTION, WHEEL_SCROLL_ACTION, ZOOM_ALL_CHANNELS_ACTION, ZOOM_CHANNEL_ACTION, SHIFT_CHANNEL_ACTION, NEW_EVENT_ACTION, SELECT_RESIZE_EVENT_ACTION, SHIFT_EVENT_TO_CHANNEL_ACTION, COPY_EVENT_TO_CHANNEL_ACTION }; static Action getAction(QGraphicsSceneMouseEvent* e, SignalVisualisationMode mode); }; } #endif sigviewer-0.6.4/src/images/000077500000000000000000000000001345753661000155735ustar00rootroot00000000000000sigviewer-0.6.4/src/images/ic_add_box_black_24dp.png000066400000000000000000000004401345753661000223370ustar00rootroot00000000000000PNG  IHDR``HIDATxi0GwK:L151!I{ɥ\/(!6 dV:vH9tĵ_Z #%Ȇ_,|%z{ܹ8gn[w̾]W/IENDB`sigviewer-0.6.4/src/images/ic_add_circle_outline_black_24dp.png000066400000000000000000000023521345753661000245530ustar00rootroot00000000000000PNG  IHDR``HIDATxkW?fAl"c77KzeQIQ?%lx_}5ihC|!^$4BƘ )iLff̊03g.bbbbbb,FNp'2 3<4RKIRN#죍=)hN6ʈ "E8@3"!i#|K+)BÈEh"4V .V?1$x uԑ$A$ug7'kI8& qߩ!v^0yL Ybd( N3}jk|ru6bMH0Xjj L#lP 9Dt}2wHL\R#| 'rel$V!ʝx↊=H @*зÑЋ_x`)FV` Ade+PH Wn[XΨQp削슴^JÌXu3\SH ,SGʌ$#-RGMʼ$"-PG}Jk .bܖ*ndp]ENFZ0wO82#L"ʆ -ThdZ+ea#+Ga7*4DR`5܎'LH \V#L#*:AE3Fg!ӡ8(3e 8UeRYP >6߱!N7^$%I [ig4yf _ )/Œ%J3TYhrOhmG"#t"}_ R/3RڒBd& $"r#آEuS0 yI|t4(nơJF{5-%.CK ɆT@bWH.7'R\:/:`eeeeB6Xv>`eeeeev>`S @d ԯVXS }{@(G(g  =oDQDiܔ[QRLS7Ý)d-tρ]sUZqZPQ)a0F7GBq)jgPU=7=!DQ4[s#]ءFūq@\Sd\c:cTXk䝐sΤo1W=ge >  ?\IE;7.%"B\d<0LJ8BZ ư0-,F1NH~'Ⱥ +d=b'7 WdaɄFY},>_ b7:z7ȺJo\ +I~DVjX)Wa aL|-H[w+'#&;a;M$N;awº }Yy y'*-[-v92`mNWz&kLz !AB !AB*Kh'lz'܃o|^7a<~ |)A?_Jϗ|)A?_Jp6{>& xah~E^IENDB`sigviewer-0.6.4/src/images/ic_chevron_left_black_24dp.png000066400000000000000000000002761345753661000234240ustar00rootroot00000000000000PNG  IHDR``HIDATx a sHH.++s? '$ޟ߲Kw}w}w}$7 $l$<%A 9QpN}.)r |i(W IENDB`sigviewer-0.6.4/src/images/ic_chevron_right_black_24dp.png000066400000000000000000000003031345753661000235760ustar00rootroot00000000000000PNG  IHDR``HIDATx @iMǠ7t${؃/i/~\c  9>10g&l"A $H A 6;57gg+SO=M gB{>~BvIENDB`sigviewer-0.6.4/src/images/ic_clear_black_24dp.png000066400000000000000000000005711345753661000220320ustar00rootroot00000000000000PNG  IHDR``H@IDATxiQE݀; hQ ya ~!{֚_8RJ)RJ)|dɈK^3k@5_#֟ @&HY’ydYvF a{ >H>N@qJ>O8}y+O>6DX'}} ^'xG/G` Ȑ ^L4>{O>K`>HO>M4ˆ0cn\sHtZx6M}bRJ)RJ)_Q0h}&IENDB`sigviewer-0.6.4/src/images/ic_content_copy_black_24dp.png000066400000000000000000000004771345753661000234550ustar00rootroot00000000000000PNG  IHDR``HIDATxAjAFSϪb/,ArEOlB65]4`Q3# 6Lt!FȀ#16xXFǪP\>Pp_ns3yL辕)Ј]#yX @ @ @ @?|MYֵp"3 9c&.^]fV` Fš{gg~>1c]?Q*ܪ^u |OOkOOXgJ8iO8(fC  ٪O]$|'=H[,&?pHX>!>!o&!o{qlOM0|7 Mˌ|ȇ>'wÌ|W;_| xTj竝vj竝v3c_bÏ%‰IENDB`sigviewer-0.6.4/src/images/ic_delete_forever_black_24dp.png000066400000000000000000000005711345753661000237360ustar00rootroot00000000000000PNG  IHDR``H@IDATxA`!]I&]f\N*@%0{l;/=/ / { @3+0 @<~2 OG[G)}! όa>!`q~@.?#l 4[5< "B<ՀϯĄx~= &!_ %<}ୄo N&#=V)8hpuܧο'!0m*Z?2BisFi)0ᜧos2p Oه{QIENDB`sigviewer-0.6.4/src/images/ic_directions_run_black_24dp.png000066400000000000000000000015641345753661000237760ustar00rootroot00000000000000PNG  IHDR``H;IDATxkWu=̼6FaHT.(D7‚.2zÇmM""FEE %RY\bX}b;g=tޟ_ʖ3d̘!*„U/s@B/Lhʤ6'lJ}c:&zS;D_{VgRv!9ST6;7j1;*+N^?쒟BjCBhRYZ預~b!s+E|k7.LqM70=/1a;zvf>vA-c8LpsMpCyr085"LcZ`bOX,dArÞU`KpJNdQހ whs& =k: |yڡ)!{92?_!F@{4`UO3+pDu b<wl7p4d5xʀ ]^uyϠ_wwD݆ In "Lh"M&PMC\"٭~I%DBՆ;O!DT$l0O>oYg&Tm#FQoF:!Y;Pg_>Bbӂەौ[cRj_I>f${1nf 31jZg/5MG9s'S x~hպ -~&r@<ۇN bkuȮdWJ@ (%PjSWUIENDB`sigviewer-0.6.4/src/images/ic_file_download_black_24dp.png000066400000000000000000000003211345753661000235430ustar00rootroot00000000000000PNG  IHDR`` PLTEctRNS꺌tIDATxͱ @P@QDiKW:A% gQ{5j<7֤#39kDBDBDBDBDB@$D$D$D$D$D$Dő.a!a ge6ppqIENDB`sigviewer-0.6.4/src/images/ic_file_upload_black_24dp.png000066400000000000000000000003261345753661000232250ustar00rootroot00000000000000PNG  IHDR`` PLTEctRNS+NzIDATxͱ 0K!<4M`*6-W[u;淜Hr"qd&@a@a! Jb F" @a!Phori~,8['IENDB`sigviewer-0.6.4/src/images/ic_flag_black_24dp.png000066400000000000000000000003041345753661000216470ustar00rootroot00000000000000PNG  IHDR``HIDATx Q@ac31$cxuKΙ[}M$I?zSKpUx]s03SF:Q\c$IF b%9<IENDB`sigviewer-0.6.4/src/images/ic_folder_open_black_24dp.png000066400000000000000000000004711345753661000232370ustar00rootroot00000000000000PNG  IHDR``HIDATxM@F᳋{AȔZ@IE1X$rbͥ/f;9t5l3qHP+/'㝨// %

O(! Ԓ`];=7c2V#GJwRlI S6Hb{a [7[z>@Z`)7`Q %`]k7HO&0dYӃ-+ޅ=tB_@<$T^Q_t<_}mvJ]KQOZ@3zu~FOK*R6_uI \w -^g.b HEFl\6UF%h֍ X xV*2BG6n-Q,J_0d΅Gf3܀Թ L!nCp&̀zu /iqL{ 陰T~1 '`i܁:M Rk Rx^L"x\tcHPt|.?@T,kVu40JWfrj$F>#A@)rx~xHPAfXŹ488N6TIENDB`sigviewer-0.6.4/src/images/ic_help_outline_black_24dp.png000066400000000000000000000030151345753661000234270ustar00rootroot00000000000000PNG  IHDR``HIDATxKLTW0 36"J ; 3qJtUh$i4SSFӅ6A Tqk\X۞swf=s峊r.y8f.p"))zZp4SA)"eF9La$b">bh!14CM)KM`()6iu,`a 3Tv,R$ ;)N)nم$H+|Q]7xQ4Fbx+l4*Q?IHFӼWta+_,F%(R B[,QtѦIZCL8l"Pi&C1 7i֪QC+eQ,G]`B<딃J4"jr q jdԢV6Ũ5TA~9󠶐'c}/? kr'JH߮ Ũ+R_J)'N$+5axPkwB}bɖJل3-PFYHŨ$Z5vF~fSsZkA(z?J/EKS^J4TrpEm6Mc/zXvEJBc58!R[X!fB'N J_u+uwqǕ`A-ֶV\Z%ytkLW`kJ;:4k_!G>.`Oj}bC~+*M/cTed7rTMUfG1LрiWK0:r';1`kT%H>cHLJ j40P ;ep C]>™BLGuit!mCiJ^!9 Ďx݇W߉ ;noث(n\xYq j@?3A!RE M& ,L=ZB-!&E&|7ۉ0,/\>Y`uz'XM)) i2w`wcI3u'-----M--IQIENDB`sigviewer-0.6.4/src/images/ic_info_outline_black_24dp.png000066400000000000000000000023501345753661000234330ustar00rootroot00000000000000PNG  IHDR``HIDATxOTWLbLEcVtqgbUC}D &|!&n5# iS#%uoCJ- m1BPE<ܗh~s}C$D">HWh%}3"1N/h U"員A yT?(CaTYޠr50"I=P>#u$ޢ|0Մf+Q-GfPe3*Cuceĉ#N9U:oa(,SEQX7J67O&arAg;cԑ‹ꙴhi`(%b^T/$Kv2=~H?-tjۥe҃o[J_2(`+3OP [Ϟ#O F..<:!hQ"x-rqL:+*kא~2 ֗p B( 7J@>d Y_xx`C gXJK#N BgzpW3 Ɉ4&lGi9#-Z+Lf҈6r3f'lDiIc1b[0&fs[W̑z--̠lR+99rK>dm^lk%eFؤ29$ne֢V3@Lea7ږPR.E,ݫm}7؀=VVrh7Q{x3cm 2QRa^^h_+hZJ^~yRaJ1aI21=m8!NzC;RzXCZ$E6Pʴ~ .Ԉ 4@?+)>h_h $qN 2@* Y\K0,iNQ8TD.k(x%Oq ϶sms Jl押d&Ĉd{pnj7@eP&&t6jQ>f,e>|8Y HbTxgoY (r>8L3zce^r,(&D"P G"IENDB`sigviewer-0.6.4/src/images/ic_pan_tool_black_24dp.png000066400000000000000000000011501345753661000225510ustar00rootroot00000000000000PNG  IHDR``H/IDATxqoj۶m۶c^?6/Nhm۶ݰw/7r>,)'E9Ҝ]vr$ŏJ!㑀:39YgF~DcFIOki[D`lEDF-*rc -'0r"8p8p@<80Xαdwt-U=xy{VQ=|@?f.)2`(/͛2$\,oD08)zx͑o ʅos"B@}NM!P҈shm46sU- @;nkwЉCmt6zTy ~^j`0h do\m€ѼOC!P/DQ2O@Ff9Ҙ"f6_bQk2E"-Q],wd˝<(i%|g:lz""""""""""2JMFͺNB5JyfyEN9K lXV@e\;i%bGa"}yt2I9:ʟcX9K]|v3E ]}E28:AS8k}86Z'G ,b Vvrr9e?c{b?wYݘbcs39 XJܦjb*n㡟o`ft2#`˩ƂI1F?!-P}na ?#5,~8<[9]p$>7$R"[p l$^+lW@}IENDB`sigviewer-0.6.4/src/images/ic_reorder_black_24dp.png000066400000000000000000000001641345753661000224040ustar00rootroot00000000000000PNG  IHDR``V{PLTEgtRNS@fIDATxcQ >АCgg?6lWhIENDB`sigviewer-0.6.4/src/images/ic_save_black_24dp.png000066400000000000000000000007351345753661000217040ustar00rootroot00000000000000PNG  IHDR``HIDATxQjQOv{S-HIJ硯!졔."yd"w޹s;7gRJ)u!9O3{P/X`Z|ǰd 0İ 96 K&0? L? @R 8   3WѤI tVgJ6ÝwB=n W+ML#:UkpELK1zhSB/iPD}JcJG@I*e`ƃ͚Z~{dyR8Կ2a lҹVyaɘ>}Ƭ(s4[ Ht]ns2{qB 'oJr^2/GRJ)BDIENDB`sigviewer-0.6.4/src/images/ic_undo_black_24dp.png000066400000000000000000000011311345753661000217020ustar00rootroot00000000000000PNG  IHDR``H IDATx׽kSaQ[Z2!Qď"b\֯E.]DQЭ'Ak:JE,C͡8`m:&u?rJ)RJ)RJݤͳv'X 2a'oa,R ӌql1[6! S|R| YQ&2x2`V'OudXMyp<3j%b=CvsXӽ{aKQXÕlb9eNoJI|L GA>62&G3^w"nc}yE,B? Y,Y,['B 7. |p"" ~06p"5'0XI6ת<kn"a!}t"y:RJ)RJ)RJ)y,Wj1IENDB`sigviewer-0.6.4/src/images/ic_zoom_in_h_black_24dp.png000066400000000000000000000021071345753661000227220ustar00rootroot00000000000000PNG  IHDR``HbKGD̿ pHYs  tIME  +"UnIDATxKA-Gu*ڑVI] ǖ6lL!'6'{m[2Pe?06m?0vp-:w_q>  HA&nt }E4G?BIpo6!=n 1K@6 _;-zMc]4L33@P<>KH<e+5.~c9et.. _Wtώ ER P@&?<65s[n %C0҈[[(gy \gRW.tZA-fXܧ!?U~jE͏{Y bYzm #룓rxE|/Kx^,6i!9GqBEvB4PË95Vc౓-U;yJ}ެYҸ8|2CO `XNPRRRRR: 5I sIENDB`sigviewer-0.6.4/src/images/ic_zoom_in_v_black_24dp.png000066400000000000000000000020771345753661000227460ustar00rootroot00000000000000PNG  IHDR``HbKGD̿ pHYs  tIME  0 WR:IDATxKAǿZx .ɮxzWЫH_JQ EZ2Eע` $jo*I5+ ӌzab733wW{ϳ()))))))\Yw؏~AѶ¼)mhڿ&|Ѳ-"]܊׶܁)H@Rgc=xЏ<ͨ| 1 gi:1̌HeAed˘pѱx.xE1kip2D0ԝHE%[ɠ5 1?F||:y?z. _W JODen*82@ e`Za ^3._ڲ0!dXMs˅j0G rjӚ{*5:F^i{H";\mqbtybyjlpt'Wld~-dM[,3<):$ZGt\N~Dp@wn 0*<0}O=rJS ~!˔p4bDiօTbJ9٧ĔYg}[h5m@"%\6PeΈ,Nl2m0Ň!/*w5/R}aI;Jſ9 o-b¦e#4Dpb֒*.5Ck{7dGOWsbP Lj5W aY׺S_7D0Dz ?'}(yYl-3BY~& :jAh<5 4ȏPP-?B<uRZ31L_K52Um?RցT%}۾_Rqn1IENDB`sigviewer-0.6.4/src/images/ic_zoom_out_h_black_24dp.png000066400000000000000000000021041345753661000231200ustar00rootroot00000000000000PNG  IHDR``HbKGD̿ pHYs  tIME  .)C4IDATxZKAhYd\]wxzjWSRH=&(,@PRIzAXif'ۃI633w38pp|ދ$"&6<ۺ E 9jEД~0_neY!>3,_=t">=3%IKDJ-斯@6nF˟GnÇ$!IHt㓆UƺibȿhͰ0!@cL1e2&Rx4W)5&Z~#`Kk\|j]hkRTMs=F/Ta)ΗW]5&xy+gH-L f3h`-4c"%svZfzpc)#~- |\`.H .$#ЃEd(rװ`4unk%~i.pɟF _Zp_ Bhyk r߆LT"n(n#Ğ}W,iJa~rw]dSn oA?7Aa),ZXh 5Pm GB},BJ[k>X"OPe)JyF-X*ˏ1h{+t#a1p3}qYIENDB`sigviewer-0.6.4/src/images/ic_zoom_out_map_black_24dp.png000066400000000000000000000010711345753661000234500ustar00rootroot00000000000000PNG  IHDR``HIDATxEbQ E=6,jqfvO)AB![XJP 0TE} !?` Qh~'hfUMGnmpBG9 OD5<OyۮbBiO(H]4:n@'` 'F>Z5`$/x70$xo# KP)a7 0}oJ)3%%lM ,Ae1 !B!|*|XLPV6 00}xB-jzb{W$wա$;aReŭ{+XTM.8ԭ(H:ӈc Ө%wfkVKh,zѭ>0{Qo5p87>@b@}@ɿo塏5Ƚ2]׫0F(a#ĞzRZkݏVƆƷ"Sr ]xy|EJu jh #T"TGBE(B(xn_KUvBvHt2/Pu~IENDB`sigviewer-0.6.4/src/images/sigviewer.ico000066400000000000000000003065761345753661000203140ustar00rootroot00000000000000 (f@@ (B00 %J  ^p  h(    #&+.1467777777777752/,($  %,39AHOV\`eimoooooooooomkhb]XRKD<5.'  )3>IS^gnuz|vqi`VL@6,# #0=KYfqz666555___\\\|||||||||瘘{{{|||ddd]]]III444|si\OA3&  !0@P`o{@@@]]]|||扉󖖖{{{bbbIII'''~seUD3% &9M`q~KKKjjjن󔔔qqqQQQ'''udR>, ';RhzRRR~~~쒒```'''oZD/#9RjIII}}}쐐XXXs\B* /JfZZZLJfff111oT8 7X~ZZZņrrr}bC& ;_@@@[[[ lJ);kmmm؈|||$$$pJ& 3fwww熆AAAkB $Y{{{@@@^17vvv⃃$$$uGcccoooY) (((2{{{AAAe1 ```y}}}bbbi3 mmmuuue1sssǘyyyY) nnnsssHlllg}}}ccc2UUUrrr|||PPPllllll& ccclllћnnn>>>QPPPkkk𑑑lllUUUxaaa"hhh}}}gggXXXsZZZggghhhrrreeeHHHC cccRfffpppyyyfff]]]444ZZZbbbcccdddxxxddd___OOO=ZZZ```bbbcccvvvcccccc^^^RRRJ ---"TTTm]]]aaaaaattt|||aaaaaa]]]VVV5559 $-3677777777777777777777%%%RHHHbbb{{{qqq___\\\ZZZPPP<<<=977777777777777777777750' -@R_imooooooooooooooooooooorRRRyyyfff+++wpoooooooooooooooooooooomkcWF3 $>ZoXXXxxxddd uaH-)Ii...hhh}}}昘lll???sU5(L###☘???|Z4 !FVVVlll|U,8ZZZqF $WWWlll_0$$$?555rAvvv~P#,,,Z* ZZZL^^^_- vvvvzzz`. }}}zzz`. }}}пϿϾννͼ̼˻˺ʹɹȸȷǷƶŵŴijó²ӿҾҽѼмкϺιθͷ̶˵˴ʳʳɲȱǰǯƮŭĬzzz`. }}}yyy`. }}}xxx`. }}}d$e&g(j*k,m.o/q1s3u5w7y8{:|<~=Ҁ?ӂAԃBՅDևF׈G؊IٌJڍLۏMܐNݒPݓQޔRߖTUVWXXYZZ[[[\\\\[[[ZYYXWVUߖTߕSޔRݒQܑOېNڎLڍKًJ؊H׈GֆEՅDԃBӁ@>}=|;z9x8v6t4r2p0o/l-k+i)g'e%c$a"_ ][YW۪xxx`. |||b#e%f'h)j+l-n.p0r2t3v5w7y9{;}<>Ҁ?ӂAԄCՅDևF׈G؊IٌJڍKۏMېNܑOݒQޔRޕSߖTUVVWXXYYYZZZZYYYXWWVUTߖTޔSޓRݒPܑOۏMڎLٌKًJ؊H׈GֆEՅDԃBӁ@Ҁ?~=|ҁ@ӂAԄCՅDևF׈G؊IًJڍKڎLۏMܑOݒPݓQޔRޕSߖTߖTUVVWWWXXXXWWWVVUߖTߕSޔSޓRݒQܑOܐNۏMڍLٌK؋I؉H׈GֆEՅDԃBӁ@Ҁ?~=|<{:y9w7v5t3r2p0n.l-j+i)f'e%c#a"_ ][YWU۩vvv`. zzz`!b#d%f'h)j*l,n.p0q1s3u5w7x8z:|;}=>ҁ@ӂAԄCՅDևF׈G؊H؋IٌKڍLۏMېNܑOݒPݓQޓRޔSߕSߖTߖTUUUVVVUUUUߖTߖTޕSޔRޓRݒQܑOܐNۏMڎLڍKٌJ؋I׉HևFֆEՅDԃBӂAҀ?>}<{;y9x8v6t4r2q1o/m-k,i*g(e&d$a"`!^\ZXVT۩vvv`. zzz_ a"c$e&g'i)k+l-n.p0r2s3u5w7x8z:|;}=>ҁ@ӂAԃBՅDֆE׈G׉H؊IٌJڍKڎLۏMېNܑOܑPݒPݓQޓRޔRޔSߕSߕSߕSߖTߖTߕSߕSޕSޔSޔRޓRݒQݒPܑOܐNېNێMڍLٌKًJ؊I׈GևFՆEە^崌䲋ؒZ>}<{;z9x8v6u4s3q1o/m.l,j*h)f'd%b#`!_ ][YWUSڨvvv`. xxx^`!b#d$f&g(i*k,m-o/p0r2t3u5w7y8z:|;}=>Ҁ?ӂAԃBՅDՆEևF׈G؊H؋IٌJڍKڎLۏMۏMܐNܑOܑOݒPݒPݒQݓQݓQޓQݓQݓQݓQݒQݒPֽߜbۏMڎLڍLٌKًJ؊I׉H׈GևFՆEԄC}<{;z9x8v6u5s3q1p0n.l-j+i)g'e&c$a"_ ]\ZXVTRڨuuu`. xxx]_ a"b#d%f'h)j*k,m-o/q1r2t4v5w7Ǭȭ}=>Ҁ?Ӂ@ԃBԄCՅDֆEׇF׉G؊H؋IٌJٌKڍLڎLۏMۏMېNܐNܐNܑOܑOܑOܑOܑOܑOܐNġ龙ڍKٌKًJ؊I؉H׈GևFֆEՅDԃBӂA罝z9x8v6u5s3r2p0n.l-k+i*g(f&d$b#`!^\ZYWUSQڧuuu`. xxx\]`!a"c$e%f'h)j+l,m.o/q1r2t4۞q଄}<~>Ҁ?ҁ@ӂAԃBՅDՆEևF׈G׈G؊H؊IًJٌJ䯀ێMێMێMێMێMێMޚ`؋I؊I׉H׈GևFֆEՅDԄCԃBӂAߦxx8v6u5t3r2p0o/m-k,j*h(f&d%b#a"_ ][YWUTRP٧ttt`. vvv[\^`!b#c$e&g'i)j+l,n.o/q1r2{;|<~=>Ҁ?Ӂ@ӂAԃBՅDՆEֆEևF׈G׉H}ֿٌKٌKٌKٌKٌKٌJ齘׉G׈GևFֆEՅDՄCԃBӂAӁ@Ҁ?v6u5t3r2p0o/m-k,j*h)f'e%c$a"_ ]\ZXVTRPO٦sss`. vvvY[]ܪݫެ٠xj+l,n.o/q1Ǭ溘~>Ҁ?ҁ@ӂAӂAԃBՄCՅDՆEևF浌؊I؊H{ՆEՅDؑXxߥw؏UҀ?>ɮЄKⴓӎ[m-k,j*h)f'ޭܩ\ZYWUSQON٦qqq`. vvvXZ[ɱzzևFĦԾ~=}<Ƭͷg'v>ϋ^ҔmTRPNLإqqq`. vvvVXZһՅD̲ȭȭv6v>伡˄YQOMK ؤqqq`. uuuUWY䱈ؐVåƫu4ç伡ONLJ פqqq`. uuuTUWḝ~E˰嶑Ҁ?ژcԊPt4s3ρHNLJ I ףqqq`. sssRTVj3_ a"b#d%l-¨ЂIлѼ۞q廛ܟrՋSՌSԾ}<ՋR帖y8廛r2q1p0zB}LλɁUMK I G עppp`. sssQSTVWΉ\ܬϋ_^_ a"b#Ґck+l,֗iⶖטkp0q1ЂIԏ[ЃKu5v6w7ⱌܡs{;{;|;ӽӾݢt{:{:帖w7w7v6ؚlp0o/n.౏㸚g(f&v=ҏbYWƱŰPOMK J H F֢ooo`. qqqOQSTVWY[\^_ `!b#i)j*k,l-m.n/p0p0q1r2s3t4u4ЄKx8y9y9y9ӉOה`ӉPz:y8x8x8۞q庚ڝpu5u4t3ʳo/n.m-l,k+j*h)g'f&d%c$a"WUg/sBc,OMKJ H F E֡nnn`. qqqNPQSTVWYZ\]_ `!㻠g'h)i*j+k,l-m.n/o/p0q1r2s2s3ڜnv6w7w7w7w7w7x8x8ⱍv6v6v5u5u4t3s3r2q1㷗ⶖm-l,k+j*i)g(f'e&d$b#a"`!ů{IUTRQONLJ H F ECՠnnn`. qqqLNPQSTVWYZ\]^ r:e%f&g(h)i*j+k,l-m.n.o/p0p0q1r2r2s3s3t4t4u4u5u5u5v5v5хKt4t3s3s3r2q1q1p0p0טk֖ik,j+i*h)g'f&d%c$b#a"_ ^ϋ_vDTRQONLJ I G EDBՠmmm`. oooK LNPQSTVWYZ[\^㼢佣c$d%e&f'g(h)i*j+k,l,m-m.n.o/p0p0q1q1r2r2r2s2s3s3s3s3s3ĩr2q1q1q1p0o/o/n.m.l-l,k+j+i*h)g'f&e%d$b#a"`!_ ]\[g/RPONLJ I G EDB@՟lll`. oooI K LNPQRTUWXZ[\]_ `!a"b#c$d%e&f'g(h)i*j*k+k,l-m-m.n.n/o/p0p0p0p0q1q1q1q1q1¦p0p0o/o/n/n.m.l-l,k,j+j*i)h)g'f&e&d%c$b#a"_ ^]\ZY٦̺RPONLJ I G EDB@?ԟlll`. oooH I K LNOQRTUVXYZ[]^_ `!a"b#c$d%e&f'g'h(i)i*j+k+k,l,l-m-m.m.n.n.n/n/n/n/n/~FȰn.m.m-l-l-l,k,j+j*i*h)g(g'f&e%d%c$b#a"`!_ ]\[ZXWVh0tBd-POMLJ I G EDCA?>ԟkkk`. oooFH I K LNOPRSUVWXZ[\]^_ `!a"b#c$d%e%f&f'g(h(h)i*j*j+k+k+k,l,l,l-l-l-l-l-l-l-l,l,k,k,k+j+j+j*i*h)h(g'f'e&e%d$c$xB؟yמxv@^\[ZYXWUTSQPOMKJ I G EDCA?>>ԟkkk`. oooEFG I J LMOPQSTUVXYZ[\]^_ `!a"b#c#d$d%e&f&f'g'g(h(h)i)i*j*j*j*j+j+j+j+j+j+j*j*ǯyAh(g(g'f'e&e%d%c$b#a"a"\[ZXWVUSRQPNMKJ I G EDCA?>>>ԟkkk`. nnnCDFG I J KMNPQRSUVWṟ⺠[\]^_ `!a"a"b#c$c$d%e%e&f&f'f'g'g(g(g(h(h(h(h(h(h(g(߮ܨf&e&e%d%c$b#b#a"`!`!_ ܬYXVUTSRPONLK J H G EDBA?>>>>ԟjjj`. lllACDEG H J K LNOPQSṪZӖoZ[\]^^ _ `!a"a"b#b#c$c$d%ӑeӒee&f&f&f&f&e&v>c$c$b#b#a"`!`!_ ^]ϋ`WVUSRQPOMLK I H F EDBA?>>>>>ԟhhh`. lll?ABDEF H I K LMNPQRμXYZ[[\]^^ _ `!`!a"a"Ӑdʳj*j+l,l,l,l,ޫh)h)e&e&b#a"^]\[UTRQPONMKJ I G FECB@?>>>>>>ԟhhh`. lll>?AӚzԜ{ԝ|΍fK LNOPḞڧZZ[\]`"d%g(i)k,᱐ۤ{n.n.ѽ֗jl-l,{CՕgՔgzBh)e&佣f.أпtDMLK J H ԝ|Ӛz@?>>>>>>>ԟhhh`. jjj>>?⽥ޯϽ֗jטk᳑p0亝θk,k+徤޴޳H [$wLɅ_>>>>>ԟggg`. jjj~~~>>>̵r2ū¨j*[$ܯvK>>>>ԟfff`. jjj~~~>>>ިЃK潟l,濤ۯລ>>>>ԟfff`. hhh~~~>>>ڬi2Ǭᰋv6֐]ЂJo/n.}D຤>>>>ԟeee`. hhh}}}>>>S?@BCi*~EϹкٚm丘ڜn҇N҇NҼx8҇N䶔v5乙q1p0o/zBg7ƴvJ>>>>ԟeee`. hhh}}}>>>>>vJӞvJ>?@AxMk,l-חjⶖטkp0q1ςIԎ[ЃJu4u5v6᱌ܟrz:z:{:ӽӽܡs{:{:帖x8x8w7ٜns2r2q1᳑亜l,k+zBԓf>>⾪⾪>>>>>>>ԟddd`. hhh}}}>>>>>>>>>>>F ]m-n.o/p0q1r2s3t4u5v6w7w7x8ӈO|;|<|<}<ՋRٖcՋS~=}<}<|<ܢs漜ܡs{:z9y9̴v5u4t3s3r2q1p0o/m.l-k,j+ëI >Sc2S>>>>>>>ԟddd`. gggvvv>>>>>>>>>>Rg(i)濤o/p0q1r2s3t4u5v6w7x8y8z9z:{:ܢs~=~>>>Ҁ?Ҁ?Ҁ?Ҁ?嶑>>~>~=~=}<|<|;{;漜廛w7w7v6u4t3s2r2q1p0n.m-l,ʳ΅Tc$V@>>>>>>>>>ԟccc`. gggvvv>>>>>>>>A\h(i*j+|Cq1r2s3t4u5v6w7x8y9z:{:|;|<}<~=~>>Ҁ?Ҁ?ҁ@ҁ@Ӂ@ӂAӂAӂAӂAؐVӁ@Ӂ@ҁ@Ҁ?Ҁ?>>~=}=ݢtܠsz9x8w7w7v6u4t3r2q1p0o/n.֖ḯPd%c$_ G >>>>>>>>ԟccc`. eeeuuu>>>>>>>Fa"h)j*k+l,m.èér2t3u5v6w7x8y9z:{;|;}<~=~>>Ҁ?ҁ@Ӂ@ӂAӂAԃBԃBԃBԄCԄCԄCՄCՄC˰ԄCԃBԃBӂAӂAӁ@ҁ@Ҁ?Ҁ?>~=}=|<|;{:z9x8w7v6u5t4s3r2q1p0n.x@f&e%c$a"K >>>>>>>ԟbbb`. eeettt>>>>>>Fd%h)j*k+l-n.o/p0r2s3t4u5w7x8y9z:{;|;}<~=>Ҁ?ҁ@Ӂ@ӂAӂAԃBԄCՄCՅDՅDՆEֆEֆEևFևFևF˯ֆEՆEՆEՅDՅDԄCԄCԃBӂAӂAҁ@Ҁ?>>}=|<|;{:z9x8w7v6u5t3r2q1p0Აi*g(f'e%c$a"O>>>>>>ԟaaa`. cccsss>>>>>Fd%h)j*k,l-n.o/q1r2s3u4v6w7x8z9{:|;}<~=>Ҁ?ҁ@ӂAӂAԃBԄCՅDՆEֆEևFևFևF׈G׈G׈G׉H׉H׉Hۖ\ҹ׈G׈G׈GևFևFֆEՆEՅDՄCԄCԃBӂAӁ@Ҁ?Ҁ?>}=|<{;z:y9x8w7u5t4s3q1p0FщV|Ck+i*h(f'e%c$a"M>>>>>ԟ___`. cccsss>>>>Cd%h)j*k,l-n.p0q1r2t3u5v6x8y9z:{;|<~=>Ҁ?ҁ@ӂAԃBԄCՅDՅDֆEևFևF׈G׉H؉H؊H؊I؋I؋IًJًJًJًJًJًJًI؋I؊I؊I؉H׉H׈G׈GևFևFՆEՅDԄCԃBӂAӁ@Ҁ?Ҁ?~>}=|;{:z9x8w7v6u4s3r2p0o/m.l,k+i*g(f&e%c$a"K >>>>ԟ___`. cccrrr>>>>_ h)j*k,l-n.p0q1r2t4u5w7x8y9{:|;}=~>Ҁ?ҁ@ӂAԃBԄCՅDՆEևFևF׈G׉H؊H؊I؋IًJٌJٌKڍKڍKڍLڍLڍLڍLڍLڍLڍLڍKڍKٌKٌJًJ؋I؊I؉H׉G׈GևFֆEՅDՄCԃBٔ\䲋㲋בZ~=}<{;z:y9w7v6u4t3r2p0o/m.l,k+i*g(f&d%c#a"D>>>ԟ___`. aaaqqq>>>Rh)j*k+l-n.p0q1s2t4v5w7x8z9{;|<~=>Ҁ?Ӂ@ӂAԄCՅDՆEևF׈G׉G؊H؊IًJٌJٌKڍKڎLڎLێMۏMۏMېNېNېNېNېNېNېNռޚ`ڍLڍKٌKًJ؋I؊I׉H׈GևFֆEՅDҀ?~>}<|;{:y9x8v6u5t3r2p0o/m.l,j+i)g(f&d%b#Z>>>ԟ___`. aaappp>>Cg(i*k+l-n.p0q1s2t4v6w7x8z:ȭɮҀ?ҁ@ӂAԃBՄCՆEևF׈G׉G؊H؋IٌJٌKڍLڎLۏMۏMېNܐNܑOܑOܑPݒPݒPݒPݒPݒPݒPŢ뿚ېNۏMێMڎLڍKٌKًJ؊I؉H׈GևFҀ?>}=|<{:y9x8v6u5t3r2p0o/m.l,j+i)g'e&d$b#O>>ԟ^^^`. aaappp>>Xi*k+l,n.o/q1r2t4v6w7x8z:ݡt㯇ӂAԄCՅDֆEևF׈G؊H؋IٌJڍKڍLۏMۏMܐNܑO求粄ޔRޔRޔRޔRޔSޔReݒPܑOܐNېNۏMڎLڍLٌKًJ؊I}ӂAҁ@>~=|<{:z9x8v6u5t3r2p0o/m-k,j*h)f'e%c$_ @>ԟ^^^`. ```nnn>Ci)j+l,m.o/q1r2t4u5w7x8z:|;ԄCՅDևF׈G׉H؊IًJڌKڎLۏMېNܑOܑOݒP粄ߖTߖTߖTUUTÝޔRޓRݒQݒPܑOܐNۏMێLڍLٌKԃBӂAҁ@>~=|<{:z9x8v6u4s3q1p0n.m-k,i*h(f&d%b#M>ԟ\\\`. ^^^mmm>Qj*ఏᲐ᳑ިw7x8z:{;}<ً̱IٌKڍLۏMېNܑOݑPݒQޓRޔRȥ쿕WW贆ߕSޕSe求求ߝcܐNۏMдْY轛ښg~=|<{:y9w7䶔᳑n.l-k+i*g(e&d$[>ԟ[[[`. ^^^mmm>_ k+Ϸɪ贅贆ʧYίݒPܑOϴԽɮȭ{:ӈOؙlڡyh)f'e%c$Cԟ[[[`. ^^^lll>j+l,[ֻҷҶڎLԊQƪՕhg(f&d%I ԟZZZ`. \\\kkkDk,m-™mбѵېNβǬʴi)g'e&QԟZZZ`. \\\jjjI l,n.ڔ[׼Ȣ^|jݒQܑOߜbʳj*h(f&QԟYYY`. \\\jjjI m-o/ρHz9{;}<>׉Gγߜb赆˪귈pq`q˨ZͫޔRݓQܑOܗ\Ͳؕb֖ik+i)g'RԟYYY`. ZZZiiiDn.p0q1s3ڝo庚ܟq{:|<~=Ҁ?ߥw؊IٌJƥ氁ݒPޓRfuiWXYƠ`ab￐baΫ]\[赆ߖTޔRݓQġȪ؋I׉Hڔ[zz9x8Ѽкq1o/m-k,j*h(RԟXXX`. ZZZiii>o/q1r2t4v6x8z9|;}=>ҁ@ӂAًJڍKۏMܐNݒPޓRޕSߖTVWXZ[nabccuvedccѯ_^]VUߖTޔRݒQܑOېNڎLٌK؋I׉HևF͵{:y9҆MՐ\ЃJr2p0n.l-j+i)MԟXXX`. ZZZhhh>g'q1s3u5w7y9{:|<~>Ҁ?ӂAԃBʯٌKڎLېNܑOݓQޕSߖTVWXZ[\^cdeefgggΧfeddcba`_ϭͫXVUߖTޔRݒQܑOۏMڍLٌJ؊I׈GӼڙf|;z:x8v6u4r2q1o/m-k,i*FԟVVV`. YYYggg>[r2t4v6x8z9|;}=>Ӂ@ԃBՅDړZڍLۏMܑOݒQޔRߖTUWXZ[]^`abcdefgghiiizhgfeedba`빊YXVUߕSޓRݒPܐNۏMڍKًJ׉H{ڗc|<{:y9w7u5s3q1p0n.l,e%>ԟVVV`. YYYfff>H s3u5w7x8{:|<~=Ҁ?ӂAԃBՆEևFͲϴۏMܐNݒPޔRߖTUWXZ[]^`abcefghhijkklljihgfedcb`_^\ZYWVߖTޕSݓQܑOېNڎLٌJ؊I׈G֍S}={;z9x8v6t4r2p0n/l-W>ԟUUU`. YYYfff>>f'v5w7y9{;}<>ҁ@ӂAՅDֆE׈G؊IٌJڎLېNܑOݓQߕSUVXY[\^`abdefghikllmmnnmlkjihgfdcb`_]\ZYWUߖTޔRݒQܑOۏMڍKًJ؉H鿝Ҁ?~=|ԟUUU`. WWWeee>>Lv6x8z:|;~=Ҁ?Ӂ@ԃBՅDևF׉H؋IڍKۏMܑOݒPޔRߖTVWYZ\^_abdefhijlmmnoopponmlkjhgfdcb`_][ZXVUߕSޓRܑOېNڎLٌJ؊I׈GړZݜgؐVҁ@>}<{;y9w7u5s3q1p0Y>>ԟUUU`. WWWddd>>>b#x8{:|<~>Ҁ?ӂAԄCՆE׈G؊HٌJڍLېNܑOݓQߕSUVXZ[]_`bcefhiklmnopqqrrrrrqpponmljigfdca`^\[YWVߖTޔRݒQܑOۏMڍK؋I׉HևFՅDԃBӁ@Ҁ?}=|;z9x8v6t4r2m-A>>ԟTTT`. WWWddd>>>Br2{;}<>ҁ@ԃBՅDևF׈G؊IٌKڎLܐNݒPޔRߖTVWY[\^`acefhiklnopqrsstttttsrrqonmljhgedba_][ZXVUߕSݓQܑOۏMڍLًJ؊H׈GՆEԄCӂAҀ?~=|>>ԟTTT`. UUUccc>>>>I x7}=Ҁ?Ӂ@ԃBՅDևF׉HًJڍKۏMܑOݒQޕSߖTVXZ[]_abdfgiklnoprstuuvvvvvutsrqpnmljhgecb`^\[YWUߖTޔRݒPܐNڎLٌK؊I׈GֆEՄCӂAҁ@>}<{:y9w7u5\>>>>ԟSSS`. UUUbbb>>>>>U~=Ҁ?ӂAԄCՆE׈G؊HٌJڍLېNܑOޓRߕSUWXZ\^`bceghjlmoprstuvwxxxxxwvutrqpnmkigfdca_][YXVߖTޔSݒQܑOۏMڍK؋I׉HևFՅDԃBӁ@>}<{;y9w7a">>>>>ԟRRR`.SSSaaaiKiKiKiKiKiK|X…TÇVĈWŊYƋZǍ[Ȏ]ɏ^ʑ_ʒa˔b̕d͗eΘfϚhЛiќkўlҟmӡoԢpդq֥rצtبu٩v٪xڬyۭzܮ{ܯ|ݰ}ޱ~޲߳߳ߴߴߴ߳޳޲ݱ~ݰ}ܯ|ۮ{ۭzګx٪wبvקu֦s֥rգqԢoӠnҟmѝkМjϚhΙgΘf͖d̕c˓bʒ`ɐ_ȏ^Ǎ\nj[ƊZʼnXćWÆU…TRQPWiKiKiKiKiKiKϴQQQ`.TTTaaaQQQ_- UUUaaaQQQZ* WWWaaaRRRP#VVVjaaaSSSASSS7aaaoooEEE0___└aaa+++j\\\hhh[[[.PPP```𔔔aaa@@@v\\\SaaahhhWWW^^^aaahhh\\\'''' ]]]saaa}}}aaa[[[...![[[2___aaavvvhhh___WWW{ ^^^A___```aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa```]]]YYYgBBB????????(@    "0=JV^fiiiiig`WL?2%  5O m(((:::MMM___kkkuuu}}}|||||||||||||||wwwlll```OOO999&&& hR9!,T$$$JJJjjj~~~튊~~~kkkKKK&&&xV4 ) `FFFqqqߊrrrGGG`2DHHHxxxꡡJJJ K RjjjңoooR"""ӂAՅDևF؊HڌJێLܐNݑPݓQޔRޔRޕSޔRޔRݓQ鼕tڎLًJ؉HևFՄCݟnڙhx8u5q1n.j*f'b#_ [Ua(/yyyr?^d%g(k,o/r2u5ЂF罜Ӂ@ԃBֆD׈G؊HٌJڍKܗZ꽗寀ېNېNۏM踐؉HׇFօDԃBҁ@Ǭu5r2n.k+h(d%`!\XS_&/wwwo=[s<Օj؝tטko/r2ஈⰉ᫁ӂAԄCՆEևF׉G泉䮀؋I؎QՆGْZӂC֏XІOުs7h(d%՘pڥl5UP]$~~~/wwwm;Xݭ㱇ũϹɰˀNҖq[!~~~/uuuj9UՙrԽä˴шSX~~~/sssh6R\ ݯůb#e%ⶖᲐ̵ԏ[Ĩٛl֓_҄Fȭ幘଄çцNטjl-~J|K㾧yKV}}}/rrre4OUX\^a"מvᴔk,m.o/q1s3u4۠sⱍx8{=уHݣw㴑v5Տ[|Aq1k+i)f'd$a"^ͻR["OES{{{/pppc1L RUX[^d'ڡ{g(i*k,m.n/p0q1r3s3t3t4t4w9ީq1p0n/m-ԓdӑcg'e%b#`!]ZߴߵOK H BPyyy/ppp`.H ORUXZ]_ a"c$e&g(i)k+l,m-n/n/o/o0o0o0Ǯm.m.l,j+i)g'e&c$a"_ \ZWh1ߴr@KH E?Nxxx/ppp]*ELNQTVY[]_ a"c$e%f'g(h)i*j+k+k,k,k,k+j+ۤ~ЉWg(f'd%b#a"ͅVλɀPXVSQNK H EB<Mwww/nnnY(BH K NPSUc)ܫ]_ `"b#b#d$d%q6ۦԒdg'g'f'٠xc$a"_ ^]ḝTRPMJ H EB><Mvvv/nnnV%>Z$ȁWˉaɂVOQԚvԚtђi\`!c$f'h)ڠwיlm-t8j,yBd'r=i4җsUI G Ɇ]ЕtT><Mttt/jjjU#;Ԟ㶖ܣz徣ʳh7ˌiMsss/jjjT#;Ɇ`Ϻ澟ҾɲτOMrrr/jjjT";CԠ຤?H ⵖᲐ˴ӌYçؙj֐]ЁCǬ幖ૃçцNؘkn.΂Nj;߸pEMqqq/gggS";>=>Oe&ۣ{㷗q1s3u5w7y9z:ݣw䴏=҂CՉMz帕}<ٕa҃Gy9t4r2p0n.k,i*̺?LC<Mooo/cccR!;=@Wj*l-q3ުu5w7y9{;}<~>Ҁ?Ӂ@ӂAԃAԃBԃBՆG䳌Ӂ@Ҁ?>}=ܟp۝nx8v6t3q1o/l-弟佢XA=<Mnnn/bbbR!;@Zk+l-o/r2t4w7y9{;}<>Ӂ@ԃBԄCֆEֆEֈF׈F׈G׈GзևFՅDՄCԃBӁ@Ҁ?~=|;z9w7u5r2p0~E濤υSf&ZB;Mmmm/bbbR ;Wk,l-o0s2u5x8z:|<>Ӂ@ԃBՅDևF׈G؊HًIٌJٍJڍKڍKڍKٌJًJ؊H؉GևFՅDԃBӂ@ӄEږc@x8v6s3q0m.j+g(f&X=Mlll/```PI j*m-o0s2v5x8{;㱉ؒ[ԂAՅDׇF؉HًIڍKڎLۏMܐOܑOܑOܑOܑOcϳڍKًK؉IׇFօD绗ǫ|;y9w6t3p0m.j+g(d&MLjjj/^^^R ]m-o/r2u5x8|;ܟoևE׈HًJڎKۏMܑPݒP꼔ߖTߖTߕSֽܑOۏNڍLًJ؊H>|ԃBևF؊I軒iߖTWZ]`cehjkmnnhfda^[XߖTݓQېNٌJ׈G⮃嶓x8u5r2d$Paaa/SSSKI w7}=Ҁ@ԄC׈GٌKېNޔRUY\_behkmoqrrŐѨnlifc`]ZVޕSܑOڎL׊HՅE֋OҁBz:v6t3NKaaa/RRRJ7W}:Ձ>ׅBډF܍JޑMQUY\_dgjmprtuutrqnkgd`]YVRߓOݏKڋG؆Cւ?~;z8w5]8J___/PPPgL_=bA|UY[^`b’eĔgŗjǙlɜoʞq̡sΣvϥxЧzѩ{ӫ}Ӭ~Ӭ~Ӭ}Ѫ}ШzϦxΤv̡t˟qɜpǚmƗjĕhÒfda_\YWTzSdB^=mN]]]/QQQ___*SSSzXXXNNNAAAAqqqvvv,MMM+zzzEEEUCCC"jjj𰰰oooDDD?III&NNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNANNNARRRARRRARRRAIII-??(0` )4=BBBBA90$  "Gi!!!---999AAAGGGJJJJJJJJJJJJGGG>>>666))) pR1F}CCCzzz푑mmm555X$ B:::rrr棣___!!!^XqqqܻVVVy@mmmb ggg333UUUBBB7773 aaaD %333^^^quuu(((F3ABBBB>8Znnnooo,,,L6@BBBBB>) 8999^^^cccbbbbbbbbbbbbaaa```^^^\\\’VVVZZZ___aaaaaaaaaaaaaaaaaaaaaYYY,,,X 2cccX uuu@@@$*;999PC666TȲȰʲ̵ζиѹһԼֽ׿׾սԼҺѹϷͶ˳ɲȰƮĭ俧C666Te)d#k*p/u4z9=ԃAׇEٌIۏLݒOߕRTUVWWUTRޒOܐLڌI؈FքBӀ>{:v5q0l,h'c"^QЈZC333Td)c"j*n.s2w7{;>ՃBׇEيHڎKܐNݑOޓQޔRޕRޔRߙ[氀ܑPڍKًH׈Ft䱊|;x7t3n/j*e&`!\O ΆYC333Tb'` f(k,p0t4ݣwՉNԃBֆE׈GًIܔWǧ沅ۏMۏMѶߟi׈GֆEԃB֓_u5q1l,g(c$^ZM ͅXC333T_$j/ᱎѻ巒繕淑ǩx˯Ŧ缙ߦyθު|Eͺՙri2J ̃VC333T[!i0¢ѽගFʀTC000TWUϋ_ՙqc$ᵕՓe㴔Ր]ݤyӉR֍U¤͵ؕaަ|潞цQ֖i͸υSѿأߴi5C}QC000TTQW[^ xByBk,m.p0r2Տ\ૄv6w8}@фKx;s4Ւa˴k,i)f&c#юaڥUQK ?{OC000TOM RVZ]}If(f'h)k*l-n.o0p0p1p1廝q4n/m-k+i)f'd%a"^b'㽥xFOKG :xLC---TKH NQUX`$xD`!b#d%f'h)i)j*j+j+j+͂Mⵖm0f'd%c$ڣª`#XUQNK G C6wKC---TF DV]%US֝y{Ie,^`!b#{Fಒw=j+ѾψWe'c&a%Pa(PMZ!TB?5wKC---TC R˹κҾʳϺߪл߰îvH޷j;5wKC***TB Jͼѿ̴ߩ߭§٪5wKC***TB<V a2H ڣ~шT֕e}C҉R}@҃Gߧ|㳍֐YħؖeⲎC҉T߫w<彡ůrE~WG 6wKC***TA<>Lf'x=ρHv6x8{:}<ԈMڗcҁ@ӂAӄD֍SҀ?~=בZ㳎x8w6t3q1ҍ\ݩ\F>5wKC'''TA9Ql-o/q1t4x8{;}<Ҁ?ӂAՄBֆDևFׇF׈G䱆âևFֆEՄCԂAҀ@~=|;y8v5u6ۣz{Ci)c$G 3wJC'''T@Pj+n/r2v5{<ӆL?ӂAՅDևF؉HًJڌKڍKڎLڎLޚ`蹑ٍN؊H׈GօD⭂@z:w6s3o/k,h(`!>uIC'''THg'o/r2v6z:᭄ّW׈F؋IڍKۏNߜ`׿꽕ޔRޔRrېNڎLًJܛh>{:w7s3o/j+h(TxLC$$$TŽS{@ɮͰдֽ̭켑ҷ꽖ŧؔ`㷘σO]ʁTC$$$TûZ |@ȣǥսa̅XC$$$T\!t2ד`ݠqр?辜t鹏kgp̧յ}컌̩hwˮޚaӻߩⳑ}Dd!͆XC!!!TVv5z9~>ԃBړYߜcߕSWZ^tᅬfglveb~ѱXTݒPێLv巔{;v6q1e#ʂUC!!!TIu4|<Ҁ?ՅD؊Iݙ]ݓRVZ^behkmnӭlifc_[VޕSܐNڏPڕ_}׆CیHݐLQV[_cgknqrrqolhd`\WSߒN܍I؇DՁ>}:y6m+?oEC!!!TR)P$p@ȅOɈŘVϐZѕ^ԙb֝fסiۥmީqtwz{{zxuީrܦn٢j֞fԙbі_ϑ[͍WʉSȅOƁK~Hd6IeD"""R>-rrr!nnn444~$~~~aaaPPPfff񍍍򀀀JJJ??( @ 6JVXXXO<$ /oEEEfffӄꚚ~~~```<<<x:)AAA껻uuu---B&hhhA^^^999xxxLLL777.:::#^^^ 0WYXPRvYYY:::mMRXXY> ///g򹹹} .?HHHf'''bJJJmܪ߫ⱌ䵐渓軖꿙ğƠơơŠĞœ꿙軖巒㳎ொݫܧנ{ݯ(((dIIIl^`j&q-w3}9׃>ډCݍGސJߒLߒL[ޔRۉDׅ?ޝhҀ?q-j&c \O l5&&&cFFFlc'u;ЄNr3Ȯ嶒׍RׇF؊HͰ踏ܖY،MՈJ滛ЃKl,τRd'Sp<&&&cFFFl]#оɯ˄Xl9&&&cDDDlXm6yDӐcזhԍZ҆Mޤx⯉ᭆ֐[y=ީ͂Oۨ՛vTg5$$$cBBBlRPY_!Ԕif'j+n-p0q1r2ު¦p0m.~Gg(c$^൚tCNBc0$$$cBBBlKJ RW˂Rq:a"d$g'zCs8i)ުҎ^e&b"ë͆XVQMG ;`-$$$cBBBlD Ԝ|עഗޮڠxީ亜כqߵzMƴїvL`-!!!c???lB ҙzἧdzѽȯ̳ȮחhκnF`-!!!c???lA;Tz@u5x8|;ߨ|֍SԄEʮԆHр@x8t4p0ԔiQ7`-c===l@Vo/s3w7|;Ӏ?ՄCֆE؈G؊Iݛdq׉HևEՃBԇJ|laRP XXXIJЅTԽϴռսһ¨ǰ] VVVO h(§}AրB孄ۏVŧ꾝ۑZ繗D҄Ps=K TTTݽ=J[h)]bn,r1ޡvbbԎ_P _#=?SSSظhC忬Ű绞涖龠迣彤٣ܪHRRRֶ;d2ʴ؋TېX꼙hεäoǫ؎WۙjyTAPPPԲ;ex4y1ڀ8݄<߇?Vo݅<ہ<یOr+ևN[EOOO|||Ӳt:䬁鷑가z﹈췋ߜhܙh_MMMzzzӳ~C趐›ɤѮյ1̮Ħq3LLLxxx˨V {/^EP\`ÄǏZ`H?~p$WLLLyyyҿyQԞqإyܬ᳆溍•漍ⵇޭإyԟrΕj}XMMMWWW222pooo <| @ @ @ (   0000nNNNXXXYYYKKK---q4 gggWWW:::N$$$L sss "dddloohhjyz{YY[bbbUUU +cccӒeؖeޡpx}沂xߧyזeЉXΎdxxxʁP㶖轛˯ɫ渓߬߰m7uxx`'n5ךpz?ٚkૅᮉ؛ozB٢~~P^(uxxb/}PܫЊ[ٟv؛oχVĭtCuIX$uvx[)Џf徣۠u缜ɯƪٛmĭפ^,uvxZ q1ؒ\ֆEݕYݘ[屄؉H|}?i)c-uvxҒcζҵԺ΂Ouvxe+ҁAݜdZllݕRܞiAn7x{{˽suu<<abKGDC pHYs  tIME l IDATx}ixו[ի[ݒՒZ+]X`;v2&$LMY2&3;dIkl6$ 8b֬YFɛ-}tfϞtdggߐU>˲u秧C#-- ,h.++[ j E|4MΙ37$:ʆ'X(BZZ, n7v;<2N[ntǹǏFZBN\$:<fH̿), OƵieYo, aT׋H$rWzqv=Ȍ<,K7 #@`Y ߏj*//FEEbYE xP' J ^m.ҝ9Aq'ES)r>ű>Η~!ns+T= ,XV?+>窏_a3,LݚYbD5 XUh&:jp80-;tҠX~["(XiH ϡAS2@@%k Fβ,c ǀA# )[ƎM X\aHɄ@K:(ՄlQD#7`)cǂeYn~Ca1YBX*sS'vD'4eC,@kK)`@IiLd$+A8 @j\%RpY`Xf>Arpmy5BjZCUfAuE@ G2q_v}!  % 7L_`>2AT\Ѩz))z7/\ԍo \)|30,aAp>LH^N ].nV.`|Na$̘F:t{t՛ ,Ra$P=z4x fe~S.aavNv0%A3I`a3,X(ee#=M@ ݃Q05u:\:S$_`T>t$ GPiYPwY\0iT_{rlS#0,FӒ&0_YƶL×We4*k|I8& {L|ɋcqΪGQƽ2I၊,\/l+]/4z6H2N֡0崩욠I' e3 2kezllMY㴇S  叾b;ϲl6'ψď׸07$=/ma$ 2,5hdXf7_  wHfR97g%N<4ǫzP@y _YSmjߠj_| kP=CPB Јr%N=&8.$/tHX5ˡο!oP^ِj@8ߘ*qV5cA ˰HȂt<ߤ f $XlR=AGp\-`vArYu`cRGvX@gf In(0 ): (iyeVk p_,bâ -kFCw'ZB N; G!P)sr 8YȌc-a|FNN Y_nÉa1&0 |38-`DR<G,S NWGc щYHݻ3zd |ҚFF=- 0*Y EkMIͲ,_Vi4U*ըyȲ@ :y`^ I[J*f?ڜGhF,oN F}Z9quh>4 RoT3 3'gRh96Yf?`e g|qfP~\Ųi6jWwS*`&A Fpl\?Huy` <en4N e38})OTVuGŹߎ5 %,|i61B8O0 Rc4{}ٹxa/˫fѸ]al9]1 !yT/cW/-!Ջ:/#D$p$+cY}aX&VܱOrW{vblj>c4LkFq%fa`(-H?G 64tE0%G>ԺCX;ώ=þAя(qrjfʡ~|r)Wɴ%oD 1E.݅Ʈ0ɉ0~Qζ6qVuɕ9Yc <؅}:ӧ5s5#KJ $:L:6/w /j/$g|= aQ4vF;;;eF|̟LGwPЛ ?i bryHr`Y׮nLuU+g5Ə{n5X_ӁԮ("%w/4*4 t,X,*(Pda=k#[Y M?϶w5(d$ aT_ "' 23yXFW((?RfQq?`Fڸ%z{p8,hEږh3 ^<ą-GyD =,A( TdG8$ <Ez|ql9>7gϱG,_<P c>A9Fi)+b x{vsp{B`x({mmmOʆ^Os<% ڀ( D|T/g!TMVMW6&.{#u 1y~OQ 20HcʗX,-(,rj {9Qdf RHJ㻟`ی}>hIˀ@kae) J) ?N惋0.suJ hiEH˲x2_F>|4} |q~==D"qaɿUo>?bC2nh bNJyDA"[5.K|x~(;_>d!(IK0a) 2 +`䣆7Ȁa9=ݾNhGɕ'pQ$åf/ l.<,GnIW 0pt*.geW_GpE /|q ^X2&<Ѽ[f8n%2lzMq)j 0 -pNEs!b%AmIOy6|"d 8X66Cotb`r30Ku_&=%5< ,fLچp_f0R^b9nМb&w KsT\<Ђ`04dg3AkOh\@0\7JrMX<# GS<6cn 6yeXe`v-A|\7i@̀`ݾ(g/iy.)MG8F]Tl?ދBzZn|LX7ɒzYSmYh9ixbe.BX='SFdJ S,䳐iF#MYB 4-ۏyvbanV9oFSMt[ Wem(p[P`mIp@s0ZE$ 1 İh^HUd1f҉Ho?l0hyNjcC OhO(ǿ}h,&tq;"sL{Mh o6U3'zP4/1l5%JB'/C+־vP/޼v*jw/A&5:8XۇY^_/l_om2|yz:= +)\ `v|e}?ދo{0Ԏ,v YaXg?9BkJ ЎThp@}?کa)E6 2(JעA;d/j< \ٖ vr2s`r3 9xxY($V*+OqQP4Y Ã`ЄdTy /Hڅe_j- >*W.⇯4t0M+(a |گbtXEu'|?&ڈXÓgh@$h t |FO0luOJ @~I z #)Q`'{񣍍\B)~6EPh I K1X !Yfd O~6 |j0(@]Sjd@8Ep) OZm/H!ke^o@$CY: Fbɫyp)wƇtcO?~/cZ|\pڍ2FPè) (5g;/.RKqef~h l87@J2L}VF%M6biSbÁsDA`ih (nZ;]oATC?>O TyϹF(ar۝DIFݔJQ?r(/8 dye3; 1cXDy3/87Os`fg/s Nv^XjMӄ֌PmZēD h6i3{ 6oo -j&#r.`JMQV/R;N7|ZʹY*r ))A&d1A<VdꖙT rv `>̚ !Pd:ynX^gD~qgb ߉4 Y09W=3Krj'gྛs<'% Xu3w`Sz]3[ξX?1RZ+X1}P1CWpnFDc zsL`J/ eJs3z.w0"4$VRO2d>I"9I6L7AOWb# lQ4G`a`K㇏OC DLǙoLJt%z4&;.Sn_A:IDAT<4]&L3FVQGUA&j&AF@(“y)3ׁZ<1v,yF+NnRp^gZ·]:ۮlk2b,v "H/K#(|؋͇%:C7ASULz[ .$#hU"  _0 9U*@@TvP(Dz9~чmǼ)xK08òcAl:'iFZ3x4MsPj앳ba0ެE(Ȁvގ緵oBuOmCx}y]1A*2E%?/jW6GS. Յ`~N3,vcDZP/](^[xUC[ggʦjq)oF0?=Pa!# .`cwxdIzql:҇j}u4c(4E:Qw{zpSMl3_ ""f /xf9c?vcW梮u2N7Ol Z]QV|BD "QnS}+9fCϮkhy I=yE~afXk’id΁( .  z?GU$ꭣxh~YgZCX1UXsPtz a#@ɀ*G+H$(` ު7eca/?5%`ip%${SY2FP͟cR'Q$!,"~ "QoUfNB*#D¹Ў2qPˀhG u(x4WȦ5+s[[67*@VP8Ar܇,nbŞ7vbǀ/L0mv})PEbI$ŌM\q(8@,LőځJ;H Z+@yBHz!0?w{yv`Eb Ŀs-`'^$n+,&{H[Osa_rKK\iMCLa NMZ.- (’鸱|K*S4  dsȁEє5N^UVv7aY]( ue0yq~FlW/V/\l3SlR3 ,) >)9$qI|.g>_4e`#H+9:iO?d2hmm=KQ~o`6zڢilܸt$骫o>"ubGJ$Dw!9p8GkjjZ Vk͛7 >c1w~Cחu:Ԅ&l޼#<vH#jٖvn>u |Պr|>ܹ555~.hJjkk{.Ḩ( iD Qzbԩzضm~m x8@@@ƍ_h4`ssiҥx<'wo•\'}fNPG}}=jkk/Uhӌ @)6lx*770==%%%x<07b׋f|m۪op@ TJ̝;wҥKggghkg|3g4WUU Mo"\< dk jzn+))'ÕIc[ss3Ξ=]vmonnn{#O;o._csw?C8?t =F-EMðX, rop4Mj|F˯bZjϥy`nH 0uJdz6///޼y6mڸ | {A__:z8p`7ߙ xG~%UR|Vx9sdL>}MZZڗz}8Nh4{G7Q&;{Aee%qIpx{$7Gm$Cd<§[.h4~oPp:?>nҥKxWpw"77w}L&_^744'Nĉ8y$  #t fnݺL-AQcҥPX[o=5-޽O?4rrr4qAx^bC}w|@T3jbҤIa09jX ;v+V뵇BN9vZ<;cƌo~Ic* (//ǁ [nԩSq_Q ,\Ɔ;}gϞ== p<3YNsϼy򕯌| Dg*;;v >رc8~8Ν ˅~B! 1?#ͳp:hnnd2tR}iiiə㏏Y܋YٺpBEaѢEx<n뛚pbDQD"bhɲ%K ׾}V@2וxᇳ^Yvh܄/fSLjEMM Ο?p8`4ǭ|'F4̙3t:W$Aoo/233Ӎq1[VVV4VcҫGa D䲳rڊ-[ ++ .kTDގvtuu\..\(w"Hz_,"# A[L&,ZxDizmXZJKK1ydDQ@$ɤ.>zFAQV+O.V> ٽL+z ddd ^O r ! BN ߆ dbЅBn+hf3FcW@4|7]I#^00(Mh`p v88_s Gs! ~yߏf ^q"@,`pb`llfS9㱜9s8r 4555qz@h|j9EAA]Q0fD/^۳g'X>aU$Pĉ w 8X"5F,æMkGlQ/\py^ڹ 3gPUUX,]v?~ 4c L4XsΝ-++[DlMMMZ7ϲ裏PWWp8ݳgϡ{GnG0| x霷nݺO9;x/@Oŋ_}WCCE^4wOH.jB(p b'"SV\ymh4@ff&O? wwwSN{w@y|Maͼ&0)##c=sٳ1`@~~SZގ .  ۻ^{N>1I #pnpYrΜ9 L&?5 ˃3x.^W78(AU]]ţG?qD#o߻y< #\mR(Ńk7 `ҥ -Zt:'Z,8Nvvdee]SB|?6TUUutt3tO|ə~~󮚪/a"̐f& T6_ :0x&>ďمma韺Яhi=a*ȃDOD9 B1Gj1BkIz+ Ph6s O#&MB0Z Wa.>Cs].ʇ;OÏIENDB`sigviewer-0.6.4/src/images/sigviewer16.png000066400000000000000000000016521345753661000204600ustar00rootroot00000000000000PNG  IHDRabKGDC pHYs  tIME  uv7IDAT8]O\U?f< mP1XĪAj05څ4mܘԍ ظuL4ĤˮL?):0Sf`y3w]LIl=XW2tD`0`hcH Jz~W׮ѳ=w6](%QB)c auBZLMq[(uݭǍWHp(Nu%8ݩaڢXӓ08wȏ}b,KmXoO1ĩq[EWwIH'5 (%%M~ $>N.:tsO:,Gyj5h4()RVF;st" xx,}n}Ø%B bqvA|e"P~Kg*1 !!H!#^}Q.n@ow/ Lx")t%d; )^`B\:M=ƝL)5}%gN&c'a BXdKUv|j&c'mCZjmf\Wj~z5QҚ0BaY6&VDR9RSӟtt8'CCC_~򈐒""vvvznn7˦T*c< qǢP(r_2|ڶm8RJlq|gqq9;;7ѣ]MYeylvAk' 1FIENDB`sigviewer-0.6.4/src/images/sigviewer_32x32.bmp000066400000000000000000000060661345753661000211500ustar00rootroot00000000000000BM6 6(    666ZZZ|||\\\999iiiηqqq222@@@ aaattt888AAA***$$$oooſxxxddduuuÿöǵޫᰌ㴐渔輗ÝŠǢȣȣȢơĞ龙纕䶑Ⲏ߭ݩڥĮŹɚ{g'n/u5|;ԂA׈GڍLݑPޔRߖTUeߙ[ۏN؊IߢpԆIx8q1j*b#[ҕmȺǘxs;΂Lp0ǭ嶓׌QՆE׉Hα蹐ݖZ،NֈJ滛ЃJk,΄Qb%VВkʹƕvоȯ̆[Ϗh̸Œsl6wBюa֕gӌXхLޤxᯈᭆՐ[y=ݨ͂OۨԙuX͋eηoPV]ӓie&i*l-o/q1r2߫§p0m.~Gg(b#]൚sALFˈbжjI OT˂Rq:a"d$f'{Ct9i*ެҎ_e%b#ĭ·YVQKF@ɇ`ҵeԝ}أೖݪٞwު㹜ךq൛|OǴїvRɇ`ԳbҚ{ἧıҾȯ̴ɰחhмsFɇ`ֳ`>Fr9s3w7z:|׍SԄE˯ԆHр@¤x7t3o/ґgK>ɇ`ر}^F g(p0u5z:>ԃBՆD׈G؊Hޜer׈GֆEԃBԆJ|>>***vvvwww222sigviewer-0.6.4/src/images/sigviewer_32x32.png000066400000000000000000000035601345753661000211520ustar00rootroot00000000000000PNG  IHDR  pHYs  "IDATxVmlS>|{m_4!䋤!]A-ZF[ :жj4 uPUTZ)E4G,6 ]B41I8cu c#=~=~]v޽n,)a\rqm?@Jа"RQn~\K, \0 TE@ .9``p9u5Z_ B`\emOӈ/UE#,j4iRNY.Og1#B({1\囘3=)ru+=+ϔh ƺVMcp&,cN  l/~v*z9k8fbBDz)IWwWO 9;X{w'q7:I-˙O)u@Jt2QP~ !9*U/^Kܚ !9Ne252C3Md^x/0]'_l4Mj-{W=7i=uλI#oU![Nɟ^nMdh*wm( &76SsY_/ﻕx`Ӎt޹VE;} DALgc HDz${Z ;l獟 ؝__N8zk,ej!b!aUEObI+6oAT9@0|bZRʃqrj1>*4jXw*p]'5PY$ISg^Ikyu֔j*&* \`jJJ\j]gw(S{{}>ڳ̰Vܚ̜:Դ^zϬ[?sp!hh!KkI yLN/УYwϣJ'>CEu)Nٿz!Ϣs((@;9M 3@hg`y-P' ?lz7v_Xy>x;15p!02T5r꣨bUEF0F|PQtows&IT6DEѼ &"(]J`s>>sLc0D! Xl@)B.81Ι`S&J90l'֔mjR !BHåB,B(V0 ˲P.]}8U ChHhHXXX:t.p:`ٳ.СC.=}I}ϟ>}ejii9yduub:0Ν;7>>^0KEQ6o|;vWUUO$Ix^zĉ^i===Lb022200`iƑ#GZyf}}=5M1J(!aR)xK(SSSUUUWucL)x0ty9Z$ Z2g y^cPb !ڗ Z ; "E6}:;;+ @Jfff._|…H$ϲe pݭMMM555~_UU[e"Fp8 RG+/ݺIENDB`sigviewer-0.6.4/src/images/sigviewer_installer.bmp000066400000000000000000000623321345753661000223620ustar00rootroot00000000000000BMd6(9d  ȮŞ}}}ʗij{{{󱱱Գzzzީ|||矟𾾾޻ݱ߭岲Ŝ޽鿿jjjyyy쫫ڤݔȿƿľ̮¨ĪǬɮʰ̱γеѶӷԹպֻ׻׼׼׻׻ֺչԸҷѶϴͳ̱ʯȭƫ΍侤㼢Į̮Ț{f&k+p0t4y9}=ӂAՆE؊HڍLܑOޔRߖTVWXYXWUߕSݓQېNٌK׉GՄCҀ?|;w7s3n.i*e%`![o9˭ǘyc$h(l-q1u5z9~=ӂAՅD׉HٌJۏMܑOݓQޔRߕSߕSޕSmpܐNڎL؋JֈGz㯆}Rh3ɭĔu͆Y޹Z e0ȬÒt^"⺠߰Lʴܥ}ީȯިѻȭᬄ᫂ݢvӌX߬ڣ}ڧ֞|Qb.ǬqQUY]̈́SφRj+m.o0r2чPՏ[x8Bૄw7҈Qu6Ⲑӿl-j*f'c$ͅUVYLH _+ŬnMRUY]ۧo4e&h)j+l-n.p0q1r2r2чP潠q1o0n.t8v[&d\(ئ޴͋d|O㽥ɵᷛ}K·Xэ`́Mǯ఍֗iԐb؝tψWґd۫޳zKXԛz޵i9V!>[&cuJкĪİѮI[&ԿaJὨۮtHǵܧⴒӿⲏ̴ⲍᭅާ~Ԏ[ఌ౐צ֤F [&ս~`>@AI Њ\ҋXu7t4x8y8ג]ڙfр@֍T嵏ҀAڙf@溙w7w8y=n/ՓdʵRT>>[&ּ|^>>Oh(n/潠πFv6y9{;~=>Ӂ@ӃBԃBԄCۘa̰ԃBӂAҁ@ՊO֎V{:x8u5r2s5e%W@>[&ػ{]>Pi)m-q1t4w7{:~=Ҁ?ӃBՅDևF׈G؉H؊IٌL寂ܗ]؉H׈GֆEՄCӂAӄE҂Ez:w7t4y=t8i)e&W@[&ٹz\F g(m-q1u4~Aݡs>ӂAՅDֈF؊HٌJڍLۏMېNܐNܐNţŤڍLٌJ؉HևFɭӅG{;x8t4p0l-i)d%P[&ڸy[`#~FчQzԄC׉HڎLݒQUY^bfjnqsttrpmieb]YUݒPڍK׈GԃB~>z9s3L[&򯯯{fY/d:ÄRljUɌY̐]Δ`ИdҜg՟kףnڧrܪuޭx߰{}~}߰{ݭx۪u٦qףnԟkқgЗcΓ`ː\ɌYLjUĄQ€NnBY0rN󮮮🟟ܓ֖sigviewer-0.6.4/src/main.cpp000066400000000000000000000026041345753661000157600ustar00rootroot00000000000000// Copyright (c) 2017 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "gui_impl/commands/open_file_gui_command.h" #include #include using namespace sigviewer; int main(int argc, char* argv[]) { QApplication app(argc, argv); QApplication::setOrganizationName("SigViewer"); QApplication::setOrganizationDomain("http://github.com/cbrnr/sigviewer/"); QApplication::setApplicationName("SigViewer"); QApplication::setApplicationVersion(QString("%1.%2.%3").arg(VERSION_MAJOR).arg(VERSION_MINOR).arg(VERSION_BUILD)); #ifdef Q_OS_MACOS QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif QCommandLineParser parser; parser.setApplicationDescription("SigViewer - a biosignal viewer."); parser.addPositionalArgument("file", QApplication::translate("main", "Input file (optional).")); parser.addHelpOption(); parser.addVersionOption(); parser.process(app); const QStringList args = parser.positionalArguments(); GuiActionFactory::getInstance()->initAllCommands(); std::set app_modes; ApplicationContextImpl::init(app_modes); if (!args.isEmpty()) OpenFileGuiCommand::openFile(args[0]); int result = app.exec(); ApplicationContextImpl::cleanup(); return result; } sigviewer-0.6.4/src/signal_processing/000077500000000000000000000000001345753661000200375ustar00rootroot00000000000000sigviewer-0.6.4/src/signal_processing/FFTReal.cpp000066400000000000000000000430111345753661000217650ustar00rootroot00000000000000/***************************************************************************** * * * DIGITAL SIGNAL PROCESSING TOOLS * * Version 1.03, 2001/06/15 * * (c) 1999 - Laurent de Soras * * * * FFTReal.cpp * * Fourier transformation of real number arrays. * * Portable ISO C++ * * * * Tab = 3 * *****************************************************************************/ /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ #include "FFTReal.h" #include #include #if defined (_MSC_VER) #pragma pack (push, 8) #endif // _MSC_VER /*\\\ PUBLIC MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*==========================================================================*/ /* Name: Constructor */ /* Input parameters: */ /* - length: length of the array on which we want to do a FFT. */ /* Range: power of 2 only, > 0. */ /* Throws: std::bad_alloc, anything */ /*==========================================================================*/ FFTReal::FFTReal (const long length) : _bit_rev_lut (int (floor (log (length) / log (2) + 0.5))) , _trigo_lut (int (floor (log (length) / log (2) + 0.5))) , _sqrt2_2 (flt_t (sqrt (2) * 0.5)) , _length (length) , _nbr_bits (int (floor (log (length) / log (2) + 0.5))) { assert ((1L << _nbr_bits) == length); _buffer_ptr = 0; if (_nbr_bits > 2) { _buffer_ptr = new flt_t [_length]; } } /*==========================================================================*/ /* Name: Destructor */ /*==========================================================================*/ FFTReal::~FFTReal (void) { delete [] _buffer_ptr; _buffer_ptr = 0; } /*==========================================================================*/ /* Name: do_fft */ /* Description: Compute the FFT of the array. */ /* Input parameters: */ /* - x: pointer on the source array (time). */ /* Output parameters: */ /* - f: pointer on the destination array (frequencies). */ /* f [0...length(x)/2] = real values, */ /* f [length(x)/2+1...length(x)-1] = imaginary values of */ /* coefficents 1...length(x)/2-1. */ /* Throws: Nothing */ /*==========================================================================*/ void FFTReal::do_fft (flt_t f [], const flt_t x []) const { /*______________________________________________ * * General case *______________________________________________ */ if (_nbr_bits > 2) { flt_t * sf; flt_t * df; if (_nbr_bits & 1) { df = _buffer_ptr; sf = f; } else { df = f; sf = _buffer_ptr; } /* Do the transformation in several pass */ { int pass; long nbr_coef; long h_nbr_coef; long d_nbr_coef; long coef_index; /* First and second pass at once */ { const long * const bit_rev_lut_ptr = _bit_rev_lut.get_ptr (); coef_index = 0; do { const long rev_index_0 = bit_rev_lut_ptr [coef_index]; const long rev_index_1 = bit_rev_lut_ptr [coef_index + 1]; const long rev_index_2 = bit_rev_lut_ptr [coef_index + 2]; const long rev_index_3 = bit_rev_lut_ptr [coef_index + 3]; flt_t * const df2 = df + coef_index; df2 [1] = x [rev_index_0] - x [rev_index_1]; df2 [3] = x [rev_index_2] - x [rev_index_3]; const flt_t sf_0 = x [rev_index_0] + x [rev_index_1]; const flt_t sf_2 = x [rev_index_2] + x [rev_index_3]; df2 [0] = sf_0 + sf_2; df2 [2] = sf_0 - sf_2; coef_index += 4; } while (coef_index < _length); } /* Third pass */ { coef_index = 0; const flt_t sqrt2_2 = _sqrt2_2; do { flt_t v; sf [coef_index] = df [coef_index] + df [coef_index + 4]; sf [coef_index + 4] = df [coef_index] - df [coef_index + 4]; sf [coef_index + 2] = df [coef_index + 2]; sf [coef_index + 6] = df [coef_index + 6]; v = (df [coef_index + 5] - df [coef_index + 7]) * sqrt2_2; sf [coef_index + 1] = df [coef_index + 1] + v; sf [coef_index + 3] = df [coef_index + 1] - v; v = (df [coef_index + 5] + df [coef_index + 7]) * sqrt2_2; sf [coef_index + 5] = v + df [coef_index + 3]; sf [coef_index + 7] = v - df [coef_index + 3]; coef_index += 8; } while (coef_index < _length); } /* Next pass */ for (pass = 3; pass < _nbr_bits; ++pass) { coef_index = 0; nbr_coef = 1 << pass; h_nbr_coef = nbr_coef >> 1; d_nbr_coef = nbr_coef << 1; const flt_t * const cos_ptr = _trigo_lut.get_ptr (pass); do { long i; const flt_t * const sf1r = sf + coef_index; const flt_t * const sf2r = sf1r + nbr_coef; flt_t * const dfr = df + coef_index; flt_t * const dfi = dfr + nbr_coef; /* Extreme coefficients are always real */ dfr [0] = sf1r [0] + sf2r [0]; dfi [0] = sf1r [0] - sf2r [0]; // dfr [nbr_coef] = dfr [h_nbr_coef] = sf1r [h_nbr_coef]; dfi [h_nbr_coef] = sf2r [h_nbr_coef]; /* Others are conjugate complex numbers */ const flt_t * const sf1i = sf1r + h_nbr_coef; const flt_t * const sf2i = sf1i + nbr_coef; for (i = 1; i < h_nbr_coef; ++ i) { const flt_t c = cos_ptr [i]; // cos (i*PI/nbr_coef); const flt_t s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef); flt_t v; v = sf2r [i] * c - sf2i [i] * s; dfr [i] = sf1r [i] + v; dfi [-i] = sf1r [i] - v; // dfr [nbr_coef - i] = v = sf2r [i] * s + sf2i [i] * c; dfi [i] = v + sf1i [i]; dfi [nbr_coef - i] = v - sf1i [i]; } coef_index += d_nbr_coef; } while (coef_index < _length); /* Prepare to the next pass */ { flt_t * const temp_ptr = df; df = sf; sf = temp_ptr; } } } } /*______________________________________________ * * Special cases *______________________________________________ */ /* 4-point FFT */ else if (_nbr_bits == 2) { f [1] = x [0] - x [2]; f [3] = x [1] - x [3]; const flt_t b_0 = x [0] + x [2]; const flt_t b_2 = x [1] + x [3]; f [0] = b_0 + b_2; f [2] = b_0 - b_2; } /* 2-point FFT */ else if (_nbr_bits == 1) { f [0] = x [0] + x [1]; f [1] = x [0] - x [1]; } /* 1-point FFT */ else { f [0] = x [0]; } } /*==========================================================================*/ /* Name: do_ifft */ /* Description: Compute the inverse FFT of the array. Notice that */ /* IFFT (FFT (x)) = x * length (x). Data must be */ /* post-scaled. */ /* Input parameters: */ /* - f: pointer on the source array (frequencies). */ /* f [0...length(x)/2] = real values, */ /* f [length(x)/2+1...length(x)] = imaginary values of */ /* coefficents 1...length(x)-1. */ /* Output parameters: */ /* - x: pointer on the destination array (time). */ /* Throws: Nothing */ /*==========================================================================*/ void FFTReal::do_ifft (const flt_t f [], flt_t x []) const { /*______________________________________________ * * General case *______________________________________________ */ if (_nbr_bits > 2) { flt_t * sf = const_cast (f); flt_t * df; flt_t * df_temp; if (_nbr_bits & 1) { df = _buffer_ptr; df_temp = x; } else { df = x; df_temp = _buffer_ptr; } /* Do the transformation in several pass */ { int pass; long nbr_coef; long h_nbr_coef; long d_nbr_coef; long coef_index; /* First pass */ for (pass = _nbr_bits - 1; pass >= 3; --pass) { coef_index = 0; nbr_coef = 1 << pass; h_nbr_coef = nbr_coef >> 1; d_nbr_coef = nbr_coef << 1; const flt_t *const cos_ptr = _trigo_lut.get_ptr (pass); do { long i; const flt_t * const sfr = sf + coef_index; const flt_t * const sfi = sfr + nbr_coef; flt_t * const df1r = df + coef_index; flt_t * const df2r = df1r + nbr_coef; /* Extreme coefficients are always real */ df1r [0] = sfr [0] + sfi [0]; // + sfr [nbr_coef] df2r [0] = sfr [0] - sfi [0]; // - sfr [nbr_coef] df1r [h_nbr_coef] = sfr [h_nbr_coef] * 2; df2r [h_nbr_coef] = sfi [h_nbr_coef] * 2; /* Others are conjugate complex numbers */ flt_t * const df1i = df1r + h_nbr_coef; flt_t * const df2i = df1i + nbr_coef; for (i = 1; i < h_nbr_coef; ++ i) { df1r [i] = sfr [i] + sfi [-i]; // + sfr [nbr_coef - i] df1i [i] = sfi [i] - sfi [nbr_coef - i]; const flt_t c = cos_ptr [i]; // cos (i*PI/nbr_coef); const flt_t s = cos_ptr [h_nbr_coef - i]; // sin (i*PI/nbr_coef); const flt_t vr = sfr [i] - sfi [-i]; // - sfr [nbr_coef - i] const flt_t vi = sfi [i] + sfi [nbr_coef - i]; df2r [i] = vr * c + vi * s; df2i [i] = vi * c - vr * s; } coef_index += d_nbr_coef; } while (coef_index < _length); /* Prepare to the next pass */ if (pass < _nbr_bits - 1) { flt_t * const temp_ptr = df; df = sf; sf = temp_ptr; } else { sf = df; df = df_temp; } } /* Antepenultimate pass */ { const flt_t sqrt2_2 = _sqrt2_2; coef_index = 0; do { df [coef_index] = sf [coef_index] + sf [coef_index + 4]; df [coef_index + 4] = sf [coef_index] - sf [coef_index + 4]; df [coef_index + 2] = sf [coef_index + 2] * 2; df [coef_index + 6] = sf [coef_index + 6] * 2; df [coef_index + 1] = sf [coef_index + 1] + sf [coef_index + 3]; df [coef_index + 3] = sf [coef_index + 5] - sf [coef_index + 7]; const flt_t vr = sf [coef_index + 1] - sf [coef_index + 3]; const flt_t vi = sf [coef_index + 5] + sf [coef_index + 7]; df [coef_index + 5] = (vr + vi) * sqrt2_2; df [coef_index + 7] = (vi - vr) * sqrt2_2; coef_index += 8; } while (coef_index < _length); } /* Penultimate and last pass at once */ { coef_index = 0; const long * bit_rev_lut_ptr = _bit_rev_lut.get_ptr (); const flt_t * sf2 = df; do { { const flt_t b_0 = sf2 [0] + sf2 [2]; const flt_t b_2 = sf2 [0] - sf2 [2]; const flt_t b_1 = sf2 [1] * 2; const flt_t b_3 = sf2 [3] * 2; x [bit_rev_lut_ptr [0]] = b_0 + b_1; x [bit_rev_lut_ptr [1]] = b_0 - b_1; x [bit_rev_lut_ptr [2]] = b_2 + b_3; x [bit_rev_lut_ptr [3]] = b_2 - b_3; } { const flt_t b_0 = sf2 [4] + sf2 [6]; const flt_t b_2 = sf2 [4] - sf2 [6]; const flt_t b_1 = sf2 [5] * 2; const flt_t b_3 = sf2 [7] * 2; x [bit_rev_lut_ptr [4]] = b_0 + b_1; x [bit_rev_lut_ptr [5]] = b_0 - b_1; x [bit_rev_lut_ptr [6]] = b_2 + b_3; x [bit_rev_lut_ptr [7]] = b_2 - b_3; } sf2 += 8; coef_index += 8; bit_rev_lut_ptr += 8; } while (coef_index < _length); } } } /*______________________________________________ * * Special cases *______________________________________________ */ /* 4-point IFFT */ else if (_nbr_bits == 2) { const flt_t b_0 = f [0] + f [2]; const flt_t b_2 = f [0] - f [2]; x [0] = b_0 + f [1] * 2; x [2] = b_0 - f [1] * 2; x [1] = b_2 + f [3] * 2; x [3] = b_2 - f [3] * 2; } /* 2-point IFFT */ else if (_nbr_bits == 1) { x [0] = f [0] + f [1]; x [1] = f [0] - f [1]; } /* 1-point IFFT */ else { x [0] = f [0]; } } /*==========================================================================*/ /* Name: rescale */ /* Description: Scale an array by divide each element by its length. */ /* This function should be called after FFT + IFFT. */ /* Input/Output parameters: */ /* - x: pointer on array to rescale (time or frequency). */ /* Throws: Nothing */ /*==========================================================================*/ void FFTReal::rescale (flt_t x []) const { const flt_t mul = flt_t (1.0 / _length); long i = _length - 1; do { x [i] *= mul; --i; } while (i >= 0); } /*\\\ NESTED CLASS MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*==========================================================================*/ /* Name: Constructor */ /* Input parameters: */ /* - nbr_bits: number of bits of the array on which we want to do a */ /* FFT. Range: > 0 */ /* Throws: std::bad_alloc */ /*==========================================================================*/ FFTReal::BitReversedLUT::BitReversedLUT (const int nbr_bits) { long length; long cnt; long br_index; long bit; length = 1L << nbr_bits; _ptr = new long [length]; br_index = 0; _ptr [0] = 0; for (cnt = 1; cnt < length; ++cnt) { /* ++br_index (bit reversed) */ bit = length >> 1; while (((br_index ^= bit) & bit) == 0) { bit >>= 1; } _ptr [cnt] = br_index; } } /*==========================================================================*/ /* Name: Destructor */ /*==========================================================================*/ FFTReal::BitReversedLUT::~BitReversedLUT (void) { delete [] _ptr; _ptr = 0; } /*==========================================================================*/ /* Name: Constructor */ /* Input parameters: */ /* - nbr_bits: number of bits of the array on which we want to do a */ /* FFT. Range: > 0 */ /* Throws: std::bad_alloc, anything */ /*==========================================================================*/ FFTReal::TrigoLUT::TrigoLUT (const int nbr_bits) { long total_len; _ptr = 0; if (nbr_bits > 3) { total_len = (1L << (nbr_bits - 1)) - 4; _ptr = new flt_t [total_len]; const double PI = atan (1) * 4; for (int level = 3; level < nbr_bits; ++level) { const long level_len = 1L << (level - 1); flt_t * const level_ptr = const_cast (get_ptr (level)); const double mul = PI / (level_len << 1); for (long i = 0; i < level_len; ++ i) { level_ptr [i] = (flt_t) cos (i * mul); } } } } /*==========================================================================*/ /* Name: Destructor */ /*==========================================================================*/ FFTReal::TrigoLUT::~TrigoLUT (void) { delete [] _ptr; _ptr = 0; } #if defined (_MSC_VER) #pragma pack (pop) #endif // _MSC_VER /***************************************************************************** LEGAL Source code may be freely used for any purpose, including commercial applications. Programs must display in their "About" dialog-box (or documentation) a text telling they use these routines by Laurent de Soras. Modified source code can be distributed, but modifications must be clearly indicated. CONTACT Laurent de Soras 92 avenue Albert 1er 92500 Rueil-Malmaison France ldesoras@club-internet.fr *****************************************************************************/ /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ sigviewer-0.6.4/src/signal_processing/FFTReal.h000066400000000000000000000071121345753661000214340ustar00rootroot00000000000000/***************************************************************************** * * * DIGITAL SIGNAL PROCESSING TOOLS * * Version 1.03, 2001/06/15 * * (c) 1999 - Laurent de Soras * * * * FFTReal.h * * Fourier transformation of real number arrays. * * Portable ISO C++ * * * * Tab = 3 * *****************************************************************************/ #if defined (FFTReal_CURRENT_HEADER) #error Recursive inclusion of FFTReal header file. #endif #define FFTReal_CURRENT_HEADER #if ! defined (FFTReal_HEADER_INCLUDED) #define FFTReal_HEADER_INCLUDED #if defined (_MSC_VER) #pragma pack (push, 8) #endif // _MSC_VER class FFTReal { /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ public: /* Change this typedef to use a different floating point type in your FFTs (i.e. float, double or long double). */ typedef float flt_t; explicit FFTReal (const long length); ~FFTReal (); void do_fft (flt_t f [], const flt_t x []) const; void do_ifft (const flt_t f [], flt_t x []) const; void rescale (flt_t x []) const; /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ private: /* Bit-reversed look-up table nested class */ class BitReversedLUT { public: explicit BitReversedLUT (const int nbr_bits); ~BitReversedLUT (); const long * get_ptr () const { return (_ptr); } private: long * _ptr; }; /* Trigonometric look-up table nested class */ class TrigoLUT { public: explicit TrigoLUT (const int nbr_bits); ~TrigoLUT (); const flt_t * get_ptr (const int level) const { return (_ptr + (1L << (level - 1)) - 4); }; private: flt_t * _ptr; }; const BitReversedLUT _bit_rev_lut; const TrigoLUT _trigo_lut; const flt_t _sqrt2_2; const long _length; const int _nbr_bits; flt_t * _buffer_ptr; /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ private: FFTReal (const FFTReal &other); const FFTReal& operator = (const FFTReal &other); int operator == (const FFTReal &other); int operator != (const FFTReal &other); }; #if defined (_MSC_VER) #pragma pack (pop) #endif // _MSC_VER #endif // FFTReal_HEADER_INCLUDED #undef FFTReal_CURRENT_HEADER /***************************************************************************** LEGAL Source code may be freely used for any purpose, including commercial applications. Programs must display in their "About" dialog-box (or documentation) a text telling they use these routines by Laurent de Soras. Modified source code can be distributed, but modifications must be clearly indicated. CONTACT Laurent de Soras 92 avenue Albert 1er 92500 Rueil-Malmaison France ldesoras@club-internet.fr *****************************************************************************/ /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ sigviewer-0.6.4/src/signal_processing/SPUC/000077500000000000000000000000001345753661000206115ustar00rootroot00000000000000sigviewer-0.6.4/src/signal_processing/SPUC/butterworth.h000066400000000000000000000071421345753661000233570ustar00rootroot00000000000000// // author="Tony Kirke" // Copyright(c) 1993-1998 Tony Kirke /* * SPUC - Signal processing using C++ - A DSP library * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "spuc.h" #include "complex.h" #include "iir_1st.h" #include "iir_2nd.h" namespace SPUC { /*! \addtogroup iir IIR filters */ /*! \brief Template Class for Butterworth iir filter \ingroup iir */ //! Butterworth low pass filter. //! Specify cut-off, order and Attenuation at cut-off on construction //! Filter is bilinear transformation of analog butterworth template class butterworth { private: long order; long odd; long n2; complex* roots; iir_2nd< Numeric>* iir; iir_1st< Numeric>* iir_1; double gain; double* coeff; public: //! Constructor, fcd = cut-off (1=sampling rate) //! ord = Filter order //! amax = attenuation at cut-off butterworth(double fcd, long ord=1, double amax=3.0) { // amax - attenuation at cutoff gain = 1; order = ord; double epi = pow( (pow(10.0,(amax/10.)) - 1.0) ,(1./(2.0*ord))); // fcd - desired cutoff frequency (normalized) double wca = 2.0*tan(PI*fcd)/epi; // wca - pre-warped angular frequency n2 = (order+1)/2; odd = (order%2); roots = new complex[n2]; if (odd) iir_1 = new iir_1st< Numeric >; get_roots(wca,order,n2); bilinear(n2); iir = new iir_2nd< Numeric >[order/2]; get_coeff(n2); } //! Destructor ~butterworth() { delete [] roots; if (odd) delete iir_1; delete [] iir; } //! Reset history void reset() { for (int j=odd;jreset(); } } //! print coefficients void print() { for (int j=odd;jclock(tmp); return(gain*tmp); } private: //! Calculate roots void get_roots(double wp, long n, long n2) { long l = 0; if (n%2 == 0) l = 1; double arg; for (int j=0;jset_coeff(-tmp); gain *= 0.5*(1+tmp); } for (j=odd;j((a*a - magsq(roots[j])), 2.0*a*roots[j].imag())/td; } } //! Get 2nd order IIR coefficients void get_coeff(long n2) { for (int j=odd;j class chebyshev { private: long order; long odd; long n2; complex* roots; iir_2nd< Numeric>* iir; iir_1st< Numeric>* iir_1; double gain; double* coeff; double epi; public: //! Constructor, fcd = cut-off (1=sampling rate) //! ord = Filter order //! ripple = passband ripple in dB chebyshev(double fcd, long ord=1, double ripple=3.0) { gain = 1; order = ord; epi = pow(10.0,(ripple/10.)) - 1.0; epi = pow(epi,(1./(1.0*ord))); double wca = tan(0.5*PI*fcd); //! wca - pre-warped angular frequency n2 = (order+1)/2; odd = (order%2); roots = new complex[n2]; if (odd) iir_1 = new iir_1st< Numeric >; get_roots(wca,order,n2); bilinear(n2); iir = new iir_2nd< Numeric >[order/2]; get_coeff(n2); } //! Destructor ~chebyshev() { delete [] roots; if (odd) delete iir_1; delete [] iir; } //! Reset history void reset() { for (int j=odd;jreset(); } } //! print coefficients void print() { int j; for (j=odd;jprint(); } //! Clock in sample and get output. Numeric clock(Numeric in) { Numeric tmp = in; for (int i=odd;iclock(tmp); return(gain*tmp); } private: //! Calculate roots (chebyshev) void get_roots(double wp, long n, long n2) { long l = 0; if (n%2 == 0) l = 1; double arg; double x = 1/epi; double asinh = log(x + sqrt(1.0+x*x)); double v0 = asinh/(double(n)); double sm = sinh(v0); double cm = cosh(v0); for (int j=0;j(-sm*cos(arg),cm*sin(arg)); l += 2; } } //! Do bilinear transformation void bilinear(long n2) { double td; int j; const double a = 1.; if (odd) { // For s-domain zero (or pole) at infinity we // get z-domain zero (or pole) at z = -1 double tmp = (roots[0].real()-a)/(a+roots[0].real()); iir_1->set_coeff(-tmp); gain *= 0.5*(1+tmp); } for (j=odd;j((a*a - magsq(roots[j])), 2.0*a*roots[j].imag())/td; } } //! Get 2nd order IIR coefficients void get_coeff(long n2) { for (int j=odd;j #include "spuc.h" #include namespace SPUC { //! \brief Spuc template complex class. //! Basically the same as STL complex class but allows easier customization. template class complex { public: T re; T im; complex() { re = 0; im = 0; } void* operator new (size_t) { T* re = new T; T* im = new T; } complex(T r, T i) :re(r), im(i) {} complex(T r) : re(r), im(0) {} // template <> complex(const complex& y) : re(y.re), im(y.im) {;} inline T real() { return(re);}; inline T imag() { return(im);}; friend T real( complex y ) { return(y.re);} friend T imag( complex y ) { return(y.im);} inline T operator=(T r) { re = r; im = 0; return r; } inline complex operator =(const complex& y) { re = (T)y.re; im = (T)y.im; return *this; } inline complex operator *=(const complex& y) { T r = re*y.re - im*y.im; im = re*y.im + im*y.re; re = r; return *this; } inline complex operator +=(const complex& y) { re += y.re; im += y.im; return *this; } inline complex operator -=(const complex& y) { re -= y.re; im -= y.im; return *this; } #ifndef DOXYGEN_SHOULD_SKIP_THIS operator const complex () const { return(complex((long)re,(long)im)); } #endif }; #ifndef DOXYGEN_SHOULD_SKIP_THIS template inline complex operator *(complex r, complex l) { complex x; x.re = ((r.re*l.re) - (r.im*l.im)); x.im = (r.re*l.im + r.im*l.re); return x; }; //! template inline complex operator +(complex r, complex l) { complex x; x.re = r.re + l.re; x.im = r.im + l.im; return x; }; //! template inline complex operator +(complex r, T l) { complex x; x.re = r.re + l; x.im = r.im; return x; }; //! template inline complex operator +(T r, complex l) { complex x; x.re = r + l.re; x.im = l.im; return x; }; //! template inline complex operator -(complex r, complex l) { complex x; x.re = r.re - l.re; x.im = r.im - l.im; return x; }; //! template inline complex operator -(complex r, T l) { complex x; x.re = r.re - l; x.im = r.im; return x; }; //! template inline complex operator -(T r, complex l) { complex x; x.re = r - l.re; x.im = -l.im; return x; }; //! template inline complex operator &(complex r, T l) { complex x; x.re = r.re & l; x.im = r.im & l; return x; }; //! template inline complex operator &(T r, complex l) { complex x; x.re = r & l.re; x.im = r & l.im; return x; }; template inline complex operator %(complex r, T l) { complex x; x.re = r.re % l; x.im = r.im % l; return x; }; //! template inline complex operator ^(complex r, T l) { complex x; x.re = r.re ^ l; x.im = r.im ^ l; return x; }; //! template inline complex operator ^(T r, complex l) { complex x; x.re = r ^ l.re; x.im = r ^ l.im; return x; }; template inline complex operator |(complex r, T l) { complex x; x.re = r.re | l; x.im = r.im | l; return x; }; //! template inline complex operator |(T r, complex l) { complex x; x.re = r | l.re; x.im = r | l.im; return x; }; //! Left shift template inline complex operator <<(complex r, const long shift) { complex res = complex(r.re << shift, r.im << shift); return(res); } //! Right shift template inline complex operator >>(complex r, const long shift) { complex res = complex(r.re >> shift, r.im >> shift); return(res); } //! template inline complex operator -(complex r) { complex x; x.re = -r.re; x.im = -r.im; return x; }; //! inline complex operator *( double r, complex l) { return(complex((long)floor((double)(r*l.re+0.5)), (long)floor((double)(r*l.im+0.5)))); }; //! inline complex operator *( long r, complex l) { complex x; x.re = (r*l.re); x.im = (r*l.im); return x; }; //! inline complex operator *( double r, complex l) { complex x; x.re = (r*l.re); x.im = (r*l.im); return x; }; //! template inline complex operator *(complex r, T l) { complex x; x.re = r.re*l; x.im = r.im*l; return x; }; //! template complex operator /(complex l, T r) { complex x(0,0); if (r != 0) { x.re = l.re/r; x.im = l.im/r; } //! else is an error condition! return x; }; //! template complex operator /(complex r, complex l) { complex x; T2 den; den = magsq(l); x = (r * conj(l))/den; return x; }; //! template inline bool operator ==(complex r, complex l) { return ((r.re == l.re) && (r.im == l.im)); }; //! template inline bool operator !=(complex r, complex l) { return ((r.re != l.re) || (r.im != l.im)); }; //! Unit magnitude polar to rectangular conversion inline complex expj(double x) { complex y; y.re = cos(x); y.im = sin(x); return y; } //! Polar to rectangular conversion inline complex polar(double amp,double arg) { complex y; y.re = amp*cos(arg); y.im = amp*sin(arg); return y; } //! Complex value (0,1) template inline complex complexj(void) { return(complex(0,1)); } template inline T re(complex x) { T y; y = x.re; return y; }; template inline T im(complex x) { T y; y = x.im; return y; }; //! Conjugate template inline complex conj(complex x) { complex y; y.re = x.re; y.im = -x.im; return y; } //! Magnitude Squared of complex vector template inline T magsq(complex x) { T y; y = (x.re*x.re + x.im*x.im); return y; }; //! Normalized vector (magnitude = 1) template inline complex norm(complex x) { T y; y = ::sqrt(x.re*x.re + x.im*x.im); return (complex(x.re/y,x.im/y)); }; template inline T approx_mag(complex x) { return(MAX(abs(x.re),abs(x.im)) + MIN(abs(x.re),abs(x.im))/4); }; template inline complex maxvalue(complex x1) { return(complex(MAX(x1.re,x1.im))); }; template inline complex minimum(complex x1, complex x2) { return(complex(MIN(x1.re,x2.re),MIN(x1.im,x2.im))); } template inline complex maximum(complex x1, complex x2) { return(complex(MAX(x1.re,x2.re),MAX(x1.im,x2.im))); }; //! Return phase angle (radians) of complex number template inline double arg(const complex x) { double TMPANG; if (real(x) == 0) { if (imag(x) < 0) return(3.0*PI/2.0); else return(PI/2.0); } else { TMPANG=atan((double)imag(x)/(double)real(x)); if (real(x) < 0) TMPANG -= PI; if (TMPANG < 0) TMPANG += TWOPI; } return(TMPANG); } //! Convert to complex template inline complex rational(complex l) { return(complex((double)l.re,(double)l.im)); } //! Round by bits, to near integer - return(complex) inline complex round(complex in, long bits) { double scale = 1.0/(double)(1 << bits); return(complex((long)floor((double)(scale*in.re)+0.5), (long)floor((double)(scale*in.im)+0.5))); } //! Saturate to specific number of bits (signed) inline complex saturate(complex in, long bits) { complex out; long low_mask = ((1<<(bits-1)) - 1); if (labs(in.re) > low_mask) out.re = (in.re>0) ? low_mask : ~low_mask; else out.re = in.re; if (labs(in.im) > low_mask) out.im = (in.im>0) ? low_mask : ~low_mask; else out.im = in.im; return(out); } template complex signbit(complex in) { return(complex(SGN(in.re),SGN(in.im))); } //template T real(complex& y) { return(y.re);} //template T imag(complex& y) { return(y.im);} template inline complex reciprocal(complex x) { T y; y = (x.re*x.re + x.im*x.im); return (complex(x.re/y,-x.im/y)); }; //! squaring function template inline complex sqr(complex x) { return (x*x); }; //! square root function (same as sqrt in spuc_math.h) template inline complex csqrt(complex x) { double mag = sqrt(sqrt(magsq(x))); double ang = 0.5*arg(x); // ambiguity return(polar(mag,ang)); }; //! complex exponential inline complex exp(complex x) { return (::exp(x.real()) * expj(x.imag())); } //! same name as math library inline double hypot(complex z) { double _hypot(double x, double y); return _hypot(z.imag(), z.real()); } #endif } // namespace SPUC #endif sigviewer-0.6.4/src/signal_processing/SPUC/iir_1st.h000066400000000000000000000045121345753661000223360ustar00rootroot00000000000000// // Copyright(c) 1993-1996 Tony Kirke // author="Tony Kirke" * /* * SPUC - Signal processing using C++ - A DSP library * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IIR_1ST #define IIR_1ST #include using namespace std; namespace SPUC { //! \brief Template Class for 1st Order iir filter //! //! \ingroup iir //! Template for 1st Order IIR filter

//! The filter is assumed the first order low pass digital filter //! generated by the bilinear transform of a first order analog //! filter. //! \f$ G(z) = \frac{1+z^-1}{1-a*z^-1} \f$

where a is real and |a| < 1 //! Note: Not normalized template class iir_1st { protected: double gain; Numeric out; Numeric previous_out; Numeric previous_in; public: iir_1st(double A=0) : gain(A) { previous_in = previous_out = out = 0 ; } void set_coeff(double A) { gain=A;} //! Constructor reading coefficient from a file. iir_1st(const char* file) { FILE *iirf = fopen(file,"r"); fscanf(iirf,"%lf",&gain); fclose(iirf); previous_in = previous_out = out = 0; } //! Print out coefficients void print() { cout << "IIR Coefficient gain = " << gain << "\n"; } //! Input new sample and calculate output Numeric clock(Numeric input) { // Shift previous outputs and calculate new output */ // out = gain*previous_out + (1-gain)*input; out = gain*previous_out + (input+previous_in); previous_out = out; previous_in = input; return(out); } //! Reset void reset() { previous_in = previous_out = out = 0; } }; } // namespace SPUC #endif sigviewer-0.6.4/src/signal_processing/SPUC/iir_2nd.h000066400000000000000000000054551345753661000223210ustar00rootroot00000000000000// // Copyright(c) 1993-1996 Tony Kirke // author="Tony Kirke" * /* * SPUC - Signal processing using C++ - A DSP library * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef IIR_2ND #define IIR_2ND namespace SPUC { /*! \addtogroup iir IIR filters */ //! \brief Template for 2nd Order IIR filter

//! \ingroup iir //! //! Template for 2nd Order IIR filter

//! The filter is assumed to be a low pass 2nd order digital filter //! of the form \f$ G(z) = \frac{b0*z^2 + b1*z+b2}{(z^2+a1*z+a2)} \f$ //! \image html iir_2nd.gif //! \image latex iir_2nd.eps template class iir_2nd { protected: Numeric b0,b1,b2; Numeric a1,a2; Numeric in[3]; Numeric out[3]; public: iir_2nd(Numeric B0, Numeric B1, Numeric B2, Numeric A1, Numeric A2) : b0(B0), b1(B1), b2(B2), a1(A1), a2(A2) { in[0] = in[1] = in[2] = out[2] = out[1] = out[0] = 0 ; } iir_2nd(Numeric A1=0, Numeric A2=0) : b0(1), b1(2), b2(1), a1(A1), a2(A2) { in[0] = in[1] = in[2] = out[2] = out[1] = out[0] = 0 ; } void reset() { in[0] = in[1] = in[2] = out[2] = out[1] = out[0] = 0 ; } void set_a(Numeric A1, Numeric A2) { a1=A1; a2=A2;} void set_b(Numeric A1, Numeric A2) { b1=A1; b2=A2;} void set_coeff(Numeric A1, Numeric A2) { a1=A1; a2=A2;} //! Constructor reading coefficients from a file. iir_2nd(const char* file) { FILE *iirf = fopen(file,"r"); fscanf(iirf,"%lf %lf %lf %lf %lf",&b0,&b1,&b2,&a1,&a2); fclose(iirf); in[0] = in[1] = in[2] = out[2] = out[1] = out[0] = 0; } //! Print out coefficients void print() { printf("IIR Coefficients B0 = %lf, B1 = %lf, B2 = %lf",b0,b1,b2); printf(" A0 = 1, A1 = %lf, A2 = %lf\n",a1,a2); } //! Input new sample and calculate output Numeric clock(Numeric input) { // Shift inputs by one time sample and place new sample into array in[0] = in[1]; in[1] = in[2]; in[2] = input; // Shift previous outputs and calculate new output */ out[0] = out[1]; out[1] = out[2]; out[2] = b0*in[2] + b1*in[1] + b2*in[0] - a1*out[1] - a2*out[0]; return(out[2]); } }; } // namespace SPUC #endif sigviewer-0.6.4/src/signal_processing/SPUC/spuc.h000066400000000000000000000224521345753661000217410ustar00rootroot00000000000000/*! \mainpage * SPUC - Signal processing using C++ - A DSP library *

Copyright (C) 1993-2005 Tony Kirke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software

Signal Processing using C++ (SPUC)

Motivation:Why use C++ for DSP Simulation/Modeling?

Todays IC and system designers typically use either C or costly 2nd party tools to simulate/model Digital Signal Processing algorithms. While the latter are well suited for modeling "hardwired" DSP blocks with rather simplistic dataflows, they are very inefficient for modeling the control logic that is often required in todays DSP applications (such as ADSL or V.34 modems). while C is well suited to control logic type structures (if,else, case, etc.), it is not highly desireable for manipulation of complex or user defined data types (such as fixed width integers).

C++ bridges this gap and is the underlying language of choice for the cumbersome GUI based tools.


Objective

The objective of SPUC is to provide the Communications Systems Designer or DSP Algorithm designer with simple, efficient and reusable DSP building block objects. Thus allowing a transition from System design to implementation in either programmable DSP chips or hardwired DSP logic. While Matlab is perhaps the most useful available tool for this purpose, it can be quite slow for simulation and it favors a matrix/block based approach rather than the sample by sample simulations that are often most useful for communications systems design. Also Matlab is generally awkward or inefficient when dealing with several interactive feedback loops where C/C++ is perhaps the most useful environment. For bit-accurate simulations (for VLSI design) C/C++ generally outperforms and is easier to manipulate than Matlab or other GUI-based tools.

This Class Library

  • 1) basic building blocks such as complex data types, Fixed-bit width integer classes, pure-delay blocks, etc.
  • 2) Basic DSP building blocks such as FIR, IIR, Allpass, Running Average, Lagrange interpolation filters, NCO, Cordic rotator.
  • 3) Several communications functions such as timing, phase and frequency discriminators for BPSK/QPSK signals.
  • 4) Other miscellaneous DSP/Communications related functions/classes.
  • 5) Ability to design several types of FIR and IIR filters
  • 6) Various adaptive equalizer classes
  • 7) This library now includes code from IT 3.7.0. Code was modified to work together with SPUC and replace Vector and Matrix classes from TNT.
  • 8) Capitalized and uppercase class names are classes not originally in SPUC
The classes are designed so that they can be used in a simple straight forward manner. For example, a FIR would be initialized with its tap weights and then simply a member function would be called every time a sample is input or an output is required.

For downloading files go to

Project Page at Sourceforge

Before discussing why C++ is better than C for DSP programming. Let's look at some of the pros and cons for C++ vs. the alternatives.

Pros

  • The common alternatives are very costly (Alta's SPW, Synopsys Cossap etc.)
  • Long learning times/training not required for C++ programmers.
  • For complex simulations, C++ is more efficient and yields shorter run times.
  • Ideal for modeling a combination of control logic and hardwired DSP blocks.
  • Code entry can be faster than GUI based tools.
  • Looks closer to Verilog/VHDL than alternative tools.
  • C/C++ has a large user base.
  • Lots of freely available C/C++ code.
  • Infinitely customizable.
  • Portable to different platforms.
  • Can take advantage of Windows GUIs if desired.

Cons

  • No standardization!
  • Lack of documentation.
  • Not user friendly/ No GUI.
  • Potential portability problems.
  • No technical support.

Please see links such as those below for why to use C++ over C in general.
Nathan Myers C++ Articles
C++ Programming for Scientists Course (PDF) from NIST
Various C++ Math classes from Roldan Pozo at NIST

Advantages of C++ over C

  • Object Oriented Language
  • Abstract Data typing
  • Inheritance
  • Polymorphism
  • Comments do not extend over more than one line
  • Variables can be declared anywhere.
  • Dynamic memory allocation is simpler.
  • Function Overloading

C++ allows templates and operator overloading.
For example, we can define a complex data type based on templates. Then this class can be used whether we need floating point (double), integer, or user defined fixed bit width data types.This not only requires less code to document/debug, but also through operator overloading we can make the code much easier to read and potentially make the look and feel very close to a Hardware Description Language (HDL)such as Verilog or VHDL. Also this style makes it much easier to change your programs data types (from floating point -> integer -> fixed bit width for example), without having to change every line of code.

C++ allows for much better interfaces between classes or DSP blocks.
Because C++ supports initialization through constructors and there can be a variety of member functions, data can be handled in a much smoother manner than C. With data hiding, the code becomes much simpler to read, allowing a high level look at the code.

Inheritance
Inheritance helps you to re-use code.You can derive new types or classes from an old one and make changes only where you need them. This promotes code re-use.

Classes

  • Hide complexity.
  • Create a more convenient object oriented interfaces
  • Can create more than one instance of a structure.
  • Similar to C structure but can include functions.
  • Data abstraction and hiding allows changes to be localized to one section.
  • Private, Protected, Public members

For Hardware Modeling
C++ can be made to replicate hardware much easier than C. Functions and variables can be localised to each block (hiding complexity) in the same way that Verilog /VHDL does. Easier to have a hierarchical structure. Classes can be instantiated in same manner as in a HDL (C makes this difficult). New chip designs can inherit subblocks or a large section from an old design. Only the new or changed blocks need to be coded. Also the interfaces to the chip can remain the same if desired. When classes are designed in this manner it is quite easy to see the difference between objects. */ //! SPUC - Signal processing using C++ - A DSP library //! includes code from other sources including IT++ 3.7.0 //! \namespace SPUC namespace SPUC { //! \file //! \brief Various Defined Constants and Macros //! \author Tony Kirke, Copyright(c) 2001 #ifndef MYINCLUDE #define MYINCLUDE #define MAXINT 32767 #define MXLONG 4294967295 #define BIG 72057594037927936. // Maximum precision of DOUBLE */ #define HUGED 1.701411733192644270e38 // Largest DOUBLE */ #define LOGHUGE 39 // 10^39 --> Largest power */ #define LN2 0.69314718055994530941 #define ILN2 1.4426950408889634 // 1/LN2 #define LN10 2.30258509299404568401 #define E 2.7182818284590452353602874 #define SQRT2 1.41421356237309504880 #define HALFSQRT2 .70710678118654752440 #ifndef PI #define PI 3.141592653589793238462643 #endif //#define pi PI #define QUARTPI 0.78539816339744830962 #define HALFPI 1.57079632679489661923 #define TWOPI 6.28318530717958647692 #define RADPDEG 0.01745329251994329576 #define RTD 57.295781 // radian to decimal conversion factor // macros #define SQR(x) ((x) * (x)) #define SGN(x) ((x) < 0 ? -1 : 1) #define XSWAP(a,b) a ^= b, b ^= a, a ^= b #define SWAP(a,b,c) c = a, a = b, b = c #ifndef MAX #define MAX(x,y) ((x) >= (y) ? (x) : (y)) #endif #ifndef MIN #define MIN(x,y) ((x) <= (y) ? (x) : (y)) #endif #ifndef ABS #define ABS(x) ( (x < 0) ? (-x) : (x)) #endif //#define abs(x) ((x)<0? -(x):(x)) // Integer Absolute value */ //#define fabs(x) ((x)<0.? -(x):(x)) // Floating absolute value */ #define MODULO(x,y) ((x)%(y)) // Integer modulo */ #define LOGE(x) (log(x)) // Natural log */ #define LN(x) (log(x)) // Natural log */ #define MASK_LOW(n) ((1<B) ? B : ((A. #include "notch_filter8.h" #define _USE_MATH_DEFINES #include #include #include #include namespace SigViewer_ { //--------------------------------------------------------------------------------------- using std::vector; const unsigned int NotchFilter8::FILTER_ORDER = 8; const double NotchFilter8::POLE_DISTANCE = 0.995; //--------------------------------------------------------------------------------------- NotchFilter8::NotchFilter8(double fs, double freq) :a_(FILTER_ORDER +1,0), b_(FILTER_ORDER+1,0), d_(POLE_DISTANCE), fs_(fs), freq_(freq) { if(freq >= fs/2) throw(std::invalid_argument("Filter freq must be lower than fs/2!")); if(!freq) throw(std::invalid_argument("Filter freq must not be 0!")); if(!fs) throw(std::invalid_argument("Fs must not be 0!")); double w = (2 * M_PI * freq)/fs; std::complex e1(0,w); std::complex e2(0,-w); std::complex v_comp = std::exp(e1) + std::exp(e2); if(v_comp.imag()) throw(std::runtime_error("Coefficient factor has imaginary part -- something went wrong!")); double v( v_comp.real() ); b_[0] = 1; b_[1] = -4* v; b_[2] = 4 + 6 * pow(v,2); b_[3] = -12 * v -4 * pow(v,3); b_[4] = 6 + 12 * pow(v,2) + pow(v,4); b_[5] = b_[3]; b_[6] = b_[2]; b_[7] = b_[1]; b_[8] = b_[0]; a_[0] = b_[0]; a_[1] = b_[1] * d_; a_[2] = b_[2] * pow(d_, 2); a_[3] = b_[3] * pow(d_, 3); a_[4] = b_[4] * pow(d_, 4); a_[5] = b_[5] * pow(d_, 5); a_[6] = b_[6] * pow(d_, 6); a_[7] = b_[7] * pow(d_, 7); a_[8] = b_[8] * pow(d_, 8); } //--------------------------------------------------------------------------------------- //template //void NotchFilter8::filter (T& in, T& out, int in_out_size) //{ //} //--------------------------------------------------------------------------------------- } sigviewer-0.6.4/src/signal_processing/notch_filter8.h000066400000000000000000000047211345753661000227640ustar00rootroot00000000000000// Copyright 2013 Clemens Brunner, Thomas Brunner, Christoph Eibel, // Alois Schlögl, Oliver Terbu. // This file is part of SigViewer. // // SigViewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SigViewer 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 SigViewer. If not, see . #ifndef NOTCH_FILTER8_H #define NOTCH_FILTER8_H //--------------------------------------------------------------------------------------- #include "base/filter.h" #include #include namespace SigViewer_ { //--------------------------------------------------------------------------------------- class NotchFilter8 : public Filter { public: NotchFilter8(double fs, double freq); virtual void filter (double* in, double* out, int in_out_length) const { filterImpl (in, out, in_out_length); } private: template void filterImpl (T const& in, T& out, int in_out_size) const { double temp = 0; double sum = 0; boost::circular_buffer buffer(8); for(unsigned int m = 0; m < 8; m++) buffer.push_front(0); for(int n = 0; n < in_out_size; n++) { sum = 0; for(unsigned int m = 0; m < buffer.size(); m++) sum += buffer[m] * -a_[m +1]; temp = in[n] + sum; sum = temp * b_[0]; for(unsigned int m = 0; m < buffer.size(); m++) sum += buffer[m] * b_[m +1]; out[n] = sum; buffer.push_front(temp); } } static const unsigned int FILTER_ORDER; static const double POLE_DISTANCE; std::vector a_; std::vector b_; double d_; double fs_; double freq_; }; } //--------------------------------------------------------------------------------------- #endif // NOTCH_FILTER8_H sigviewer-0.6.4/src/signal_processing/signal_processing.pri000066400000000000000000000001051345753661000242600ustar00rootroot00000000000000HEADERS += \ $$PWD/FFTReal.h SOURCES += \ $$PWD/FFTReal.cpp sigviewer-0.6.4/src/sigviewer.icns000066400000000000000000001422411345753661000172140ustar00rootroot00000000000000icnsġis32UTSQ3_aluri^_3ZΥIaqJ^$'5y3G/8|̬յ])]cVr|f|a/b Ŀеuӷ\WͯNu\K<jdUTSSQjg⿎κ݁ɺȺ}º>|Dɽƾ|:sdgsp}il7ɠㇵ hnb^ ƻԴuϴ\WΰOu\K<jdUTQնʹߴګۮܵ״ز Ա bխ ڳvͻ˯\XϱOu\K<jds8mk*rnoooooooooop$#%"%vs}OYil32 "20//0nO2N)L6B@LV\chopkli_ZUPA7?$(O:KQRQbfkkjsjblh\RYSMH;J;iLѾ?C!c-GDFE<7S9>GFEH%1 ۼ{ y}Ol.  ( ̓,g]!$160! "20//0nO2 N΀)L8rx|`K(OU~鲦op`)Pf筟٪ؾ㗆k+Rf-Td꥜򡄑k`.V;blnz|qrigZP0X4=Z}lrwukaI4N1ZLl멥ۜس}J2\{I4^E^Mwd]ZdeU\FNS2P5^ELUb^^igaapxedntOozABQ6`KZPчggpvh]WMU8bǁU9c{ǮĴs_:dUY^xs|wcg^SL`;evs};iTѾ?C!c-GDFE<7S9>GFEH%1 ۼ{ y}Ol.  ( ̓,g]!$160! "20//0nO2 N׀ـ8)Lšɷ(OȷԀ?˽)Pʾ+R-T̻ż.VѦĻ0Xӡ紥1Zӭ˾İ2\ׯ4^٫忽º󺰳5^ܭǶƮ6`ްþ8b9cĽ:d޸Ŀ;e;iTҾ?C!c-GDFE<7S9>GFEH%1 ۼ{ y}Ol.  ( ̓,g]!$160! l8mkFc_`````````````````````_c;WF{}~~~~~~~~~~~~~~}ak $М/cTh}y2ԘF?glG it32q^_`a`]YB[_avh_W]a} Șa[.^a һh\'\aռhWP`ֵa@\hҋ[_۽a+SaoEVaօSWaٛRUaنٛQTaچڔڜQSaچK$XTVWYZ[]^_abdefhiklmopqrtuvxyz{|}~'~}|{zxwvusrqonmkjhgfdcb`_^\[ZXWUTRQPWKڜQUbۆ$=?ACEGHJLNORSUWXZ\^`bceghjlmoprstuvwx'wvutrqpnmkigfdca_][YXVTSQOMKIHFDB@><;97"۝RUc܆% 7=?@BDFHJKMOQSTVXZ[]_abdfgiklnoprstuuv(utsrqpnmljhgecb`^\[YWUTRPNLKIGECA@><:975۞SWd݆&2;<>@BDFGIKLNPRTVWY[\^`acefhiklnopqrsst)srrqonmljhgedba_][ZXVUSQOMLJHGECA?=<:8642ܞTWd݆:<>?ACEGHJLNOQSUVXZ[]_`bcefhiklmnopqqr1qpponmljigfdca`^\[YWVTRQOMKIHFDB@?=;98642-ܟTWeކ`68:;=?@BDFHIKMOPRTVWYZ\^_abdefhijlmmnoopponmlkjhgfdcb`_][ZXVUSRONLJIGZgV@><;975310ݠUYf߆a'579;<>@ADEGIJLNOQSUVXY[\^`abdefghikllmmnnmlkjihgfdcb`_]\ZYWUTRQOMKJH?=<:86431/-ݠUYf߆. 3578:<=?ABEFMNPRTUWXZ[]^`abcefghhijkkll.jihgfedcb`_^\ZYWVTSQONLJIGS=;986420/-ݡUYg24689;=>@BDZLMOQRTUWXZ[]^`abcdefgghizhgfeedba`݊YXVUSRPNMKJH{c<:975310.,%ޢVZh'13579:<>?ABKLNOQSTVWXZ[\^cdeefgfeddcba`_XVUTRQOMLJIGf;:86421/-,*ޣVZi/124689;=>@AJKMNPRSTVWXZ[nabccuvedcc_^]VUTRQONLKIHFہ:9M\J20.-+)ޣXZi.013oq:<=?w IJPRfuiWXY`abː ba]\[ TRQIH[z981/-,*(ߤX\j -/H9;<>΁ GbƆpq`qZ RQO\bi+)'ߥY\j ,.[ր^|jQObσ*(&Y\k,-؈ڃmN)'&Z^l+, [LQh(&% Z^m +ѷ 񅆂YPOۮ:Oly)'%$[^m*Ր݀78:;<IKLMNOPQRRہߥWWɂ SSecNM%Yg=<:97.-+*(&$[`n)+,./124578:;ˀCDFGHIJKLMNOOP€TUUT RRQPONMLLKف&BA@>=<:9864310.-,*(&%#\ap*+,./124678:tACDEFGHIJKLMMNO儁RSRe PONNMLLKJI}&A@>=<:9865320/-,*)'%$ ^ap)®(*+-.0124678:?@ABCEFGGHIJKLLMMNNOOPNMMLKKJIHGF'?>=<:9865320/.,+)'&$#^aqï")*+-.01245789;<=>?@ACDEFGGHIJJKKLLMN(`LKKJIIHGFED?><;:9865320/.,+)(&%# _crİ! )*,-.01245789:;=>?@ABCDEFFGHHIIJJKLK%JJIIHGGFEDCB\Z=<;:9764320/.,+*(&%#" _csű%)*,-.01235689:;<=>?@ABCDDEFFGHIJI$HHGGFFEDCBA@??>=;:98764320/.,+*(&%$"  _csŲ%)*,-./12346789:;<=>?@AABCDEEFGH\G#FFEEDCCBA@??>=<;:98754310FVC+*('%$" _etƳ%)*+-./02345789:;;<=>?@@AABCCDDEFE"DDCCBAA@?>>=<;:987653210*('%$" aeuǴ")*+,.2356789:;;<=>>?@@AABC$CBBAA@@??>==<;:9876543210.@&%$"  bgvȶ(*+C123456789::;<<=>>??@AV@??>>==ts9877643210/.iP%$  cgvȶ()/01234567889::s=>?>==<<;;776432210.-,T$ ch}ʸ -./0123456778O݀;<RcS=ށ<ss:995433210/.-,+ց 2 dh}˹JJM ,-jk01I[J456r:s ::887 n221,+Bf dh}˺  *EmnNN8N5 10/B 7J eh~̻2̀6]J/.Dà ej~ͽ͈уK, fj~ξ 2*$K fjϿƥ jk0۝,+њ $L_ glz{|f ؞"%(),Ӂא{.. j-,CggB)&.D |z hl  !!""d*+, ))&&#"ρ  hl Zo !""##$$%ee&> $$##"!! `  hn#  !""#$$%%&&'(&&%%$##"!!   jo%  !"##$%&&''(())*+***A((''&%%$#""  ko"  !"#$%%&'(()**+,-,+4**)(''&%$$Byx@ ko$  !"#$%&''()*++,,--./F..-4,,+**)('&%%$#"! 0B- ko$  !"#$%&'()**+,--..//0100/4..-,,+*))'&&%$#"  lo$ $%&'()*+,,-../0011232140//..-,++*)'&%$#"! / lq :%&()*+,-../001223345K4321100ki,+*)'&%$#" _D mq !')*+,-.//01223n6788665543321-,+*)('&$#"!I nq !#)*,-./0012344K݀89O`P:݁8qp543/.-,+*)'&%$"Ձ/B, ns\_ "#c +,ik01I[K567s;t ::776 l0/.(&=b os3 "#%ȁ -IqrSSY qvͱ zzFߦ=<ק'>^mqvӊx+,./1ެ>?@AABCDEF؁ܞIHł {EDXxwU?>%K[-,*)'qv!#$&')+,./12Ȁ;<=>?@ABDEEFGH}KJ GGFEDCBA@?ց&65320/-,*)'%$" sx!"$%')+,./124q<>?@ABDEFGGHIJJ倃M` IIHGFEDCBAx&865320/-,*(&%#" tx) "#%')*,-/12457=>?@BCDEFGHIJKLLMMNONKKJIHGFEDBA'9865320.-+*(&$#!ux,!#$&(*,-/023578:;=>?ABDEFGHIJKLMMNOOPPQ:PbMLLKJIHGFEC<;9865310.-+)'&$" uz, "$&')+-.023578:;=>@ABDEGHIJKLMNOPPQRRSTTS9RRQPONNMLKJIGFE^Z><;986431/.,*)'%#! vz-!#%')*,.013578:;=>@ACDFGHIKLMNOPQRSSTTUVU9TTSRRQONMLKJIHFEDBA?><;986421/-,*(&$"!vz."$&(*,-/124689;<>@ACDFGIJKLMOPQRSTTUVVWXW9VVUTSSRQONMLKIHGEDB@?=<:975320.-+)'%#" v3|#%')+-.023579;<>?ACDFGIJKMNOQRSTUVVWXXYZY9XWWVUTTSRPOMLKJHGEDB@?=<:87531/.,*(&$#!w3}$&(*,./13578:<=?ABDFGIJLMNPQRTUVWXXYZZ[\[9ZYYXWVUTSRQONLKJHGEDB@>=;986420/-+)'%$" x}̀ЀрӁԁՃւׄցՀԀӀЀ̀x } y }ЅÎŇĂ:zw}zwvzwZ^v,uvu$ޕ5sWlqZ坂 Vހہ؀׀ՀӀl#̸?.h}l?0Xxd 0Ryf+5%Hb{q_\ZP<-T]aat܂ۃڂك؂ׂփ |aa]V5 Z`bcv˦ēcc^RZbcdȆxd_OcfpÇyf]4Zghǡ朶reHah}ڊğ鞷gXPkڔlUclÝݙn>l ⪫ߕ ҜlUrʊٰ|Pl}ťĭcn̽łss.ym*u`}Ր#b({Acڇov؉${@wɿ۟Amλ٫|$@·̬[ ZƱּrZԪʱf1I}ɡıXR~̓ö`'KjqQ'@]|{bI'65_\|{|d]I4^_`a`]YB[_avh_W]a} Șa[.^a һh\'\aռhWP`ֵa@\hҋ[_۽a+SaoEVaօSWaٛRUaنٛQTaچڔڜQSaچi$|'iڜQUbۆ>%U~(}{ywa>۝RUc܆>%Ix}(}{ywu\>۞SWd݆>&Br{})~|zxvurN>ܞTWd݆>&bx{|~1}|zxvtrmA>>ܟTWeކ`>>Lvxz|~ⲱ}{ywusqpY>>ݠUYf߆a>>fvwy{}ڀ~|zxvusqomD>ݠUYf߆*>Hsuwx{|~Ϗ.ݭ}{zxvtrpnlW>ݡUYg>[rtvxz|}빜|{ywusqpnle>ޢVZh>gqsuwy{|~ʀ䦧΁͚Ӂ|zxvurqomkiFޣVZi>oqrtvxz|}ѽ䙗{yrpnljiMޣXZiDnpqs{|~ ưƁ ȋzxqomkjhRߤX\jImoz{}߁ ܵ˷˝́ ́kigRߥY\jIlnȁ߃jhfQY\kDkm€ѐ·igeQZ^l>jl ҀƁgfdIZ^m>_k ʛے{hfecC[^m>Qjⲳwxz{}ނ Ѓ%ݚ~|{ywnlkiged[>[`n>Cijlmoqrtuwxz|܀ۄـ &~|{zxvusqpnmkihfdbM>\ap>>Xiklnoqrtvwxzﲃ ꒑&~|{zxvutrpomkjhfec_@>^ap'®>>Cgiklnpqstvwxzɀ'}|{yxvutrpomljigedbO>>^aqï> Rhjklnpqstvwxz{|~(䚍~}|{yxvutrpomljigfdbZ> _crİ>"_hjklnpqrtuwxy{|}~&~}{zywvutrpomlkigfdcaD> _csű>"Cdhjklnpqrtuvxyz{|~&~}|{zxwvusrpomlkigfecaK> _csŲ>Fdhjklnoqrsuvwxz{|}~Ҁ#}|{zyxwutsqp|kihfecaM> _etƳ>Fdhjklnoprstuwxyz{|}~"}||{zxwvutrqpigfecaO> aeuǴ>Fahjklmrtuvwxyz{|}~~$˄~}||{zxwvutsrqpnxfecaK> bgvȶ>A\hij|qrstuvwxyz{||}~~~}zxwwvutrqpondc_G> cgvȶ>Rgiopqrstuvwxyzz{~~~}||{wwvutsrqpnmlʁcV@> ch}ʸ>F]mnopqrstuvwwx|}~}}|{zyvutsrqpomlkjI>ScS> dh}˹>vv>?@Ax klpquuvzz{ӡ {{xxw srqlkz>>> dh}˺> S?@BCЁ i~К臇xv qpoz gv> eh~̻>iǰ܀von}у> ej~ͽ>ڈ߃l> fj~ξ> rj[v> fjϿ>>?ս 󗘂pkkݴH[wޅ> gl>?AڜKLNOPZZ[\]`dgiknnт ll{zheftMLKJH@?> hl?ABDEFHIKLMNPQRрXYZ[[\]^^_``aajjl hheeba^]\[܁UTRQPONMKJIGFECB@?> hlACDEGHJKLNOPQSTZ[\]^^_`aabbccdefev ccbba``_^]WVUSRQPOMLKIHFEDBA?> hn"CDFGIJKMNPQRSUVW[\]^_`aabccdeefghgfeedcbba``_YXVUTSRPONLKJHGEDBA?> jo&EFGIJLMOPQSTUVXYZ[\]^_`abcddeffgghhiij(yhggfeedcbaa\[ZXWVUSRQPNMKJIGEDCA?> ko#FHIKLNOPRSUVWXZ[\]^_`abcdeffghhijjklkj3ihhgfeedcxv^\[ZYXWUTSQPOMKJIGEDCA?>>ko#HIKLNOQRTUVXYZ[]^_`abcdefghiijkkllmn~nmml3kjjihggfedcba`_]\[ZXWVhtdPOMLJIGEDCA?>ko$IKLNPQRTUWXZ[\]_`abcdefghijkklmmnnopq=ppoonnmllkjjihgfedcba_^]\ZYRPONLJIGEDB@?lo$KLNPQSTVWYZ[\^cdefghijklmmnoppqqrsrq4poonmllkjihgfedba`_]\[gRPONLJIGEDB@lqLNPQSTVWYZ\]^refghijklmnoppqrrssttuvvttssrqqppkjihgfdcba_^vTRQONLJIGEDBmqNPQSTVWYZ\]_`ghijklmnopqrssvwxxvuutsrqmlkjigfedba`Ł{UTRQONLJHFECnqOQSTVWY[\^_`bijklmnppqrstuxyzyxxuutonmlkjhgfdcaWUgscOMKJHFEnsQSTVW^_ab klpquvw{{|Ӣ {{wwv pongfvYWPOMKJHFosRTVj_abd؁ lў鋌}y rqpz}ځMKIGpuTUW~˶ހts؃NLJIquUWYuÇONLJqvVXZ ȀvvQOMKqvXZ[ ~}gvTRPNLqvY[]߫jlnoq~뵊ق Ƀ%؎mkjhf\ZYWUSQONqv[\^`bcegijlnoqrـ{|~փ &vutrpomkjhfeca_]\ZXVTRPOsx\]`acefhjlmoqrt}~ 鋊&xvutrpomkjhfdba_][YWUTRPtx)]_abdfhjkmoqrtvw}'zxvusrpnlkigfdb`^\ZYWUSQux*^`bdfgikmoprtuwyz|};圏}{zxvusqpnljigeca_]\ZXVTRuz-_acegiklnprsuwxz|}:}{zxvusqomljhfdb`_][YWUSvz-`bdfhjlnpqsuwxz|}9}{yxvtrqomkigeda`^\ZXVTvz0acegikmoqrtvxz{}9~|{ywvtrpnljifeca_][YWUv4|befhjlnprtvwy{}:~|zxwusqomkjhfdb`^\ZXVw4}degjkmoqsuwy{|~:}|zxvtrpolkigeca_][YWx}ހހx } y }܅ӆԊՂԁ?zw}zwvzwZ^v,uvu$ޕ5sWlqZ坂 Vހہ؀׀ՀӀl#̸?.h}l?0Xxd 0Ryf+5%Hb{q_\ZP<-T]aat܂ۃڂك؂ׂփ |aa]V5 Z`bcv˦ēcc^RZbcdȆxd_OcfpÇyf]4Zghǡ朶reHah}ڊğ鞷gXPkڔlUclÝݙn>l ⪫ߕ ҜlUrʊٰ|Pl}ťĭcn̽łss.ym*u`}Ր#b({Acڇov؉${@wɿ۟Amλ٫|$@·̬[ ZƱּrZԪʱf1I}ɡıXR~̓ö`'KjqQ'@]|{bI'65_\|{|d]I4^_`a`]YB[_avh_W]a} Șa[.^a һh\'\aռhWP`ֵa@\hҋ[_۽a+SaoEVaօSWaٛRUaنٛQTaچڔڜQSaچ"ރ&ڜQUbۆ$%Ϳ۝RUc܆#)˼۞SWd݆%(ʳܞTWd݆#1ƫܟTWeކ)3ȺݠUYf߆'3ƭݠUYf߆(.ƹݡUYgڀޢVZhĮޣVZiijޣXZi߁  öߤX\j  õߥY\jڀµY\kµZ^lƀ Z^m ܀[^m %[`n߀ &\ap݀ &^ap#®ڀہ܃ր'^aqï؀ـڇ( _crİ׀؀وڀـ _csűՀׂ؄ف؀ _csŲՁփ׀ր _etƳҀԁՂցՀ aeuǴҀӃԀӀ bgvȶ̀ Ѐс҂؂ӀҀց cgvȶср ch}ʸπ氩 dh}˹ā  ℩ dh}˺  eh~̻ځց ej~ͽހ fj~ξ ܁ fjϿ ׂŀޯɂ glβں ijӫ hl깺Łނ  hlì̀ ӻӃρ hnĭ⻼ˆܺ joـÃăɀ!𼻺 koƮÀāʼnƁĀ/ǽkoȯĀŀƆǁŀ.ĽkoɰĀƀǂȂȀ2鶵loʱǀȁɄȀ/lq˲ŀ ǀɀʃтˁρŷmq̳̂ˀȸnqʹ̀幸Ľns͵Ͻҁ ܀ 浴osͶ  ɲpuͷ̀ځ䳲qu͸䴳qv͸ ˵qv͹ Ѐҷqvͺ Ԁ %ܼqvͻ &sxͼۀ ߁&tx'ͼڀۆӀ'ux'ͽۀ܂ނ9uz*;݀ބ߁7vz*;ހ߇߀4vz-Ϳ8v1|5w0}9x }x } y }?zw}zwvzwZ^v,uvu$ޕ5sWlqZ坂 Vހہ؀׀ՀӀl#̸?.h}l?0Xxd 0Ryf+5%Hb{q_\ZP<-T]aat܂ۃڂك؂ׂփ |aa]V5 Z`bcv˦ēcc^RZbcdȆxd_OcfpÇyf]4Zghǡ朶reHah}ڊğ鞷gXPkڔlUclÝݙn>l ⪫ߕ ҜlUrʊٰ|Pl}ťĭcn̽łss.ym*u`}Ր#b({Acڇov؉${@wɿ۟Amλ٫|$@·̬[ ZƱּrZԪʱf1I}ɡıXR~̓ö`'KjqQ'@]|{bI'65_\|{|d]I4t8mk@Ag2{ s!' Sv.j70jAP#Z* _- `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `. `.v`.L_- Z* ~P#?rA $ڇ_08qF !Fܝ|U,(L|Z4)IiܼsU5$>ZouaH- -@R_imooooooooooooooooooooorwpoooooooooooooooooooooomkcWF3 $-3677777777777777777777R=977777777777777777777750' "m9 J=RC "sxQ& g2HY) e1 yi3 2e1Y) 7uG $Y…^13fÍkB;kpJ&  ;_֞lJ) 7X~詑}bC&/JfܶoT8#9RjШs\B*  ';Rhz֯oZD/ &9M`q~ɮudR>, !0@P`o{í~seUD3%#0=KYfqz|si\OA3& )3>IS^gnuz|vqi`VL@6,#  %,39AHOV\`eimoooooooooomkhb]XRKD<5.'   #&+.1467777777777752/,($   icnV Bsigviewer-0.6.4/src/src.qrc000066400000000000000000000033521345753661000156270ustar00rootroot00000000000000 images/ic_reorder_black_24dp.png images/ic_pan_tool_black_24dp.png images/ic_create_black_24dp.png images/sigviewer16.png images/sigviewer128.png images/ic_flag_black_24dp.png images/ic_add_box_black_24dp.png images/ic_content_copy_black_24dp.png images/ic_font_download_black_24dp.png images/ic_info_outline_black_24dp.png images/ic_clear_black_24dp.png images/ic_folder_open_black_24dp.png images/ic_save_black_24dp.png images/ic_chevron_left_black_24dp.png images/ic_chevron_right_black_24dp.png images/ic_redo_black_24dp.png images/ic_undo_black_24dp.png images/ic_delete_forever_black_24dp.png images/ic_add_circle_outline_black_24dp.png images/ic_build_black_24dp.png images/ic_zoom_in_v_black_24dp.png images/ic_zoom_out_v_black_24dp.png images/ic_zoom_in_h_black_24dp.png images/ic_zoom_out_h_black_24dp.png images/ic_directions_run_black_24dp.png images/ic_autoscale_black_24dp.png images/ic_zoom_out_map_black_24dp.png images/ic_help_outline_black_24dp.png color_settings.xml images/ic_file_upload_black_24dp.png images/ic_file_download_black_24dp.png sigviewer-0.6.4/src/src.rc000066400000000000000000000001121345753661000154350ustar00rootroot00000000000000IDI_ICON1 ICON DISCARDABLE "images/sigviewer.ico" sigviewer-0.6.4/src/tab_context.cpp000066400000000000000000000044301345753661000173450ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "tab_context.h" #include namespace sigviewer { //----------------------------------------------------------------------------- TabContext::TabContext () : selection_state_ (TAB_STATE_NO_EVENT_SELECTED), edit_state_ (TAB_STATE_NO_REDO_NO_UNDO) { // nothing to do here } //----------------------------------------------------------------------------- TabContext::~TabContext () { emit selectionStateChanged (NO_TAB_SELECTION_STATE); emit editStateChanged (NO_TAB_EDIT_STATE); } //----------------------------------------------------------------------------- void TabContext::gotActive () { emit selectionStateChanged (selection_state_); emit editStateChanged (edit_state_); } //----------------------------------------------------------------------------- void TabContext::executeCommand (QUndoCommand* command) { edit_undo_stack_.push (command); updateUndoRedoEditState (); } //------------------------------------------------------------------------- void TabContext::undo () { edit_undo_stack_.undo (); updateUndoRedoEditState (); } //------------------------------------------------------------------------- void TabContext::redo () { edit_undo_stack_.redo (); updateUndoRedoEditState (); } //----------------------------------------------------------------------------- void TabContext::updateUndoRedoEditState () { if (!edit_undo_stack_.canUndo () && !edit_undo_stack_.canRedo()) setEditState (TAB_STATE_NO_REDO_NO_UNDO); else if (!edit_undo_stack_.canUndo ()) setEditState (TAB_STATE_NO_UNDO); else if (!edit_undo_stack_.canRedo()) setEditState (TAB_STATE_NO_REDO); else setEditState (TAB_STATE_CAN_REDO_UNDO); } //----------------------------------------------------------------------------- void TabContext::setSelectionState (TabSelectionState state) { selection_state_ = state; emit selectionStateChanged (selection_state_); } //----------------------------------------------------------------------------- void TabContext::setEditState (TabEditState state) { edit_state_ = state; emit editStateChanged (edit_state_); } } sigviewer-0.6.4/src/tab_context.h000066400000000000000000000040311345753661000170070ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef TAB_CONTEXT_H #define TAB_CONTEXT_H #include "base/tab_states.h" #include "command_executer.h" #include #include #include namespace sigviewer { class TabContext : public QObject, public CommandExecuter { Q_OBJECT public: //------------------------------------------------------------------------- TabContext (); //------------------------------------------------------------------------- ~TabContext (); //------------------------------------------------------------------------- void gotActive (); //------------------------------------------------------------------------- virtual void executeCommand (QUndoCommand* command); //------------------------------------------------------------------------- virtual void undo (); //------------------------------------------------------------------------- virtual void redo (); signals: //------------------------------------------------------------------------- void selectionStateChanged (TabSelectionState state); //------------------------------------------------------------------------- void editStateChanged (TabEditState state); public slots: //------------------------------------------------------------------------- void setSelectionState (TabSelectionState state); //------------------------------------------------------------------------- void setEditState (TabEditState state); private: //------------------------------------------------------------------------- // disabled TabContext (TabContext const&); TabContext& operator= (TabContext const&); //------------------------------------------------------------------------- void updateUndoRedoEditState (); TabSelectionState selection_state_; TabEditState edit_state_; QUndoStack edit_undo_stack_; }; } #endif // TAB_CONTEXT_H sigviewer-0.6.4/src/tests/000077500000000000000000000000001345753661000154705ustar00rootroot00000000000000sigviewer-0.6.4/src/tests/color_manager_tests.cpp000066400000000000000000000016661345753661000222370ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "color_manager_tests.h" #include "gui/color_manager.h" namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- ColorManagerTests::ColorManagerTests () : Test (tr("ColorManager Tests")) { // nothing to do here } //----------------------------------------------------------------------------- QString ColorManagerTests::run () { QSharedPointer color_manager = applicationContext ()->getEventColorManager(); VERIFY (color_manager.isNull() == false, "initialized"); VERIFY (color_manager->getDefaultEventColor() == QColor (200, 0, 0, 30), "default color"); VERIFY (color_manager->getDefaultEventColor(0x0300) == QColor (0, 0, 200, 30), "Start of Trial color"); return ""; } } } sigviewer-0.6.4/src/tests/color_manager_tests.h000066400000000000000000000006301345753661000216720ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef COLOR_MANAGER_TESTS_H #define COLOR_MANAGER_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class ColorManagerTests : public Test { public: ColorManagerTests(); virtual QString run (); }; } } #endif // COLOR_MANAGER_TESTS_H sigviewer-0.6.4/src/tests/data_block_tests.cpp000066400000000000000000000062401345753661000215030ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "data_block_tests.h" #include "base/fixed_data_block.h" #include namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- DataBlockTests::DataBlockTests () : Test (tr("DataBlock")) { // nothing to do here } //----------------------------------------------------------------------------- QString DataBlockTests::run () { QSharedPointer > ten_data (new QVector); for (unsigned i = 1; i <= 10; i++) ten_data->push_back (i); FixedDataBlock ten_block (ten_data, 10); VERIFY (ten_block.size() == static_cast(ten_data->size()), "created with 10 elements"); VERIFY (ten_block.getMax() == 10, "get max"); VERIFY (ten_block.getMin() == 1, "get min"); for (unsigned i = 1; i <= 10; i++) VERIFY (ten_block[i-1] == i, "check content"); QString error = testMean (); if (error.size() > 0) return error; return ""; } //----------------------------------------------------------------------------- QString DataBlockTests::testMean () { QSharedPointer > ten_data (new QVector); QSharedPointer > ten_reverse_data (new QVector); for (unsigned i = 1; i <= 10; i++) { ten_data->push_back (i); ten_reverse_data->push_back (11-i); } QSharedPointer ten_block1 (new FixedDataBlock (ten_data, 10)); QSharedPointer ten_block2 (new FixedDataBlock (ten_data, 10)); QSharedPointer ten_block_revers (new FixedDataBlock (ten_reverse_data, 10)); std::list > blocks; blocks.push_back (ten_block1); blocks.push_back (ten_block2); // Test 1 QSharedPointer mean = FixedDataBlock::calculateMean (blocks); VERIFY (mean->size() == 10, "mean number of elements") for (unsigned x = 0; x < 10; x++) VERIFY (mean->operator [](x) == (x + 1), "mean checking elements") QSharedPointer std_dev = FixedDataBlock::calculateStandardDeviation (blocks); VERIFY (std_dev->size() == 10, "std-dev number of elements") for (unsigned x = 0; x < 10; x++) VERIFY ((*std_dev)[x] == 0, "std-dev checking elements") // Test 2 blocks.pop_back (); blocks.push_back (ten_block_revers); QSharedPointer mean_revers = FixedDataBlock::calculateMean (blocks); VERIFY (mean_revers->size() == 10, "mean 2 number of elements") for (unsigned x = 0; x < 10; x++) VERIFY ((mean_revers->operator [](x) == 5.5f), "mean 2 checking elements") QSharedPointer std_dev_revers = FixedDataBlock::calculateStandardDeviation (blocks); VERIFY (std_dev_revers->size() == 10, "std-dev 2 number of elements") for (unsigned x = 0; x < 10; x++) VERIFY (((*std_dev_revers)[x]) == sqrt((pow((*ten_block1)[x] - 5.5f, 2) + pow((*ten_block_revers)[x] - 5.5f, 2)) / blocks.size()), "std-dev 2 checking elements") return ""; } } } sigviewer-0.6.4/src/tests/data_block_tests.h000066400000000000000000000010671345753661000211520ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef DATA_BLOCK_TESTS_H #define DATA_BLOCK_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- /// DataBlockTests /// runs tests on the DataBlock class class DataBlockTests : public Test { public: DataBlockTests (); virtual QString run (); private: QString testMean (); }; } } #endif // DATA_BLOCK_TESTS_H sigviewer-0.6.4/src/tests/editing_commands_tests.cpp000066400000000000000000000063001345753661000227210ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "editing_commands_tests.h" #include "editing_commands/change_channel_undo_command.h" #include "editing_commands/change_type_undo_command.h" #include "editing_commands/delete_event_undo_command.h" #include "editing_commands/new_event_undo_command.h" #include "editing_commands/resize_event_undo_command.h" #include namespace sigviewer { namespace Tests_ { QString EditingCommandsTests::run () { QSharedPointer event_manager = createEventManagerWithDummyData(); QSharedPointer event = event_manager->getEvent (1); EventID id = event->getId(); QUndoStack stack; unsigned const initial_number_of_events = event_manager->getNumberOfEvents(); ChannelID const old_channel = event->getChannel(); EventType const old_type = event->getType(); uint32 const old_position = event->getPosition(); uint32 const old_duration = event->getDuration(); ChannelID const new_channel = 1; EventType const new_type = 4; uint32 const new_position = 0; uint32 const new_duration = 250; QUndoCommand* change_channel = new ChangeChannelUndoCommand (event_manager, id, new_channel); QUndoCommand* change_type = new ChangeTypeUndoCommand (event_manager, id, new_type); QUndoCommand* delete_event = new DeleteEventUndoCommand (event_manager, id); QUndoCommand* new_event = new NewEventUndoCommand (event_manager, QSharedPointer(new SignalEvent (10, 10, 100, 1, 100)), 1); QUndoCommand* resize_event = new ResizeEventUndoCommand (event_manager, id, new_position, new_duration); stack.push (change_channel); VERIFY (event_manager->getEvent(id)->getChannel() == new_channel, "change channel"); stack.undo(); VERIFY (event_manager->getEvent(id)->getChannel() == old_channel, "change channel undo"); stack.push (change_type); VERIFY (event_manager->getEvent(id)->getType() == new_type, "change type"); stack.undo(); VERIFY (event_manager->getEvent(id)->getType() == old_type, "change type undo"); stack.push (delete_event); VERIFY (event_manager->getEvent(id).isNull(), "delete event"); VERIFY (event_manager->getNumberOfEvents() == (initial_number_of_events - 1), "delete event 2"); stack.undo(); VERIFY (!event_manager->getEvent(id).isNull(), "delete event undo"); VERIFY (event_manager->getNumberOfEvents() == initial_number_of_events, "delete event undo 2"); stack.push (new_event); VERIFY (event_manager->getNumberOfEvents() == (initial_number_of_events + 1), "new event"); stack.undo (); VERIFY (event_manager->getNumberOfEvents() == initial_number_of_events, "new event undo"); stack.push (resize_event); VERIFY (event_manager->getEvent(id)->getPosition() == new_position, "resize event"); VERIFY (event_manager->getEvent(id)->getDuration() == new_duration, "resize event 2"); stack.undo (); VERIFY (event_manager->getEvent(id)->getPosition() == old_position, "resize event undo"); VERIFY (event_manager->getEvent(id)->getDuration() == old_duration, "resize event undo 2"); return ""; } } } sigviewer-0.6.4/src/tests/editing_commands_tests.h000066400000000000000000000007171345753661000223740ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EDITING_COMMANDS_TESTS_H #define EDITING_COMMANDS_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class EditingCommandsTests : public Test { public: EditingCommandsTests () : Test ("Editing Commands Tests") {} virtual QString run (); }; } } #endif // EDITING_COMMANDS_TESTS_H sigviewer-0.6.4/src/tests/event_manager_tests.cpp000066400000000000000000000023731345753661000222360ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_manager_tests.h" namespace sigviewer { namespace Tests_ { QString EventManagerTests::run () { QSharedPointer event_manager = createEventManagerWithDummyData(); VERIFY (event_manager->getAllEvents().size() == 44, "event amount"); foreach (EventID event, event_manager->getAllEvents()) { VERIFY (event_manager->getEvent(event).isNull() == false, "event exists"); } RUN_SUB_TEST(testEventCreation(event_manager)); return ""; } QString EventManagerTests::testEventCreation (QSharedPointer evt_mgr) { QSharedPointer event = evt_mgr->createEvent (1, 10, 100, 1, UNDEFINED_STREAM_ID); VERIFY (event.isNull() == false, "event created"); VERIFY (event->getChannel() == 1, "event created channel"); VERIFY (event->getDuration() == 100, "event created duration"); VERIFY (event->getDurationInSec() == 100 / evt_mgr->getSampleRate(), "event created duration in sec"); VERIFY (event->getPosition() == 10, "event created position"); VERIFY (event->getType() == 1, "event created type"); return ""; } } } sigviewer-0.6.4/src/tests/event_manager_tests.h000066400000000000000000000010141345753661000216720ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_MANAGER_TESTS_H #define EVENT_MANAGER_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class EventManagerTests : public Test { public: EventManagerTests () : Test(tr("EventManager Tests")) {} virtual QString run (); private: QString testEventCreation (QSharedPointer evt_mgr); }; } } #endif // EVENT_MANAGER_TESTS_H sigviewer-0.6.4/src/tests/event_table_widget_tests.cpp000066400000000000000000000111631345753661000232530ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "event_table_widget_tests.h" #include "gui_impl/event_table/event_table_widget.h" namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- QString EventTableWidgetTests::run () { QSharedPointer event_manager = createEventManagerWithDummyData(); RUN_SUB_TEST (basicCreation (event_manager)); RUN_SUB_TEST (newEvents (event_manager)); RUN_SUB_TEST (deleteEvents (event_manager)); RUN_SUB_TEST (changedEvents (event_manager)); return ""; } //----------------------------------------------------------------------------- QString EventTableWidgetTests::basicCreation (QSharedPointer event_manager) { EventTableWidget event_table (QSharedPointer(new TabContext()), event_manager, getChannelManagerDummyData()); VERIFY (static_cast(event_table.ui_.event_table_->rowCount()) == event_manager->getNumberOfEvents(), "number events"); return ""; } //----------------------------------------------------------------------------- QString EventTableWidgetTests::newEvents (QSharedPointer event_manager) { ChannelID const CHANNEL = 1; unsigned const POS = 10; unsigned const LENGTH = 12; EventType const TYPE = 0x03; EventTableWidget event_table (QSharedPointer(new TabContext()), event_manager, getChannelManagerDummyData()); QTableWidget* table = event_table.ui_.event_table_; int old_row_count = table->rowCount(); QSharedPointer event = event_manager->createEvent (CHANNEL, POS, LENGTH, TYPE, UNDEFINED_STREAM_ID); VERIFY (old_row_count + 1 == table->rowCount(), "one event more"); bool contains_new_event = false; for (int row = 0; row < table->rowCount(); row++) { QTableWidgetItem* table_item = table->item(row, EventTableWidget::ID_INDEX_); if (table_item->text() == QString::number(event->getId())) { contains_new_event = true; VERIFY (table->item(row, EventTableWidget::CHANNEL_INDEX_)->text() == getChannelManagerDummyData().getChannelLabel(CHANNEL), "channel fits"); } } VERIFY (contains_new_event, "contains new event"); return ""; } //----------------------------------------------------------------------------- QString EventTableWidgetTests::deleteEvents (QSharedPointer event_manager) { EventID const EVENT_ID = 2; EventTableWidget event_table (QSharedPointer(new TabContext()), event_manager, getChannelManagerDummyData()); QTableWidget* table = event_table.ui_.event_table_; int old_row_count = table->rowCount(); event_manager->removeEvent (EVENT_ID); VERIFY (old_row_count - 1 == table->rowCount(), "one event less"); bool contains_deleted_event = false; for (int row = 0; row < table->rowCount(); row++) if (table->item(row, EventTableWidget::ID_INDEX_)->text() == QString::number(EVENT_ID)) contains_deleted_event = true; VERIFY (!contains_deleted_event, "not contains deleted event"); return ""; } //----------------------------------------------------------------------------- QString EventTableWidgetTests::changedEvents (QSharedPointer event_manager) { EventID const EVENT_ID = 4; EventType const OLD_TYPE = event_manager->getEvent (EVENT_ID)->getType(); EventType const NEW_TYPE = OLD_TYPE + 1; ChannelID const NEW_CHANNEL = 3; EventTableWidget event_table (QSharedPointer(new TabContext()), event_manager, getChannelManagerDummyData()); QTableWidget* table = event_table.ui_.event_table_; int old_row_count = table->rowCount(); { QSharedPointer event_for_editing = event_manager->getAndLockEventForEditing (EVENT_ID); event_for_editing->setType (NEW_TYPE); event_for_editing->setChannel (NEW_CHANNEL); event_manager->updateAndUnlockEvent (EVENT_ID); } VERIFY (old_row_count == table->rowCount(), "same amount fo events"); for (int row = 0; row < table->rowCount(); row++) { if (table->item(row, EventTableWidget::ID_INDEX_)->text().toInt() == EVENT_ID) { VERIFY (table->item(row, EventTableWidget::TYPE_INDEX_)->text() == event_manager->getNameOfEventType(NEW_TYPE), "types match"); VERIFY (table->item(row, EventTableWidget::CHANNEL_INDEX_)->text() == getChannelManagerDummyData ().getChannelLabel (NEW_CHANNEL), "channels match"); } } return ""; } } } sigviewer-0.6.4/src/tests/event_table_widget_tests.h000066400000000000000000000013761345753661000227250ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef EVENT_TABLE_WIDGET_TESTS_H #define EVENT_TABLE_WIDGET_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class EventTableWidgetTests : public Test { public: EventTableWidgetTests () : Test(tr("Event Table Tests")) {} virtual QString run (); private: QString basicCreation (QSharedPointer event_manager); QString newEvents (QSharedPointer event_manager); QString deleteEvents (QSharedPointer event_manager); QString changedEvents (QSharedPointer event_manager); }; } } #endif // EVENT_TABLE_WIDGET_TESTS_H sigviewer-0.6.4/src/tests/file_handling_tests.cpp000066400000000000000000000061721345753661000222070ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "file_handling_tests.h" #include "gui_impl/commands/open_file_gui_command.h" #include "file_handling/file_signal_writer_factory.h" #include "file_handling/file_signal_reader_factory.h" #include namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- void FileHandlingTests::init () { OpenFileGuiCommand::openFile ("blub.sinusdummy"); } //----------------------------------------------------------------------------- QString FileHandlingTests::run () { RUN_SUB_TEST (testEventExportingImporting()) return ""; } //----------------------------------------------------------------------------- void FileHandlingTests::cleanup () { action("Close")->trigger(); } //----------------------------------------------------------------------------- QString FileHandlingTests::testEventExportingImporting () { QTemporaryFile event_file ("XXXXXX.evt"); event_file.open(); event_file.close(); QSharedPointer writer (FileSignalWriterFactory::getInstance()->getHandler(event_file.fileName())); VERIFY (writer.isNull() == false, "EVT writer not created") QString error = writer->save (applicationContext()->getCurrentFileContext()); VERIFY (error.size() == 0, error) QSharedPointer reader (FileSignalReaderFactory::getInstance()->getHandler(event_file.fileName())); VERIFY (reader.isNull() == false, "EVT reader not created") QList > events = reader->getEvents(); QSharedPointer event_manager = applicationContext()->getCurrentFileContext()->getEventManager(); VERIFY (static_cast(events.size()) == event_manager->getNumberOfEvents(), "not all events in file") QTemporaryFile event_file_2 ("XXXXXX.evt"); event_file_2.open(); event_file_2.close(); QSharedPointer writer_2 (FileSignalWriterFactory::getInstance()->getHandler(event_file_2.fileName())); VERIFY (writer_2.isNull() == false, "EVT writer 2 not created") std::set exported_event_types; exported_event_types.insert (event_manager->getEvent(0)->getType()); error = writer_2->save (applicationContext()->getCurrentFileContext(), exported_event_types); VERIFY (error.size() == 0, error) QSharedPointer reader_2 (FileSignalReaderFactory::getInstance()->getHandler(event_file_2.fileName())); events = reader_2->getEvents(); VERIFY (events.size() == event_manager->getEvents(*(exported_event_types.begin())).size(), "EVT writer 2, not all events in file") foreach (EventID event_id, event_manager->getEvents(*(exported_event_types.begin()))) { bool event_exists = false; foreach (QSharedPointer event, events) { if (event->equals(*(event_manager->getEvent(event_id)))) event_exists = true; } VERIFY (event_exists, "loaded events") } return ""; } } } sigviewer-0.6.4/src/tests/file_handling_tests.h000066400000000000000000000010561345753661000216500ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef FILE_HANDLING_TESTS_H #define FILE_HANDLING_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class FileHandlingTests : public Test { public: FileHandlingTests() : Test (tr("File Handling Tests")) {} virtual void init (); virtual QString run (); virtual void cleanup (); private: QString testEventExportingImporting (); }; } } #endif // FILE_HANDLING_TESTS_H sigviewer-0.6.4/src/tests/gui_tests.cpp000066400000000000000000000077361345753661000202170ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "gui_tests.h" #include "gui_impl/commands/open_file_gui_command.h" #include "gui/application_context.h" namespace sigviewer { namespace Tests_ { //----------------------------------------------------------------------------- void GuiTests::init () { animations_triggered_ = false; if (action("Animations")->isChecked()) { action("Animations")->trigger(); animations_triggered_ = true; } } //----------------------------------------------------------------------------- QString GuiTests::run () { RUN_SUB_TEST (testEnablednessNoOpenFile()) OpenFileGuiCommand::openFile ("blub.sinusdummy"); VERIFY (applicationContext()->getCurrentFileContext().isNull() != true, "open file") RUN_SUB_TEST (testZooming ()) RUN_SUB_TEST (testEventEditing ()) currentVisModel()->selectChannel(1); action("Hide Channel")->trigger(); VERIFY (currentVisModel()->getShownChannels().count(1) == 0, "hide channel") action("Close")->trigger(); VERIFY (applicationContext()->getCurrentFileContext().isNull() == true, "closed file") RUN_SUB_TEST (testEnablednessNoOpenFile()) return ""; } //----------------------------------------------------------------------------- void GuiTests::cleanup () { if (animations_triggered_) action ("Animations")->trigger(); } //----------------------------------------------------------------------------- QString GuiTests::testZooming () { /* unsigned old_signal_height = currentVisModel()->getSignalHeight(); action("Zoom In Vertical")->trigger(); unsigned new_signal_height = currentVisModel()->getSignalHeight(); VERIFY (new_signal_height > old_signal_height, tr("zoom in vertically, old = ") + QString::number(old_signal_height) + "; new = " + QString::number(new_signal_height)); old_signal_height = new_signal_height; action("Zoom Out Vertical")->trigger(); new_signal_height = currentVisModel()->getSignalHeight(); VERIFY (new_signal_height < old_signal_height, tr("zoom out vertically")); float32 old_pixel_per_sample = currentVisModel()->getPixelPerSample(); action("Zoom In Horizontal")->trigger(); float32 new_pixel_per_sample = currentVisModel()->getPixelPerSample(); VERIFY (new_pixel_per_sample > old_pixel_per_sample, "zoom in horizontally"); old_pixel_per_sample = currentVisModel()->getPixelPerSample(); action("Zoom Out Horizontal")->trigger(); new_pixel_per_sample = currentVisModel()->getPixelPerSample(); VERIFY (new_pixel_per_sample < old_pixel_per_sample, "zoom out horizontally"); */ return ""; } //----------------------------------------------------------------------------- QString GuiTests::testEventEditing () { currentVisModel()->selectEvent(1); action ("Delete")->trigger(); VERIFY (currentVisModel()->getEventManager()->getEvent(1).isNull(), "delete event"); action ("Undo")->trigger(); VERIFY (currentVisModel()->getEventManager()->getEvent(1).isNull() == false, "undo delete event"); applicationContext()->getCurrentFileContext()->setState(FILE_STATE_UNCHANGED); return ""; } //----------------------------------------------------------------------------- QString GuiTests::testEnablednessNoOpenFile () { QStringList enabled_on_startup; enabled_on_startup << "Animations" << "Open..." << "Set Animation Duration" << "About" << "Run Tests..." << "Exit"; QList actions = GuiActionFactory::getInstance()->getQActions(); foreach (QAction* action, actions) { VERIFY (((action->isEnabled() && enabled_on_startup.contains(action->text())) || ((action->isEnabled() == false) && (!enabled_on_startup.contains(action->text())))), QString("Action not disabled: ").append(action->text())) } return ""; } } } sigviewer-0.6.4/src/tests/gui_tests.h000066400000000000000000000011161345753661000176460ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef GUI_TESTS_H #define GUI_TESTS_H #include "test.h" namespace sigviewer { namespace Tests_ { class GuiTests : public Test { public: GuiTests() : Test (tr("GUI Tests")) {} virtual void init (); virtual QString run (); virtual void cleanup (); private: QString testZooming (); QString testEventEditing (); QString testEnablednessNoOpenFile (); bool animations_triggered_; }; } } #endif // GUI_TESTS_H sigviewer-0.6.4/src/tests/test.cpp000066400000000000000000000035331345753661000171570ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "test.h" #include "file_handling_impl/event_manager_impl.h" #include "file_handling_impl/channel_manager_impl.h" #include "file_handling/file_signal_reader_factory.h" #include "application_context_impl.h" #include "gui/gui_action_factory.h" namespace sigviewer { namespace Tests_ { //------------------------------------------------------------------------- Test::Test (QString const& name) : name_ (name), passed_tests_(0), channel_manager_ (new ChannelManagerImpl (FileSignalReaderFactory::getInstance()->getHandler("blub.sinusdummy"))) { } //------------------------------------------------------------------------- ChannelManager const& Test::getChannelManagerDummyData () { return *channel_manager_; } //------------------------------------------------------------------------- QSharedPointer Test::createEventManagerWithDummyData () { FileSignalReader* reader = FileSignalReaderFactory::getInstance()->getHandler("blub.sinusdummy"); QSharedPointer evt_mgr (new EventManagerImpl(*reader)); delete reader; return evt_mgr; } //------------------------------------------------------------------------- QSharedPointer Test::applicationContext () { return ApplicationContextImpl::getInstance(); } //------------------------------------------------------------------------- QAction* Test::action (QString const& action_name) { return GuiActionFactory::getInstance()->getQAction(action_name); } //------------------------------------------------------------------------- QSharedPointer Test::currentVisModel () { return applicationContext()->getMainWindowModel()->getCurrentSignalVisualisationModel(); } } } sigviewer-0.6.4/src/tests/test.h000066400000000000000000000036241345753661000166250ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef TEST_H #define TEST_H #include "file_handling/event_manager.h" #include "gui/application_context.h" #include #include #include namespace sigviewer { namespace Tests_ { #define VERIFY(condition, message) {if(!(condition)) return QString(message).append("; ").append(__FUNCTION__).append(":").append(QString::number(__LINE__)); else increasePassedTests();} #define RUN_SUB_TEST(subtest) {QString result = subtest; if (result.size()) return result;} //----------------------------------------------------------------------------- /// Test /// base class for all tests class Test : public QObject { Q_OBJECT public: Test (QString const& name); QString getName () {return name_;} unsigned passed () {return passed_tests_;} virtual void init () {}; virtual QString run () = 0; virtual void cleanup () {}; protected: void increasePassedTests () {passed_tests_++;} //------------------------------------------------------------------------- ChannelManager const& getChannelManagerDummyData (); //------------------------------------------------------------------------- QSharedPointer createEventManagerWithDummyData (); //------------------------------------------------------------------------- QSharedPointer applicationContext (); //------------------------------------------------------------------------- QAction* action (QString const& action_name); //------------------------------------------------------------------------- QSharedPointer currentVisModel (); private: QString name_; unsigned passed_tests_; QSharedPointer channel_manager_; }; } } #endif // TEST_H sigviewer-0.6.4/src/tests/tests.pri000066400000000000000000000012331345753661000173450ustar00rootroot00000000000000HEADERS += \ $$PWD/color_manager_tests.h \ $$PWD/data_block_tests.h \ $$PWD/editing_commands_tests.h \ $$PWD/event_manager_tests.h \ $$PWD/event_table_widget_tests.h \ $$PWD/file_handling_tests.h \ $$PWD/gui_tests.h \ $$PWD/test.h \ $$PWD/tests_dialog.h \ $$PWD/tests_factory.h SOURCES += \ $$PWD/color_manager_tests.cpp \ $$PWD/data_block_tests.cpp \ $$PWD/editing_commands_tests.cpp \ $$PWD/event_manager_tests.cpp \ $$PWD/event_table_widget_tests.cpp \ $$PWD/file_handling_tests.cpp \ $$PWD/gui_tests.cpp \ $$PWD/test.cpp \ $$PWD/tests_dialog.cpp \ FORMS += \ $$PWD/tests_dialog.ui sigviewer-0.6.4/src/tests/tests_dialog.cpp000066400000000000000000000037351345753661000206650ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #include "tests_dialog.h" #include "tests_factory.h" #include "gui_impl/commands/open_file_gui_command.h" namespace sigviewer { using namespace Tests_; //----------------------------------------------------------------------------- TestsDialog::TestsDialog () { ui_.setupUi (this); ui_.progressBar->setValue (0); } //----------------------------------------------------------------------------- void TestsDialog::runTests () { QList > tests = TestsFactory_::allTests (); ui_.progressBar->setMaximum (tests.size ()); ui_.progressBar->setValue (0); unsigned fails = 0; foreach (QSharedPointer test, tests) { QColor color; QString test_name = test->getName(); test->init(); QString result = test->run(); test->cleanup(); if (result.size()) { test_name += tr(" failed: ") + result; color = QColor (255, 0, 0, 50); fails++; } else { test_name += tr(": passed ") + QString::number(test->passed()) + tr(" verifications"); color = QColor (0, 255, 0, 50); } ui_.listWidget->addItem (test_name); ui_.listWidget->item (ui_.listWidget->count() - 1)->setBackgroundColor (color); ui_.progressBar->setValue(ui_.progressBar->value()+1); } if (fails) ui_.listWidget->addItem(QString::number(fails) + " tests failed!"); else ui_.listWidget->addItem("All tests passed!"); } //----------------------------------------------------------------------------- void TestsDialog::on_start_button__clicked () { runTests(); } //----------------------------------------------------------------------------- void TestsDialog::on_open_dummy__clicked () { OpenFileGuiCommand::openFile ("blub.sinusdummy"); close(); } } sigviewer-0.6.4/src/tests/tests_dialog.h000066400000000000000000000013211345753661000203170ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef TESTS_DIALOG_H #define TESTS_DIALOG_H #include "ui_tests_dialog.h" #include "test.h" #include #include #include namespace sigviewer { //----------------------------------------------------------------------------- /// TestsDialog /// executes tests and displays results class TestsDialog : public QDialog { Q_OBJECT public: TestsDialog (); private slots: void on_start_button__clicked (); void on_open_dummy__clicked (); private: void runTests (); Ui::TestDialog ui_; }; } #endif // TESTS_DIALOG_H sigviewer-0.6.4/src/tests/tests_dialog.ui000066400000000000000000000040421345753661000205100ustar00rootroot00000000000000 TestDialog 0 0 398 298 Tests 24 Start Open Dummy Data Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() TestDialog accept() 248 254 157 274 buttonBox rejected() TestDialog reject() 316 260 286 274 sigviewer-0.6.4/src/tests/tests_factory.h000066400000000000000000000024521345753661000205350ustar00rootroot00000000000000// Copyright (c) 2016 The SigViewer Development Team // Licensed under the GNU General Public License (GPL) // https://www.gnu.org/licenses/gpl #ifndef TESTS_FACTORY_H #define TESTS_FACTORY_H #include "test.h" #include "event_manager_tests.h" #include "data_block_tests.h" #include "editing_commands_tests.h" #include "gui_tests.h" #include "color_manager_tests.h" #include "file_handling_tests.h" #include "event_table_widget_tests.h" #include #include namespace sigviewer { namespace TestsFactory_ { //----------------------------------------------------------------------------- QList > allTests () { QList > tests; tests.append (QSharedPointer(new Tests_::DataBlockTests)); tests.append (QSharedPointer(new Tests_::ColorManagerTests)); tests.append (QSharedPointer(new Tests_::EventManagerTests)); tests.append (QSharedPointer(new Tests_::EditingCommandsTests)); tests.append (QSharedPointer(new Tests_::GuiTests)); tests.append (QSharedPointer(new Tests_::FileHandlingTests)); tests.append (QSharedPointer(new Tests_::EventTableWidgetTests)); return tests; } } } #endif // TESTS_FACTORY_H sigviewer-0.6.4/src/translations/000077500000000000000000000000001345753661000170475ustar00rootroot00000000000000sigviewer-0.6.4/src/translations/sigviewer_de.ts000066400000000000000000000263601345753661000221020ustar00rootroot00000000000000 BioSig_::BasicHeaderInfoDialog Basic Header Info Basis Header Info Close Schließen Property Eigenschaft Value Wert Unit Einheit Channels Kanäle Filter Filter Notch Notch yes ja no nein Lowpass Tiefpass Hz Hz Highpass Hochpass Label Name Data Type ID Daten Typ ID Digital Minimum Digitales Minimum Digital Maximum Digitales Maximum Physical Minimum Physikalisches Minimum Physical Maximum Physikalisches Maximum Physical Dimension Physikalische Einheit Sample Rate Abtast Rate Events Ereignisse Number Nummer Patient Patient Hospital ID Krankenhaus ID Doctor ID Arzt ID Classification Klassifikation Medication Medikation Handedness Handedness Sex Geschlecht male männlich female weiblich Age Alter years Jahre Name Name File Datei Size Größe kByte kByte Extension Erweiterung Path Pfad Basic Basis Recording Duration Aufnahme Dauer seconds Sekunden Triggered Trigger Recording Time Aufnahme Zeit Version Version Type Typ BioSig_::ChannelSelectionDialog Channel Selection Kanal Auswahl OK OK Cancel Abbrechen BioSig_::GUISignalBuffer Initialize Buffer Initialisiere Puffer Downsampling Progress Fortschritt Downsampling Range Finding Progress Fortschritt Finde Bereich Loading Events Progress Fortschritt Laden der Ereignisse BioSig_::GoToDialog Go To Gehe Zu None Kein Second Sekunde Channel Kanal OK OK Cancel Abbrechen BioSig_::LogDialog Log Log Close Schließen BioSig_::MainWindow &File &Datei &Mouse Mode &Maus Modus &View &Ansicht &Options &Optionen &Help &Hilfe Recent Files Zuletzt geöffnete Dateien whole alles Open Öffnen &Open... Ö&ffnen... Ctrl+O Ctrl+F Close Schließen Info Info Info... Info... Exit Beenden E&xit &Beenden Pointer Zeiger Hand Hand Shift Signal Verschiebe Signal Zoom Zoom Zoom In Vergrößern Zoom Out Verkleinern Auto Scale Auto Skalierung Go To Gehe Zu &Go To... &Gehe Zu... Ctrl+G Ctrl+G Channels Kanäle &Channels... &Kanäle... Log Log Log... Log... About SigViewer Über SigViewer About SigViewer... Über SigViewer... Really close? Wirklich schließen? Changes in '%1' are not saved!! Änderungen wurden nicht gesichert!! Signal files (%1) Signal Dateien (%1) Chose signal file to open Öffne Signal Datei SigViewer Version 0.01 SigViewer Version 0.01 Seconds per Page Sekunden pro Seite Signals per Page Signale pro Seite sigviewer-0.6.4/src/translations/sigviewer_en.ts000066400000000000000000000277131345753661000221170ustar00rootroot00000000000000 BioSig_::BasicHeaderInfoDialog Basic Header Info Close Property Value Unit Channels Filter Notch yes no Lowpass Hz Highpass Label Data Type ID Digital Minimum Digital Maximum Physical Minimum Physical Maximum Physical Dimension Sample Rate Events Number Patient Hospital ID Doctor ID Classification Medication Handedness Sex male female Age years Name File Size kByte Extension Path Basic Recording Duration seconds Triggered Recording Time Version Type BioSig_::ChannelSelectionDialog Channel Selection OK Cancel BioSig_::GUISignalBuffer Initialize Buffer Downsampling Progress Range Finding Progress Loading Events Progress BioSig_::GoToDialog Go To None Second Channel OK Cancel BioSig_::LogDialog Log Close BioSig_::MainWindow &File &Mouse Mode &View &Options &Help Recent Files whole Open &Open... Ctrl+O Close Info Info... Exit E&xit Pointer Hand Shift Signal Zoom Zoom In Zoom Out Auto Scale Go To &Go To... Ctrl+G Channels &Channels... Log Log... About SigViewer About SigViewer... Really close? Changes in '%1' are not saved!! Signal files (%1) Chose signal file to open SigViewer Version 0.01 Seconds per Page Signals per Page