pax_global_header00006660000000000000000000000064137720456210014521gustar00rootroot0000000000000052 comment=c327b516b06f66466d52fd3648b6bc5cd996e526 PyQt-Qwt-1.02.02/000077500000000000000000000000001377204562100133315ustar00rootroot00000000000000PyQt-Qwt-1.02.02/06_python_compat.patch000066400000000000000000000030631377204562100175450ustar00rootroot00000000000000#Patch to simplify python interface --- a/src/qwt_series_data.h +++ b/src/qwt_series_data.h @@ -54,14 +54,14 @@ virtual ~QwtSeriesData(); //! \return Number of samples - virtual size_t size() const = 0; + virtual size_t size() const {return 0;}; /*! Return a sample \param i Index \return Sample at position i */ - virtual T sample( size_t i ) const = 0; + virtual T sample( size_t i ) const {return T();}; /*! Calculate the bounding rect of all samples @@ -75,7 +75,7 @@ \return Bounding rectangle */ - virtual QRectF boundingRect() const = 0; + virtual QRectF boundingRect() const {return d_boundingRect;}; /*! Set a the "rect of interest" --- a/src/qwt_series_store.h +++ b/src/qwt_series_store.h @@ -28,19 +28,19 @@ virtual ~QwtAbstractSeriesStore() {} //! dataChanged() indicates, that the series has been changed. - virtual void dataChanged() = 0; + virtual void dataChanged() {}; /*! Set a the "rectangle of interest" for the stored series \sa QwtSeriesData::setRectOfInterest() */ - virtual void setRectOfInterest( const QRectF & ) = 0; + virtual void setRectOfInterest( const QRectF & ) {}; //! \return Bounding rectangle of the stored series - virtual QRectF dataRect() const = 0; + virtual QRectF dataRect() const {return QRectF( 0.0, 0.0, -1.0, -1.0 );}; //! \return Number of samples - virtual size_t dataSize() const = 0; + virtual size_t dataSize() const {return 0;}; }; /*! PyQt-Qwt-1.02.02/LICENSE000066400000000000000000000664521377204562100143530ustar00rootroot00000000000000 Qwt License Version 1.0, January 1, 2003 The Qwt library and included programs are provided under the terms of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL) with the following exceptions: 1. Widgets that are subclassed from Qwt widgets do not constitute a derivative work. 2. Static linking of applications and widgets to the Qwt library does not constitute a derivative work and does not require the author to provide source code for the application or widget, use the shared Qwt libraries, or link their applications or widgets against a user-supplied version of Qwt. If you link the application or widget to a modified version of Qwt, then the changes to Qwt must be provided under the terms of the LGPL in sections 1, 2, and 4. 3. You do not have to provide a copy of the Qwt license with programs that are linked to the Qwt library, nor do you have to identify the Qwt license in your program or documentation as required by section 6 of the LGPL. However, programs must still identify their use of Qwt. The following example statement can be included in user documentation to satisfy this requirement: [program/widget] is based in part on the work of the Qwt project (http://qwt.sf.net). ---------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! PyQt-Qwt-1.02.02/README.md000066400000000000000000000073451377204562100146210ustar00rootroot00000000000000# PyQt-Qwt Python PyQt wrapper for Qwt6 The code is tested for python2/3 and Qt4/5. oscilloscope.py is unfinished. animation.py works only for qt5. All the other examples have been tested to work on Debian Linux. The qwt include files must be patched to build PyQt-Qwt. The code is not tested properly for Qt4. ## BUILD: ### ******* IMPORTANT ********* The PyQt-Qwt doesn't build against unpatched Qwt version 6.1.3. The header files need to be patched with 06_python_compat.patch but for convenience the patched files are kept in the header directory. For Qwt version < 6.1.4 the following is needed before compiling: $ cp -a /usr/include/qwt header $ cp header/qwt*.h header/qwt/ ### Linux: Dependencies in Debian: There is a PyQt-Qwt package for Debian/Ubuntu systems but the instructions should work for any other Linux distro. $ sudo apt-get install pyqt5-dev pyqt5-dev-tools python3-pyqt5 libqwt-qt5-dev libqwt-headers A proper configure.py file has been added. To use it on Debian which supports coexisting Qt libraries (4 and 5) you need to add QT_SELECT ahead of the command line. All systems are not exactly equal. python may refer to python3 on some systems. On Debian systems the Qt5 version of Qwt is named libqwt-qt5.so but the default name is libqwt.so. Remove the --qwt-lib=qwt-qt5 if the name extension is not used on your system. $ sip-build --qwt-incdir=/usr/include/qwt --qwt-libdir=/usr/lib --qwt-lib=qwt-qt5 $ QT_SELECT=qt5 python3 configure.py --qwt-incdir=header/qwt --qwt-libdir=/usr/lib --qwt-lib=qwt-qt5 $ QT_SELECT=qt4 python3 configure.py --qwt-incdir=header/qwt --qwt-libdir=/usr/lib --pyqt=PyQt4 $ make $ sudo make install $ cd qt5examples $ python3 bode.py $ for name in *.py; do python3 $name; done ## Windows: Tested for MSVC2017 and python 3.9 Assuming the default installation directory, c:\qwt-6.1.5 Compile Qwt with the following parts in qwtconfig.pri commented out: \#QWT_CONFIG += QwtDll \#QWT_CONFIG += QwtSvg \#QWT_CONFIG += QwtOpenGL \#QWT_CONFIG += QwtMathML Open "Qt 5.14.2 64-bit for Desktop (MSVC2017)" command prompt run "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" Install Python prerequisites: pip install numpy pip install pyqt-builder pip install pyqt5 pip install sip sip-install --qwt-incdir=c:\qwt-6.1.5\include --qwt-libdir=c:\qwt-6.1.5\lib --qwt-lib=qwt --verbose ### Debugging It took me a lot of time to find out how to debug with gdb, and there is a bug/(feature) in gcc that makes the procedure more problematic. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61918 I am using gcc 8.1.0 $ QT_SELECT=qt5 python3-dbg configure.py --qwt-incdir=header/qwt --qwt-libdir=/usr/lib --qwt-lib=qwt-qt5 --trace --debug Then do the following in Qwt/Makefile Replace "-isystem" with "-I" Remove "$(shell dpkg-buildflags --get CFLAGS) -D_FORTIFY_SOURCE=2". The line looks very Debianish, don't know if it exists on other systems. Will check. Then do: $ make; sudo make install Then debug with $ gdb --args python3-dbg $ run barchart.py ### Usage The pyuic5 doesn't fully work with PyQt-Qwt. After creating the python file. pyuic5 uifile.ui -o ui_uifile.py you need to edit the file afterwards. Add from PyQt5.Qwt import * at the top of the file. Then remove all lines with import qwt_ from the bottom of the file. The following command will do this automatically pyuic5 uifile.ui |grep -v "from qwt_" | sed 's/# WARNING! All changes made in this file will be lost!/from PyQt5.Qwt import */g' > ui_uifile.py but it needs sed and grep to be installed on your computer. ### Status 2020-12-27 * Compiles with sip >= 4.18. * Compiles with Qwt >= 6.1.2. Tested for version 6.1.2 -- 6.1.5 * All examples except for oscilloscope.py do work. PyQt-Qwt-1.02.02/changelog000066400000000000000000000021321377204562100152010ustar00rootroot00000000000000Change Log ---------- Version 1.01.00 - Bug fixes in examples - Add examples controls.py and curvdemo1.py - Add sip files: qwt_plot_renderer.sip, qwt_transform.sip, qwt_slider.sip - Correct Transfer/TransferThis annotations. There may still be errors but I have not seen any crashes. - Add more functions that were earlier commented out: qwt_scale_engine.sip: void setTransformation( QwtTransform * ); QwtTransform *transformation() const; qwt_slider.sip: const QwtScaleDraw *scaleDraw() const; qwt_plot.sip: explicit QwtPlot( const QwtText &title, QWidget * = NULL ); - Add QT += printsupport. - Known bug: printing from spectrogram.py freezes in Linux. Version 1.02.00 - Fix compilation for Sip >= 4.18 and Qwt >= 6.1.2 Tested for Qwt 6.1.2, 6.1.3 and 6.1.4 - Add Analog Clock widget - Add Compass widget - Add Dial wigets - Add setSamples(QPolygon). Improves framerate. Thanks to Olivier. - A few bug fixes - A few more examples Version 1.02.01 - Fix compilation with sip5 - Minor bugfixes in examples Version 1.02.02 - sip-tool compilation added. Thanks to Dmitry Shachnev. PyQt-Qwt-1.02.02/clean.sh000077500000000000000000000002401377204562100147460ustar00rootroot00000000000000#!/bin/bash rm -f sip*.cpp rm -f *.o rm -f Makefile rm -f Qwt.exp rm -f Qwt.so rm -f qwt.sbf rm -f Qwt.pyi Qwt.pro Qwt.api sipAPIQwt.h .qmake.stash rm -rf Qwt PyQt-Qwt-1.02.02/configure-old.py000077500000000000000000002050051377204562100164450ustar00rootroot00000000000000# Copyright (c) 2017, Riverbank Computing Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This is v2.3 of this boilerplate. from distutils import sysconfig import glob import os import optparse import sys ############################################################################### # You shouldn't need to modify anything above this line. ############################################################################### # This must be kept in sync with Python/configure-old.py, qwt.pro, # example-Qt4Qt5/application.pro and designer-Qt4Qt5/designer.pro. QWT_API_MAJOR = 6 class ModuleConfiguration(object): """ This class encapsulates all the module specific information needed by the rest of this script to implement a configure.py script for modules that build on top of PyQt. Functions implemented by the rest of this script that begin with an underscore are considered internal and shouldn't be called from here. """ # The name of the module as it would be used in an import statement. name = 'Qwt' # The descriptive name of the module. This is used in help text and error # messages. descriptive_name = "Qwt" # The version of the module as a string. Set it to None if you don't # provide version information. version = "1.02.02" # The name of the PEP 376 .dist-info directory to be created. distinfo_name = 'Qwt' # Set if a configuration script is provided that handles versions of PyQt4 # prior to v4.10 (i.e. versions where the pyqtconfig.py module is # available). If provided the script must be called configure-old.py and # be in the same directory as this script. legacy_configuration_script = False # The minimum version of SIP that is required. This should be a # dot-separated string of two or three integers (e.g. '1.0', '4.10.3'). If # it is None or an empty string then the version is not checked. minimum_sip_version = '4.18' # Set if support for C++ exceptions can be disabled. no_exceptions = True # The name (without the .pyi extension) of the name of the PEP 484 stub # file to be generated. If it is None or an empty string then a stub file # is not generated. pep484_stub_file = 'Qwt' # Set if the module supports redefining 'protected' as 'public'. protected_is_public_is_supported = True # Set if the module supports PyQt4. pyqt4_is_supported = True # Set if the module supports PyQt5. pyqt5_is_supported = True # Set if the PyQt5 support is the default. It is ignored unless both # 'pyqt4_is_supported' and 'pyqt5_is_supported' are set. pyqt5_is_default = True # The name (without the .api extension) of the name of the Qwt API # file to be generated. If it is None or an empty string then an API file # is not generated. qwt_api_file = 'Qwt' # The email address that will be included when an error in the script is # detected. Leave it blank if you don't want to include an address. support_email_address = 'gudjon@gudjon.org' # Set if the user can provide a configuration file. It is normally only # used if cross-compilation is supported. user_configuration_file_is_supported = True # Set if the user is allowed to pass PyQt sip flags on the command line. # It is normally only used if cross-compilation is supported. It is # ignored unless at least one of 'pyqt4_is_supported' or # 'pyqt5_is_supported' is set. user_pyqt_sip_flags_is_supported = True @staticmethod def init_target_configuration(target_configuration): """ Perform any module specific initialisation of the target target configuration. Typically this is the initialisation of module specific attributes. To avoid name clashes attributes should be given a module specific prefix. target_configuration is the target configuration. """ target_configuration.qwt_version = None target_configuration.qwt_features_dir = None target_configuration.qwt_inc_dir = None target_configuration.qwt_lib_dir = None target_configuration.qwt_lib = None target_configuration.qwt_sip_dir = None @staticmethod def init_optparser(optparser, target_configuration): """ Perform any module specific initialisation of the command line option parser. To avoid name clashes destination attributes should be given a module specific prefix. optparser is the option parser. target_configuration is the target configuration. """ optparser.add_option('--qwt-incdir', '-n', dest='qwt_inc_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the Qwt header " "file directory is DIR [default: QT_INSTALL_HEADERS]") optparser.add_option('--qwt-featuresdir', dest='qwt_features_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the qwt.prf features " "file is DIR [default: " "QT_INSTALL_PREFIX/mkspecs/features]") optparser.add_option('--qwt-libdir', '-o', dest='qwt_lib_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the Qwt library is DIR " "[default: QT_INSTALL_LIBS]") optparser.add_option('--qwt-lib', '-l', dest='qwt_lib', type='string', default=None, help="the Qwt library " "[default: qwt]") optparser.add_option('--qwt-sipdir', '-v', dest='qwt_sip_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the Qwt .sip files will be installed in DIR " "[default: %s]" % target_configuration.pyqt_sip_dir) optparser.add_option("--no-sip-files", action="store_true", default=False, dest="qwt_no_sip_files", help="disable the installation of the .sip files " "[default: enabled]") @staticmethod def apply_options(target_configuration, options): """ Apply the module specific command line options to the target configuration. target_configuration is the target configuration. options are the parsed options. """ if options.qwt_features_dir is not None: target_configuration.qwt_features_dir = options.qwt_features_dir if options.qwt_inc_dir is not None: target_configuration.qwt_inc_dir = options.qwt_inc_dir if options.qwt_lib_dir is not None: target_configuration.qwt_lib_dir = options.qwt_lib_dir if options.qwt_lib is not None: target_configuration.qwt_lib = options.qwt_lib if options.qwt_sip_dir is not None: target_configuration.qwt_sip_dir = options.qwt_sip_dir else: target_configuration.qwt_sip_dir = target_configuration.pyqt_sip_dir if options.qwt_no_sip_files: target_configuration.qwt_sip_dir = '' @staticmethod def check_module(target_configuration): """ Perform any module specific checks now that the target configuration is complete. target_configuration is the target configuration. """ # Find the Qwt header files. inc_dir = target_configuration.qwt_inc_dir if inc_dir is None: inc_dir = target_configuration.qt_inc_dir qwtglobal = os.path.join(inc_dir, '', 'qwt_global.h') print(inc_dir) if not os.access(qwtglobal, os.F_OK): error( "qwt/qwt_global.h could not be found in %s. If " "Qwt is installed then use the --qwt-incdir " "argument to explicitly specify the correct " "directory." % inc_dir) # Get the Qwt version string. qwt_version = read_define(qwtglobal, 'QWT_VERSION_STR') if qwt_version is None: error( "The Qwt version number could not be determined by " "reading %s." % qwtglobal) lib_dir = target_configuration.qwt_lib_dir if lib_dir is None: lib_dir = target_configuration.qt_lib_dir if not glob.glob(os.path.join(lib_dir, '*qwt*')): error( "The Qwt library could not be found in %s. If " "Qwt is installed then use the --qwt-libdir " "argument to explicitly specify the correct " "directory." % lib_dir) # Because we include the Python bindings with the C++ code we can # reasonably force the same version to be used and not bother about # versioning in the .sip files. qv=qwt_version.split('.') qwt_version_numeric = int(qv[0])*10000 + int(qv[1])*100 + int(qv[2]) mv=ModuleConfiguration.version.split('.') mod_version_numeric = int(mv[0])*10000 + int(mv[1])*100 + int(mv[2]) if qwt_version_numeric < mod_version_numeric: error( "Qwt %s is being used but the Python bindings %s " "are being built. Please use a newer Qwt " "version." % (qwt_version, ModuleConfiguration.version)) target_configuration.qwt_version = qwt_version @staticmethod def inform_user(target_configuration): """ Inform the user about module specific configuration information. target_configuration is the target configuration. """ inform("Qwt %s is being used." % target_configuration.qwt_version) if target_configuration.qwt_sip_dir != '': inform("The Qwt .sip files will be installed in %s." % target_configuration.qwt_sip_dir) @staticmethod def pre_code_generation(target_config): """ Perform any module specific initialisation prior to generating the code. target_config is the target configuration. """ # Nothing to do. @staticmethod def get_sip_flags(target_configuration): """ Return the list of module-specific flags to pass to SIP. target_configuration is the target configuration. """ # Nothing to do. return [] @staticmethod def get_sip_file(target_configuration): """ Return the name of the module's .sip file. target_configuration is the target configuration. """ return 'sip/qwt.sip' #if target_configuration.pyqt_package == 'PyQt5': # return os.path.join(src_dir, 'sip/qwt.sip') #else: # return os.path.join(src_dir, 'sip/qwtmod4.sip') #return 'sip/qwtmod5.sip' if target_configuration.pyqt_package == 'PyQt5' else 'sip/qwtmod4.sip' @staticmethod def get_sip_installs(target_configuration): """ Return a tuple of the installation directory of the module's .sip files and a sequence of the names of each of the .sip files relative to the directory containing this configuration script. None is returned if the module's .sip files are not to be installed. target_configuration is the target configuration. """ if target_configuration.qwt_sip_dir == '': return None path = os.path.join(target_configuration.qwt_sip_dir, 'Qwt') files = glob.glob('sip/*.sip') return path, files @staticmethod def get_qmake_configuration(target_configuration): """ Return a dict of qmake configuration values for CONFIG, DEFINES, INCLUDEPATH, LIBS and QT. If value names (i.e. dict keys) have either 'Qt4' or 'Qt5' prefixes then they are specific to the corresponding version of Qt. target_configuration is the target configuration. """ qmake = {'CONFIG': 'qwt'} if target_configuration.qwt_inc_dir is not None: qmake['INCLUDEPATH'] = quote(target_configuration.qwt_inc_dir) if target_configuration.qwt_lib_dir is not None: qmake['LIBS'] = '-L%s' % quote(target_configuration.qwt_lib_dir) if target_configuration.qwt_features_dir is not None: os.environ['QMAKEFEATURES'] = target_configuration.qwt_features_dir return qmake @staticmethod def get_mac_wrapped_library_file(target_configuration): """ Return the full pathname of the file that implements the library being wrapped by the module as it would be called on OS/X so that the module will reference it explicitly without DYLD_LIBRARY_PATH being set. If it is None or an empty string then the default is used. target_configuration is the target configuration. """ lib_dir = target_configuration.qwt_lib_dir if lib_dir is None: lib_dir = target_configuration.qt_lib_dir debug = '_debug' if target_configuration.debug else '' return os.path.join(lib_dir, 'libqwt%s.%s.dylib' % (debug, QWT_API_MAJOR)) ############################################################################### # You shouldn't need to modify anything below this line. ############################################################################### def error(msg): """ Display an error message and terminate. msg is the text of the error message. """ sys.stderr.write(_format("Error: " + msg) + "\n") sys.exit(1) def inform(msg): """ Display an information message. msg is the text of the error message. """ sys.stdout.write(_format(msg) + "\n") def quote(path): """ Return a path with quotes added if it contains spaces. path is the path. """ if ' ' in path: path = '"%s"' % path return path def optparser_store_abspath(option, opt_str, value, parser): """ An optparser callback that saves an option as an absolute pathname. """ setattr(parser.values, option.dest, os.path.abspath(value)) def optparser_store_abspath_dir(option, opt_str, value, parser): """ An optparser callback that saves an option as the absolute pathname of an existing directory. """ if not os.path.isdir(value): raise optparse.OptionValueError("'%s' is not a directory" % value) setattr(parser.values, option.dest, os.path.abspath(value)) def optparser_store_abspath_exe(option, opt_str, value, parser): """ An optparser callback that saves an option as the absolute pathname of an existing executable. """ if not os.access(value, os.X_OK): raise optparse.OptionValueError("'%s' is not an executable" % value) setattr(parser.values, option.dest, os.path.abspath(value)) def read_define(filename, define): """ Read the value of a #define from a file. filename is the name of the file. define is the name of the #define. None is returned if there was no such #define. """ f = open(filename) for l in f: wl = l.split() if len(wl) >= 3 and wl[0] == "#define" and wl[1] == define: # Take account of embedded spaces. value = ' '.join(wl[2:])[1:-1] break else: value = None f.close() return value def version_from_string(version_str): """ Convert a version string of the form m, m.n or m.n.o to an encoded version number (or None if it was an invalid format). version_str is the version string. """ parts = version_str.split('.') if not isinstance(parts, list): return None if len(parts) == 1: parts.append('0') if len(parts) == 2: parts.append('0') if len(parts) != 3: return None version = 0 for part in parts: try: v = int(part) except ValueError: return None version = (version << 8) + v return version def _format(msg, left_margin=0, right_margin=78): """ Format a message by inserting line breaks at appropriate places. msg is the text of the message. left_margin is the position of the left margin. right_margin is the position of the right margin. Returns the formatted message. """ curs = left_margin fmsg = " " * left_margin for w in msg.split(): l = len(w) if curs != left_margin and curs + l > right_margin: fmsg = fmsg + "\n" + (" " * left_margin) curs = left_margin if curs > left_margin: fmsg = fmsg + " " curs = curs + 1 fmsg = fmsg + w curs = curs + l return fmsg class _ConfigurationFileParser: """ A parser for configuration files. """ def __init__(self, config_file): """ Read and parse a configuration file. """ self._config = {} self._extrapolating = [] cfg = open(config_file) line_nr = 0 last_name = None section = '' section_config = {} self._config[section] = section_config for l in cfg: line_nr += 1 # Strip comments. l = l.split('#')[0] # See if this might be part of a multi-line. multiline = (last_name is not None and len(l) != 0 and l[0] == ' ') l = l.strip() if l == '': last_name = None continue # See if this is a new section. if l[0] == '[' and l[-1] == ']': section = l[1:-1].strip() if section == '': error( "%s:%d: Empty section name." % ( config_file, line_nr)) if section in self._config: error( "%s:%d: Section '%s' defined more than once." % ( config_file, line_nr, section)) section_config = {} self._config[section] = section_config last_name = None continue parts = l.split('=', 1) if len(parts) == 2: name = parts[0].strip() value = parts[1].strip() elif multiline: name = last_name value = section_config[last_name] value += ' ' + l else: name = value = '' if name == '' or value == '': error("%s:%d: Invalid line." % (config_file, line_nr)) section_config[name] = value last_name = name cfg.close() def sections(self): """ Return the list of sections, excluding the default one. """ return [s for s in self._config.keys() if s != ''] def preset(self, name, value): """ Add a preset value to the configuration. """ self._config[''][name] = value def get(self, section, name, default=None): """ Get a configuration value while extrapolating. """ # Get the name from the section, or the default section. value = self._config[section].get(name) if value is None: value = self._config[''].get(name) if value is None: if default is None: error( "Configuration file references non-existent name " "'%s'." % name) return default # Handle any extrapolations. parts = value.split('%(', 1) while len(parts) == 2: prefix, tail = parts parts = tail.split(')', 1) if len(parts) != 2: error( "Configuration file contains unterminated " "extrapolated name '%s'." % tail) xtra_name, suffix = parts if xtra_name in self._extrapolating: error( "Configuration file contains a recursive reference to " "'%s'." % xtra_name) self._extrapolating.append(xtra_name) xtra_value = self.get(section, xtra_name) self._extrapolating.pop() value = prefix + xtra_value + suffix parts = value.split('%(', 1) return value def getboolean(self, section, name, default): """ Get a boolean configuration value while extrapolating. """ value = self.get(section, name, default) # In case the default was returned. if isinstance(value, bool): return value if value in ('True', 'true', '1'): return True if value in ('False', 'false', '0'): return False error( "Configuration file contains invalid boolean value for " "'%s'." % name) def getlist(self, section, name, default): """ Get a list configuration value while extrapolating. """ value = self.get(section, name, default) # In case the default was returned. if isinstance(value, list): return value return value.split() class _HostPythonConfiguration: """ A container for the host Python configuration. """ def __init__(self): """ Initialise the configuration. """ self.platform = sys.platform self.version = sys.hexversion >> 8 self.inc_dir = sysconfig.get_python_inc() self.venv_inc_dir = sysconfig.get_python_inc(prefix=sys.prefix) self.module_dir = sysconfig.get_python_lib(plat_specific=1) self.debug = hasattr(sys, 'gettotalrefcount') if sys.platform == 'win32': try: # Python v3.3 and later. base_prefix = sys.base_prefix except AttributeError: try: # virtualenv for Python v2. base_prefix = sys.real_prefix except AttributeError: # We can't detect the base prefix in Python v3 prior to # v3.3. base_prefix = sys.prefix self.data_dir = sys.prefix self.lib_dir = base_prefix + '\\libs' else: self.data_dir = sys.prefix + '/share' self.lib_dir = sys.prefix + '/lib' class _TargetQtConfiguration: """ A container for the target Qt configuration. """ def __init__(self, qmake): """ Initialise the configuration. qmake is the full pathname of the qmake executable that will provide the configuration. """ pipe = os.popen(quote(qmake) + ' -query') for l in pipe: l = l.strip() tokens = l.split(':', 1) if isinstance(tokens, list): if len(tokens) != 2: error("Unexpected output from qmake: '%s'\n" % l) name, value = tokens else: name = tokens value = None name = name.replace('/', '_') setattr(self, name, value) pipe.close() class _TargetConfiguration: """ A container for the target configuration. """ def __init__(self, pkg_config): """ Initialise the configuration with default values. pkg_config is the package configuration. """ # Values based on the host Python configuration. py_config = _HostPythonConfiguration() self.py_debug = py_config.debug self.py_platform = py_config.platform self.py_version = py_config.version self.py_module_dir = py_config.module_dir self.py_inc_dir = py_config.inc_dir self.py_venv_inc_dir = py_config.venv_inc_dir self.py_pylib_dir = py_config.lib_dir self.py_sip_dir = os.path.join(py_config.data_dir, 'sip') self.sip_inc_dir = py_config.venv_inc_dir # Remaining values. self.debug = False self.pyqt_sip_flags = None self.pyqt_version_str = '' self.qmake = self._find_exe('qmake') self.qmake_spec = '' self.qt_version = 0 self.qt_version_str = '' self.sip = self._find_exe('sip5', 'sip') self.sip_version = None self.sip_version_str = None self.sysroot = '' self.stubs_dir = '' self.distinfo = False self.prot_is_public = (self.py_platform.startswith('linux') or self.py_platform == 'darwin') if pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: pyqt = 'PyQt5' if pkg_config.pyqt5_is_default else 'PyQt4' elif pkg_config.pyqt5_is_supported and not pkg_config.pyqt4_is_supported: pyqt = 'PyQt5' elif not pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: pyqt = 'PyQt4' else: pyqt = None if pyqt is not None: self.module_dir = os.path.join(py_config.module_dir, pyqt) self.pyqt_sip_dir = os.path.join(self.py_sip_dir, pyqt) else: self.module_dir = py_config.module_dir self.pyqt_sip_dir = None self.pyqt_package = pyqt pkg_config.init_target_configuration(self) def update_from_configuration_file(self, config_file): """ Update the configuration with values from a file. config_file is the name of the configuration file. """ inform("Reading configuration from %s..." % config_file) parser = _ConfigurationFileParser(config_file) # Populate some presets from the command line. parser.preset('py_major', str(self.py_version >> 16)) parser.preset('py_minor', str((self.py_version >> 8) & 0xff)) parser.preset('sysroot', self.sysroot) if self.pyqt_package is None: section = '' else: # At the moment we only need to distinguish between PyQt4 and # PyQt5. If that changes we may need a --target-pyqt-version # command line option. pyqt_version = 0x050000 if self.pyqt_package == 'PyQt5' else 0x040000 # Find the section corresponding to the version of PyQt. section = None latest_section = -1 for name in parser.sections(): parts = name.split() if len(parts) != 2 or parts[0] != 'PyQt': continue section_pyqt_version = version_from_string(parts[1]) if section_pyqt_version is None: continue # Major versions must match. if section_pyqt_version >> 16 != pyqt_version >> 16: continue # It must be no later that the version of PyQt. if section_pyqt_version > pyqt_version: continue # Save it if it is the latest so far. if section_pyqt_version > latest_section: section = name latest_section = section_pyqt_version if section is None: error( "%s does not define a section that covers PyQt " "v%s." % (config_file, self.pyqt_version_str)) self.py_platform = parser.get(section, 'py_platform', self.py_platform) self.py_inc_dir = parser.get(section, 'py_inc_dir', self.py_inc_dir) self.py_venv_inc_dir = self.py_inc_dir self.py_pylib_dir = parser.get(section, 'py_pylib_dir', self.py_pylib_dir) self.sip_inc_dir = self.py_venv_inc_dir self.module_dir = parser.get(section, 'module_dir', self.module_dir) if self.pyqt_package is not None: self.py_sip_dir = parser.get(section, 'py_sip_dir', self.py_sip_dir) # Construct the SIP flags. flags = [] flags.append('-t') flags.append(self._get_platform_tag()) if self.pyqt_package == 'PyQt5': if self.qt_version < 0x050000: error("PyQt5 requires Qt v5.0 or later.") if self.qt_version > 0x060000: self.qt_version = 0x060000 else: if self.qt_version > 0x050000: self.qt_version = 0x050000 major = (self.qt_version >> 16) & 0xff minor = (self.qt_version >> 8) & 0xff patch = self.qt_version & 0xff flags.append('-t') flags.append('Qt_%d_%d_%d' % (major, minor, patch)) for feat in parser.getlist(section, 'pyqt_disabled_features', []): flags.append('-x') flags.append(feat) self.pyqt_sip_flags = ' '.join(flags) def _get_platform_tag(self): """ Return the tag for the target platform. """ # This replicates the logic in PyQt's configure scripts. if self.py_platform == 'win32': plattag = 'WS_WIN' elif self.py_platform == 'darwin': plattag = 'WS_MACX' else: plattag = 'WS_X11' return plattag def introspect_pyqt(self, pkg_config): """ Introspect PyQt to determine the sip flags required. pkg_config is the package configuration. """ if self.pyqt_package == 'PyQt5': try: from PyQt5 import QtCore except ImportError: error( "Unable to import PyQt5.QtCore. Make sure PyQt5 is " "installed.") else: try: from PyQt4 import QtCore except ImportError: error( "Unable to import PyQt4.QtCore. Make sure PyQt4 is " "installed.") self.pyqt_version_str = QtCore.PYQT_VERSION_STR self.qt_version_str = QtCore.qVersion() # See if we have a PyQt that embeds its configuration. try: pyqt_config = QtCore.PYQT_CONFIGURATION except AttributeError: pyqt_config = None if pyqt_config is None: if pkg_config.legacy_configuration_script: # Fallback to the old configuration script. config_script = sys.argv[0].replace('configure', 'configure-old') args = [sys.executable, config_script] + sys.argv[1:] try: os.execv(sys.executable, args) except OSError: pass error("Unable to execute '%s'" % config_script) error("PyQt v4.10 or later is required.") self.pyqt_sip_flags = pyqt_config['sip_flags'] def apply_sysroot(self): """ Apply sysroot where necessary. """ if self.sysroot != '': self.py_inc_dir = self._apply_sysroot(self.py_inc_dir) self.py_venv_inc_dir = self._apply_sysroot(self.py_venv_inc_dir) self.py_pylib_dir = self._apply_sysroot(self.py_pylib_dir) self.py_sip_dir = self._apply_sysroot(self.py_sip_dir) self.module_dir = self._apply_sysroot(self.module_dir) self.sip_inc_dir = self._apply_sysroot(self.sip_inc_dir) def _apply_sysroot(self, dir_name): """ Replace any leading sys.prefix of a directory name with sysroot. """ if dir_name.startswith(sys.prefix): dir_name = self.sysroot + dir_name[len(sys.prefix):] return dir_name def get_qt_configuration(self, opts): """ Get the Qt configuration that can be extracted from qmake. opts are the command line options. """ # Query qmake. qt_config = _TargetQtConfiguration(self.qmake) self.qt_version_str = getattr(qt_config, 'QT_VERSION', '') self.qt_version = version_from_string(self.qt_version_str) if self.qt_version is None: error("Unable to determine the version of Qt.") # On Windows for Qt versions prior to v5.9.0 we need to be explicit # about the qmake spec. if self.qt_version < 0x050900 and self.py_platform == 'win32': if self.py_version >= 0x030500: self.qmake_spec = 'win32-msvc2015' elif self.py_version >= 0x030300: self.qmake_spec = 'win32-msvc2010' elif self.py_version >= 0x020600: self.qmake_spec = 'win32-msvc2008' elif self.py_version >= 0x020400: self.qmake_spec = 'win32-msvc.net' else: self.qmake_spec = 'win32-msvc' else: # Otherwise use the default. self.qmake_spec = '' # The binary MacOS/X Qt installer used to default to XCode. If so then # use macx-clang (Qt v5) or macx-g++ (Qt v4). if sys.platform == 'darwin': try: # Qt v5. if qt_config.QMAKE_SPEC == 'macx-xcode': # This will exist (and we can't check anyway). self.qmake_spec = 'macx-clang' else: # No need to explicitly name the default. self.qmake_spec = '' except AttributeError: # Qt v4. self.qmake_spec = 'macx-g++' self.api_dir = os.path.join(qt_config.QT_INSTALL_DATA, 'qwt') self.qt_inc_dir = qt_config.QT_INSTALL_HEADERS self.qt_lib_dir = qt_config.QT_INSTALL_LIBS if self.sysroot == '': self.sysroot = getattr(qt_config, 'QT_SYSROOT', '') def apply_pre_options(self, opts): """ Apply options from the command line that influence subsequent configuration. opts are the command line options. """ # On Windows the interpreter must be a debug build if a debug version # is to be built and vice versa. if sys.platform == 'win32': if opts.debug: if not self.py_debug: error( "A debug version of Python must be used when " "--debug is specified.") elif self.py_debug: error( "--debug must be specified when a debug version of " "Python is used.") self.debug = opts.debug # Get the system root. if opts.sysroot is not None: self.sysroot = opts.sysroot # Determine how to run qmake. if opts.qmake is not None: self.qmake = opts.qmake # On Windows add the directory that probably contains the Qt DLLs # to PATH. if sys.platform == 'win32': path = os.environ['PATH'] path = os.path.dirname(self.qmake) + ';' + path os.environ['PATH'] = path if self.qmake is None: error( "Use the --qmake argument to explicitly specify a working " "Qt qmake.") if opts.qmakespec is not None: self.qmake_spec = opts.qmakespec if self.pyqt_package is not None: try: self.pyqt_package = opts.pyqt_package except AttributeError: # Multiple PyQt versions are not supported. pass self.module_dir = os.path.join(self.py_module_dir, self.pyqt_package) def apply_post_options(self, opts, pkg_config): """ Apply options from the command line that override the previous configuration. opts are the command line options. pkg_config is the package configuration. """ if self.pyqt_package is not None: if pkg_config.user_pyqt_sip_flags_is_supported: if opts.pyqt_sip_flags is not None: self.pyqt_sip_flags = opts.pyqt_sip_flags if opts.pyqt_sip_dir is not None: self.pyqt_sip_dir = opts.pyqt_sip_dir else: self.pyqt_sip_dir = os.path.join(self.py_sip_dir, self.pyqt_package) if _has_stubs(pkg_config): if opts.stubsdir is not None: self.stubs_dir = opts.stubsdir if opts.no_stubs: self.stubs_dir = '' elif self.stubs_dir == '': self.stubs_dir = self.module_dir if pkg_config.qwt_api_file: if opts.apidir is not None: self.api_dir = opts.apidir if opts.no_qwt_api: self.api_dir = '' if opts.destdir is not None: self.module_dir = opts.destdir if pkg_config.protected_is_public_is_supported: if opts.prot_is_public is not None: self.prot_is_public = opts.prot_is_public else: self.prot_is_public = False if opts.sip_inc_dir is not None: self.sip_inc_dir = opts.sip_inc_dir if opts.sip is not None: self.sip = opts.sip if pkg_config.distinfo_name and opts.distinfo: self.distinfo = True pkg_config.apply_options(self, opts) @staticmethod def _find_exe(*exes): """ Find an executable, ie. the first on the path. """ path_dirs = os.environ.get('PATH', '').split(os.pathsep) for exe in exes: # Strip any surrounding quotes. if exe.startswith('"') and exe.endswith('"'): exe = exe[1:-1] if sys.platform == 'win32': exe = exe + '.exe' for d in path_dirs: exe_path = os.path.join(d, exe) if os.access(exe_path, os.X_OK): return exe_path return None def _create_optparser(target_config, pkg_config): """ Create the parser for the command line. target_config is the target configuration containing default values. pkg_config is the package configuration. """ pkg_name = pkg_config.descriptive_name p = optparse.OptionParser(usage="python %prog [options]", version=pkg_config.version) p.add_option('--spec', dest='qmakespec', default=None, action='store', metavar="SPEC", help="pass -spec SPEC to qmake") if pkg_config.distinfo_name: p.add_option("--no-dist-info", action="store_false", default=True, dest="distinfo", help="do not install the dist-info directory") if _has_stubs(pkg_config): p.add_option('--stubsdir', dest='stubsdir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="the PEP 484 stubs will be installed in DIR [default: " "with the module]") p.add_option('--no-stubs', dest='no_stubs', default=False, action='store_true', help="disable the installation of the PEP 484 stubs " "[default: enabled]") if pkg_config.qwt_api_file: p.add_option('--apidir', '-a', dest='apidir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="the Qwt API file will be installed in DIR " "[default: QT_INSTALL_DATA/qwt]") p.add_option('--no-qwt-api', dest='no_qwt_api', default=True, action='store_true', help="disable the installation of the Qwt API file " "[default: enabled]") if pkg_config.user_configuration_file_is_supported: p.add_option('--configuration', dest='config_file', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="FILE", help="FILE defines the target configuration") p.add_option('--destdir', '-d', dest='destdir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="install %s in DIR [default: %s]" % (pkg_name, target_config.module_dir)) if pkg_config.protected_is_public_is_supported: p.add_option('--protected-is-public', dest='prot_is_public', default=None, action='store_true', help="enable building with 'protected' redefined as 'public' " "[default: %s]" % target_config.prot_is_public) p.add_option('--protected-not-public', dest='prot_is_public', action='store_false', help="disable building with 'protected' redefined as 'public'") if target_config.pyqt_package is not None: pyqt = target_config.pyqt_package if pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: p.add_option('--pyqt', dest='pyqt_package', type='choice', choices=['PyQt4', 'PyQt5'], default=pyqt, action='store', metavar="PyQtn", help="configure for PyQt4 or PyQt5 [default: %s]" % pyqt) if pkg_config.user_pyqt_sip_flags_is_supported: p.add_option('--pyqt-sip-flags', dest='pyqt_sip_flags', default=None, action='store', metavar="FLAGS", help="the sip flags used to build PyQt [default: query PyQt]") p.add_option('--qmake', '-q', dest='qmake', type='string', default=None, action='callback', callback=optparser_store_abspath_exe, metavar="FILE", help="the pathname of qmake is FILE [default: %s]" % ( target_config.qmake or "search PATH")) p.add_option('--sip', dest='sip', type='string', default=None, action='callback', callback=optparser_store_abspath_exe, metavar="FILE", help="the pathname of sip is FILE [default: " "%s]" % (target_config.sip or "None")) p.add_option('--sip-incdir', dest='sip_inc_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the sip.h header file file is DIR " "[default: %s]" % target_config.sip_inc_dir) if target_config.pyqt_package is not None: p.add_option('--pyqt-sipdir', dest='pyqt_sip_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the PyQt .sip files is DIR " "[default: %s]" % target_config.pyqt_sip_dir) p.add_option('--concatenate', '-c', dest='concat', default=False, action='store_true', help="concatenate the C++ source files") p.add_option('--concatenate-split', '-j', dest='split', type='int', default=1, metavar="N", help="split the concatenated C++ source files into N pieces " "[default: 1]") p.add_option('--static', '-k', dest='static', default=False, action='store_true', help="build a static %s" % pkg_name) p.add_option("--sysroot", dest='sysroot', type='string', action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="DIR is the target system root directory") p.add_option('--no-docstrings', dest='no_docstrings', default=False, action='store_true', help="disable the generation of docstrings") p.add_option('--trace', '-r', dest='tracing', default=False, action='store_true', help="build %s with tracing enabled" % pkg_name) p.add_option('--debug', '-u', default=False, action='store_true', help="build %s with debugging symbols" % pkg_name) p.add_option('--verbose', '-w', dest='verbose', default=False, action='store_true', help="enable verbose output during configuration") pkg_config.init_optparser(p, target_config) return p def _has_stubs(pkg_config): """ See if a stub file for any of the modules will be generated. pkg_config is the package configuration. """ for module_config in pkg_config.modules: if module_config.pep484_stub_file: return True return False def _inform_user(target_config, pkg_config): """ Tell the user the values that are going to be used. target_config is the target configuration. pkg_config is the package configuration. """ pkg_name = pkg_config.descriptive_name inform("Configuring %s %s..." % (pkg_name, pkg_config.version)) pkg_config.inform_user(target_config) inform("%s will be installed in %s." % (pkg_name, target_config.module_dir)) if target_config.debug: inform("A debug version of %s will be built." % pkg_name) if target_config.py_debug: inform("A debug build of Python is being used.") if target_config.pyqt_version_str != '': inform("PyQt %s is being used." % target_config.pyqt_version_str) else: inform("%s is being used." % target_config.pyqt_package) if target_config.qt_version_str != '': inform("Qt %s is being used." % target_config.qt_version_str) if target_config.sysroot != '': inform("The system root directory is %s." % target_config.sysroot) inform("sip %s is being used." % target_config.sip_version_str) inform("The sip executable is %s." % target_config.sip) if target_config.prot_is_public: inform("%s is being built with 'protected' redefined as 'public'." % pkg_name) if target_config.stubs_dir != '': inform("The PEP 484 stubs will be installed in %s." % target_config.stubs_dir) if pkg_config.qwt_api_file and target_config.api_dir != '': inform("The Qwt API file will be installed in %s." % os.path.join(target_config.api_dir, 'api', 'python')) def _generate_code(target_config, opts, pkg_config, module_config, all_installs): """ Generate the code for the module. target_config is the target configuration. opts are the command line options. pkg_config is the package configuration. module_config is the module configuration. all_installs is a list that is updated with the files installed for this module. """ inform( "Generating the C++ source for the %s module..." % module_config.name) # Generate the code in a module-specific sub-directory. try: os.mkdir(module_config.name) except: pass # Build the SIP command line. argv = [quote(target_config.sip)] # Tell SIP if this is a debug build of Python (SIP v4.19.1 and later). if target_config.sip_version >= 0x041301 and target_config.py_debug: argv.append('-D') # Add the module-specific flags. argv.extend(pkg_config.get_sip_flags(target_config)) # -n arg new in sip 4.19.9 if target_config.sip_version >= version_from_string("4.19.9"): argv.append('-n sip') if target_config.pyqt_package is not None: # Get the flags used for the main PyQt module. argv.extend(target_config.pyqt_sip_flags.split()) # Add the backstop version. argv.append('-B') argv.append('Qt_6_0_0' if target_config.pyqt_package == 'PyQt5' else 'Qt_5_0_0') # Add PyQt's .sip files to the search path. argv.append('-I') argv.append(quote(target_config.pyqt_sip_dir)) if target_config.stubs_dir != '': # Generate the stub file. argv.append('-y') argv.append(quote(module_config.pep484_stub_file + '.pyi')) if pkg_config.qwt_api_file and target_config.api_dir != '': # Generate the API file. argv.append('-a') argv.append(quote(module_config.name + '.api')) if target_config.prot_is_public: argv.append('-P'); if not opts.no_docstrings: argv.append('-o'); if opts.concat: argv.append('-j') argv.append(str(opts.split)) if opts.tracing: argv.append('-r') argv.append('-c') argv.append(os.path.abspath(module_config.name)) # This assumes that, for multi-module packages, all modules's .sip files # will be rooted in a common root directory. sip_file = module_config.get_sip_file(target_config) head, tail = os.path.split(sip_file) while head: head, tail = os.path.split(head) if tail != sip_file: argv.append('-I') argv.append(quote(tail)) argv.append(sip_file) check_file = os.path.join(module_config.name, 'sipAPI%s.h' % module_config.name) _remove_file(check_file) _run_command(' '.join(argv), opts.verbose) if not os.access(check_file, os.F_OK): error("Unable to create the C++ code.") # Generate the .pro file. _generate_pro(target_config, opts, module_config, all_installs) def _get_qt_qmake_config(qmake_config, qt_version): """ Return a dict of qmake configuration values for a specific Qt version. """ qt_qmake_config = {} for name, value in qmake_config.items(): name_parts = name.split(':') if len(name_parts) == 2 and name_parts[0] == qt_version: qt_qmake_config[name_parts[1]] = value return qt_qmake_config def _write_qt_qmake_config(qt_qmake_config, pro): """ Write the qmake configuration values to a .pro file. """ for name in ('QT', 'CONFIG', 'DEFINES', 'INCLUDEPATH', 'LIBS'): value = qt_qmake_config.get(name) if value: pro.write(' %s += %s\n' % (name, value)) def _generate_pro(target_config, opts, module_config, all_installs): """ Generate the .pro file for the module. target_config is the target configuration. opts are the command line options. module_config is the module configuration. all_installs is a list that is updated with the files installed for this module. """ inform("Generating the .pro file for the %s module..." % module_config.name) # Without the 'no_check_exist' magic the target.files must exist when qmake # is run otherwise the install and uninstall targets are not generated. qmake_config = module_config.get_qmake_configuration(target_config) pro = open(os.path.join(module_config.name, module_config.name + '.pro'), 'w') pro.write('TEMPLATE = lib\n') qt = qmake_config.get('QT') if qt: pro.write('QT += %s\n' % qt) if target_config.pyqt_package == 'PyQt5': pro.write("QT += core gui widgets printsupport\n") pro.write('CONFIG += %s\n' % ('debug' if target_config.debug else 'release')) pro.write('CONFIG += %s\n' % ('staticlib' if opts.static else 'plugin plugin_bundle')) config = qmake_config.get('CONFIG') if config: pro.write('CONFIG += %s\n' % config) # Work around QTBUG-39300. pro.write('CONFIG -= android_install\n') qt5_qmake_config = _get_qt_qmake_config(qmake_config, 'Qt5') qt4_qmake_config = _get_qt_qmake_config(qmake_config, 'Qt4') if qt5_qmake_config or qt4_qmake_config: pro.write(''' greaterThan(QT_MAJOR_VERSION, 4) { ''') if qt5_qmake_config: _write_qt_qmake_config(qt5_qmake_config, pro) if qt4_qmake_config: pro.write('} else {\n') _write_qt_qmake_config(qt4_qmake_config, pro) pro.write('}\n') mname = module_config.name pro.write('TARGET = %s\n' % mname) if not opts.static: pro.write(''' win32 { PY_MODULE = %s.pyd PY_MODULE_SRC = $(DESTDIR_TARGET) LIBS += -L%s } else { PY_MODULE = %s.so macx { PY_MODULE_SRC = $(TARGET).plugin/Contents/MacOS/$(TARGET) QMAKE_LFLAGS += "-undefined dynamic_lookup" equals(QT_MAJOR_VERSION, 5) { equals(QT_MINOR_VERSION, 5) { QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS] } } } else { PY_MODULE_SRC = $(TARGET) } } QMAKE_POST_LINK = $(COPY_FILE) $$PY_MODULE_SRC $$PY_MODULE target.CONFIG = no_check_exist target.files = $$PY_MODULE ''' % (mname, quote(target_config.py_pylib_dir), mname)) pro.write(''' target.path = %s INSTALLS += target ''' % quote(target_config.module_dir)) mod_ext = '.pyd' if sys.platform == 'win32' else '.so' all_installs.append(target_config.module_dir + '/' + mname + mod_ext) sip_installs = module_config.get_sip_installs(target_config) if sip_installs is not None: path, files = sip_installs pro.write(''' sip.path = %s sip.files =''' % quote(path)) for f in files: pro.write(' \\\n ../%s' % f) pro.write(''' INSTALLS += sip ''') all_installs.append(path) pro.write('\n') # These optimisations could apply to other platforms. if module_config.no_exceptions: if target_config.py_platform.startswith('linux') or target_config.py_platform == 'darwin': pro.write('QMAKE_CXXFLAGS += -fno-exceptions\n') if target_config.py_platform.startswith('linux') and not opts.static: if target_config.py_version >= 0x030000: entry_point = 'PyInit_%s' % mname else: entry_point = 'init%s' % mname exp = open(os.path.join(mname, mname + '.exp'), 'wt') exp.write('{ global: %s; local: *; };' % entry_point) exp.close() pro.write('QMAKE_LFLAGS += -Wl,--version-script=%s.exp\n' % mname) if target_config.prot_is_public: pro.write('DEFINES += SIP_PROTECTED_IS_PUBLIC protected=public\n') defines = qmake_config.get('DEFINES') if defines: pro.write('DEFINES += %s\n' % defines) pro.write('DEFINES += QWT_PYTHON_WRAPPER\n') includepath = qmake_config.get('INCLUDEPATH') if includepath: pro.write('INCLUDEPATH += %s\n' % includepath) # Make sure the SIP include directory is searched before the Python include # directory if they are different. pro.write('INCLUDEPATH += %s\n' % quote(target_config.sip_inc_dir)) if target_config.py_inc_dir != target_config.sip_inc_dir: pro.write('INCLUDEPATH += %s\n' % quote(target_config.py_inc_dir)) libs = qmake_config.get('LIBS') if libs: if target_config.qwt_lib == None: pro.write('LIBS += %s -lqwt\n' % libs) else: pro.write('LIBS += %s -l%s\n' % (libs,target_config.qwt_lib)) if not opts.static: dylib = module_config.get_mac_wrapped_library_file(target_config) if dylib: pro.write(''' macx { QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\\\n\\\\t)$$quote(install_name_tool -change %s %s $$PY_MODULE) } ''' % (os.path.basename(dylib), dylib)) pro.write('\n') pro.write('HEADERS = sipAPI%s.h\n' % mname) pro.write('SOURCES =') for s in os.listdir(module_config.name): if s.endswith('.cpp'): pro.write(' \\\n %s' % s) pro.write('\n') pro.close() def _run_qmake(target_config, verbose, pro_name): """ Run qmake against a .pro file. target_config is the target configuration. verbose is set if the output is to be displayed. pro_name is the name of the .pro file. """ inform("Generating the Makefiles...") # qmake doesn't behave consistently if it is not run from the directory # containing the .pro file - so make sure it is. pro_dir, pro_file = os.path.split(pro_name) if pro_dir != '': cwd = os.getcwd() os.chdir(pro_dir) else: cwd = None mf = 'Makefile' _remove_file(mf) args = [quote(target_config.qmake)] # Make sure all Makefiles are generated now in case qmake has been # configured with environment variables. args.append('-recursive') if target_config.qmake_spec != '': args.append('-spec') args.append(target_config.qmake_spec) args.append(pro_file) _run_command(' '.join(args), verbose) if not os.access(mf, os.F_OK): error( "%s failed to create a Makefile from %s." % (target_config.qmake, pro_name)) # Restore the current directory. if cwd is not None: os.chdir(cwd) def _run_command(cmd, verbose): """ Run a command and display the output if requested. cmd is the command to run. verbose is set if the output is to be displayed. """ if verbose: sys.stdout.write(cmd + "\n") fout = _get_command_output(cmd) # Read stdout and stderr until there is no more output. lout = fout.readline() while lout: if verbose: if sys.hexversion >= 0x03000000: sys.stdout.write(str(lout, encoding=sys.stdout.encoding)) else: sys.stdout.write(lout) lout = fout.readline() fout.close() try: os.wait() except: pass def _get_command_output(cmd): """ Return a pipe from which a command's output can be read. cmd is the command. """ try: import subprocess except ImportError: _, sout = os.popen4(cmd) return sout p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return p.stdout def _remove_file(fname): """ Remove a file which may or may not exist. fname is the name of the file. """ try: os.remove(fname) except OSError: pass def _check_sip(target_config, pkg_config): """ Check that the version of sip is good enough. target_config is the target configuration. pkg_config is the package configuration. """ if target_config.sip is None: error( "Make sure you have a working sip on your PATH or use the " "--sip argument to explicitly specify a working sip.") pipe = os.popen(' '.join([quote(target_config.sip), '-V'])) for l in pipe: version_str = l.strip() break else: error("'%s -V' did not generate any output." % target_config.sip) pipe.close() if '.dev' in version_str or 'snapshot' in version_str: version = 0 else: version = version_from_string(version_str) if version is None: error( "'%s -V' generated unexpected output: '%s'." % ( target_config.sip, version_str)) min_sip_version = pkg_config.minimum_sip_version if min_sip_version: min_version = version_from_string(min_sip_version) if version < min_version: error( "This version of %s requires sip %s or later." % (pkg_config.descriptive_name, min_sip_version)) target_config.sip_version = version target_config.sip_version_str = version_str def _main(argv, pkg_config): """ Create the configured package. argv is the list of command line arguments. pkg_config is the package configuration. """ # Create the default target configuration. target_config = _TargetConfiguration(pkg_config) # Parse the command line. p = _create_optparser(target_config, pkg_config) opts, args = p.parse_args() if args: p.print_help() sys.exit(2) target_config.apply_pre_options(opts) # Query qmake for the basic configuration information. target_config.get_qt_configuration(opts) # Update the target configuration. if pkg_config.user_configuration_file_is_supported: config_file = opts.config_file else: config_file = None if config_file is not None: target_config.update_from_configuration_file(config_file) else: target_config.apply_sysroot() target_config.apply_post_options(opts, pkg_config) if target_config.pyqt_package is not None: if target_config.pyqt_sip_flags is None: target_config.introspect_pyqt(pkg_config) # Check SIP is new enough. _check_sip(target_config, pkg_config) # Perform any package specific checks now that all other information has # been captured. pkg_config.check_package(target_config) # Tell the user what's been found. _inform_user(target_config, pkg_config) # Allow for module specific hacks. pkg_config.pre_code_generation(target_config) # Generate the code. all_installs = [] for module_config in pkg_config.modules: _generate_code(target_config, opts, pkg_config, module_config, all_installs) # Concatenate any .api files. if pkg_config.qwt_api_file and target_config.api_dir != '': inform("Generating the Qwt API file...") f = open(pkg_config.qwt_api_file + '.api', 'w') for module_config in pkg_config.modules: api = open(module_config.name + '.api') for l in api: if target_config.pyqt_package is not None: l = target_config.pyqt_package + '.' + l f.write(l) api.close() os.remove(module_config.name + '.api') f.close() # Generate the top-level .pro file. inform("Generating the top-level .pro file...") pro_name = pkg_config.descriptive_name + '.pro' pro = open(pro_name, 'w') pro.write('''TEMPLATE = subdirs CONFIG += ordered nostrip SUBDIRS = %s ''' % ' '.join([module.name for module in pkg_config.modules])) if target_config.stubs_dir != '': stubs = [module.pep484_stub_file + '.pyi' for module in pkg_config.modules if module.pep484_stub_file] if stubs: pro.write(''' pep484_stubs.path = %s pep484_stubs.files = %s INSTALLS += pep484_stubs ''' % (target_config.stubs_dir, ' '.join(stubs))) all_installs.extend( [target_config.stubs_dir + '/' + pyi for pyi in stubs]) if pkg_config.qwt_api_file and target_config.api_dir != '': api_dir = target_config.api_dir + '/api/python' api_file = pkg_config.qwt_api_file + '.api' pro.write(''' api.path = %s api.files = %s INSTALLS += api ''' % (api_dir, api_file)) all_installs.append(api_dir + '/' + api_file) if target_config.distinfo: distinfo_dir = os.path.join(target_config.py_module_dir, pkg_config.distinfo_name + '-' + pkg_config.version + '.dist-info') mk_distinfo = sys.executable + ' mk_distinfo.py $(INSTALL_ROOT)' + distinfo_dir + ' installed.txt' pro.write(''' distinfo.extra = %s distinfo.path = %s INSTALLS += distinfo ''' % (mk_distinfo, target_config.module_dir)) # Create the file containing the names of all installed files. installed = open('installed.txt', 'w') for install in all_installs: installed.write(install + '\n') installed.close() pro.close() # Generate the Makefile. _run_qmake(target_config, opts.verbose, pro_name) ############################################################################### # The script starts here. ############################################################################### if __name__ == '__main__': # Assume the product is a package containing multiple modules. If it isn't # then create a dummy package containing the single module. try: pkg_config_type = PackageConfiguration except NameError: pkg_config_type = type('PackageConfiguration', (object, ), {}) if hasattr(pkg_config_type, 'modules'): # Provide some default values. pkg_config_type.distinfo_name = getattr(pkg_config_type, 'distinfo_name', '') else: mod_config_type = ModuleConfiguration # Extract the package-specific attributes and methods. pkg_config_type.descriptive_name = mod_config_type.descriptive_name pkg_config_type.distinfo_name = getattr(mod_config_type, 'distinfo_name', '') pkg_config_type.legacy_configuration_script = mod_config_type.legacy_configuration_script pkg_config_type.minimum_sip_version = mod_config_type.minimum_sip_version pkg_config_type.protected_is_public_is_supported = mod_config_type.protected_is_public_is_supported pkg_config_type.pyqt4_is_supported = mod_config_type.pyqt4_is_supported pkg_config_type.pyqt5_is_supported = mod_config_type.pyqt5_is_supported pkg_config_type.pyqt5_is_default = mod_config_type.pyqt5_is_default pkg_config_type.qwt_api_file = mod_config_type.qwt_api_file pkg_config_type.support_email_address = mod_config_type.support_email_address pkg_config_type.user_configuration_file_is_supported = mod_config_type.user_configuration_file_is_supported pkg_config_type.user_pyqt_sip_flags_is_supported = mod_config_type.user_pyqt_sip_flags_is_supported pkg_config_type.version = mod_config_type.version pkg_config_type.init_target_configuration = staticmethod( mod_config_type.init_target_configuration) pkg_config_type.init_optparser = staticmethod( mod_config_type.init_optparser) pkg_config_type.apply_options = staticmethod( mod_config_type.apply_options) pkg_config_type.inform_user = staticmethod( mod_config_type.inform_user) pkg_config_type.pre_code_generation = staticmethod( mod_config_type.pre_code_generation) pkg_config_type.get_sip_flags = staticmethod( mod_config_type.get_sip_flags) # Note the name change. pkg_config_type.check_package = staticmethod( mod_config_type.check_module) pkg_config_type.modules = [mod_config_type()] pkg_config = pkg_config_type() try: _main(sys.argv, pkg_config) except SystemExit: raise except: if pkg_config.support_email_address: sys.stderr.write( """An internal error occured. Please report all the output from the program, including the following traceback, to %s. """ % pkg_config.support_email_address) raise PyQt-Qwt-1.02.02/configure.py000077500000000000000000002137151377204562100157000ustar00rootroot00000000000000# Copyright (c) 2020, Riverbank Computing Limited # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This is v2.16 of this boilerplate. from distutils import sysconfig import glob import os import optparse import sys ############################################################################### # You shouldn't need to modify anything above this line. ############################################################################### class ModuleConfiguration(object): """ This class encapsulates all the module specific information needed by the rest of this script to implement a configure.py script for modules that build on top of PyQt. Functions implemented by the rest of this script that begin with an underscore are considered internal and shouldn't be called from here. """ # The name of the module as it would be used in an import statement. name = 'Qwt' # The descriptive name of the module. This is used in help text and error # messages. descriptive_name = "Qwt" # The version of the module as a string. Set it to None if you don't # provide version information. version = '1.02.02' # The name of the PEP 376 .dist-info directory to be created. distinfo_name = 'Qwt' # Set if a configuration script is provided that handles versions of PyQt4 # prior to v4.10 (i.e. versions where the pyqtconfig.py module is # available). If provided the script must be called configure-old.py and # be in the same directory as this script. legacy_configuration_script = False # The minimum version of SIP that is required. This should be a # dot-separated string of two or three integers (e.g. '1.0', '4.10.3'). If # it is None or an empty string then the version is not checked. minimum_sip_version = '4.19' # Set if support for C++ exceptions can be disabled. no_exceptions = True # The name (without the .pyi extension) of the name of the PEP 484 stub # file to be generated. If it is None or an empty string then a stub file # is not generated. pep484_stub_file = 'Qwt' # Set if the module supports redefining 'protected' as 'public'. protected_is_public_is_supported = True # Set if the module supports PyQt4. pyqt4_is_supported = True # Set if the module supports PyQt5. pyqt5_is_supported = True # Set if the PyQt5 support is the default. It is ignored unless both # 'pyqt4_is_supported' and 'pyqt5_is_supported' are set. pyqt5_is_default = True # The name (without the .api extension) of the name of the Qwt API # file to be generated. If it is None or an empty string then an API file # is not generated. qwt_api_file = 'Qwt' # The email address that will be included when an error in the script is # detected. Leave it blank if you don't want to include an address. support_email_address = 'gudjon@gudjon.org' # Set if the user can provide a configuration file. It is normally only # used if cross-compilation is supported. user_configuration_file_is_supported = True # Set if the user is allowed to pass PyQt sip flags on the command line. # It is normally only used if cross-compilation is supported. It is # ignored unless at least one of 'pyqt4_is_supported' or # 'pyqt5_is_supported' is set. user_pyqt_sip_flags_is_supported = True @staticmethod def init_target_configuration(target_configuration): """ Perform any module specific initialisation of the target target configuration. Typically this is the initialisation of module specific attributes. To avoid name clashes attributes should be given a module specific prefix. target_configuration is the target configuration. """ target_configuration.qwt_version = None target_configuration.qwt_features_dir = None target_configuration.qwt_inc_dir = None target_configuration.qwt_lib_dir = None target_configuration.qwt_lib = None target_configuration.qwt_sip_dir = None @staticmethod def init_optparser(optparser, target_configuration): """ Perform any module specific initialisation of the command line option parser. To avoid name clashes destination attributes should be given a module specific prefix. optparser is the option parser. target_configuration is the target configuration. """ optparser.add_option('--qwt-incdir', '-n', dest='qwt_inc_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the Qwt header " "file directory is DIR [default: QT_INSTALL_HEADERS]") optparser.add_option('--qwt-featuresdir', dest='qwt_features_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the qwt.prf features " "file is DIR [default: " "QT_INSTALL_PREFIX/mkspecs/features]") optparser.add_option('--qwt-libdir', '-o', dest='qwt_lib_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the Qwt library is DIR " "[default: QT_INSTALL_LIBS]") optparser.add_option('--qwt-lib', '-l', dest='qwt_lib', type='string', default=None, help="the Qwt library " "[default: qwt]") optparser.add_option('--qwt-sipdir', '-v', dest='qwt_sip_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the Qwt .sip files will be installed in DIR " "[default: %s]" % target_configuration.pyqt_sip_dir) optparser.add_option("--no-sip-files", action="store_true", default=False, dest="qwt_no_sip_files", help="disable the installation of the .sip files " "[default: enabled]") @staticmethod def apply_options(target_configuration, options): """ Apply the module specific command line options to the target configuration. target_configuration is the target configuration. options are the parsed options. """ if options.qwt_features_dir is not None: target_configuration.qwt_features_dir = options.qwt_features_dir if options.qwt_inc_dir is not None: target_configuration.qwt_inc_dir = options.qwt_inc_dir if options.qwt_lib_dir is not None: target_configuration.qwt_lib_dir = options.qwt_lib_dir if options.qwt_lib is not None: target_configuration.qwt_lib = options.qwt_lib if options.qwt_sip_dir is not None: target_configuration.qwt_sip_dir = options.qwt_sip_dir else: target_configuration.qwt_sip_dir = target_configuration.pyqt_sip_dir if options.qwt_no_sip_files: target_configuration.qwt_sip_dir = '' @staticmethod def check_module(target_configuration): """ Perform any module specific checks now that the target configuration is complete. target_configuration is the target configuration. """ # Find the Qwt header files. inc_dir = target_configuration.qwt_inc_dir if inc_dir is None: inc_dir = target_configuration.qt_inc_dir qwtglobal = os.path.join(inc_dir, '', 'qwt_global.h') if not os.access(qwtglobal, os.F_OK): error( "%s could not be found in %s. If " "Qwt is installed then use the --qwt-incdir " "argument to explicitly specify the correct " "directory." %(qwtglobal,inc_dir)) # Get the Qwt version string. qwt_version = read_define(qwtglobal, 'QWT_VERSION_STR') if qwt_version is None: error( "The Qwt version number could not be determined by " "reading %s." % qwtglobal) lib_dir = target_configuration.qwt_lib_dir if lib_dir is None: lib_dir = target_configuration.qt_lib_dir if not glob.glob(os.path.join(lib_dir, '*qwt*')): error( "The Qwt library could not be found in %s. If " "Qwt is installed then use the --qwt-libdir " "argument to explicitly specify the correct " "directory." % lib_dir) # Because we include the Python bindings with the C++ code we can # reasonably force the same version to be used and not bother about # versioning in the .sip files. qv=qwt_version.split('.') qwt_version_numeric = int(qv[0])*10000 + int(qv[1])*100 + int(qv[2]) mv=ModuleConfiguration.version.split('.') mod_version_numeric = int(mv[0])*10000 + int(mv[1])*100 + int(mv[2]) if qwt_version_numeric < mod_version_numeric: error( "Qwt %s is being used but the Python bindings %s " "are being built. Please use a newer Qwt " "version." % (qwt_version, ModuleConfiguration.version)) target_configuration.qwt_version = qwt_version @staticmethod def inform_user(target_configuration): """ Inform the user about module specific configuration information. target_configuration is the target configuration. """ inform("Qwt %s is being used." % target_configuration.qwt_version) if target_configuration.qwt_sip_dir != '': inform("The Qwt .sip files will be installed in %s." % target_configuration.qwt_sip_dir) @staticmethod def pre_code_generation(target_config): """ Perform any module specific initialisation prior to generating the code. target_config is the target configuration. """ # Nothing to do. @staticmethod def get_sip_flags(target_configuration): """ Return the list of module-specific flags to pass to SIP. target_configuration is the target configuration. """ # Nothing to do. return [] @staticmethod def get_sip_file(target_configuration): """ Return the name of the module's .sip file. target_configuration is the target configuration. """ return 'sip/Qwt_Qt5.sip' if target_configuration.pyqt_package == 'PyQt5' else 'sip/Qwt_Qt4.sip' @staticmethod def get_sip_installs(target_configuration): """ Return a tuple of the installation directory of the module's .sip files and a sequence of the names of each of the .sip files relative to the directory containing this configuration script. None is returned if the module's .sip files are not to be installed. target_configuration is the target configuration. """ if target_configuration.qwt_sip_dir == '': return None path = os.path.join(target_configuration.qwt_sip_dir, 'Qwt') files = glob.glob('sip/*.sip') return path, files @staticmethod def get_qmake_configuration(target_configuration): """ Return a dict of qmake configuration values for CONFIG, DEFINES, INCLUDEPATH, LIBS and QT. If value names (i.e. dict keys) have either 'Qt4' or 'Qt5' prefixes then they are specific to the corresponding version of Qt. target_configuration is the target configuration. """ qmake = {'CONFIG': 'qwt'} if target_configuration.qwt_inc_dir is not None: qmake['INCLUDEPATH'] = quote(target_configuration.qwt_inc_dir) if target_configuration.qwt_lib_dir is not None: qmake['LIBS'] = '-L%s' % quote(target_configuration.qwt_lib_dir) if target_configuration.qwt_features_dir is not None: os.environ['QMAKEFEATURES'] = target_configuration.qwt_features_dir return qmake @staticmethod def get_mac_wrapped_library_file(target_configuration): """ Return the full pathname of the file that implements the library being wrapped by the module as it would be called on OS/X so that the module will reference it explicitly without DYLD_LIBRARY_PATH being set. If it is None or an empty string then the default is used. target_configuration is the target configuration. """ return None ############################################################################### # You shouldn't need to modify anything below this line. ############################################################################### def error(msg): """ Display an error message and terminate. msg is the text of the error message. """ sys.stderr.write(_format("Error: " + msg) + "\n") sys.exit(1) def inform(msg): """ Display an information message. msg is the text of the error message. """ sys.stdout.write(_format(msg) + "\n") def quote(path): """ Return a path with quotes added if it contains spaces. path is the path. """ if ' ' in path: path = '"%s"' % path return path def optparser_store_abspath(option, opt_str, value, parser): """ An optparser callback that saves an option as an absolute pathname. """ setattr(parser.values, option.dest, os.path.abspath(value)) def optparser_store_abspath_dir(option, opt_str, value, parser): """ An optparser callback that saves an option as the absolute pathname of an existing directory. """ if not os.path.isdir(value): raise optparse.OptionValueError("'%s' is not a directory" % value) setattr(parser.values, option.dest, os.path.abspath(value)) def optparser_store_abspath_exe(option, opt_str, value, parser): """ An optparser callback that saves an option as the absolute pathname of an existing executable. """ if not os.access(value, os.X_OK): raise optparse.OptionValueError("'%s' is not an executable" % value) setattr(parser.values, option.dest, os.path.abspath(value)) def read_define(filename, define): """ Read the value of a #define from a file. filename is the name of the file. define is the name of the #define. None is returned if there was no such #define. """ f = open(filename) for l in f: wl = l.split() if len(wl) >= 3 and wl[0] == "#define" and wl[1] == define: # Take account of embedded spaces. value = ' '.join(wl[2:])[1:-1] break else: value = None f.close() return value def version_from_string(version_str): """ Convert a version string of the form m, m.n or m.n.o to an encoded version number (or None if it was an invalid format). version_str is the version string. """ parts = version_str.split('.') if not isinstance(parts, list): return None if len(parts) == 1: parts.append('0') if len(parts) == 2: parts.append('0') if len(parts) != 3: return None version = 0 for part in parts: try: v = int(part) except ValueError: return None version = (version << 8) + v return version def _format(msg, left_margin=0, right_margin=78): """ Format a message by inserting line breaks at appropriate places. msg is the text of the message. left_margin is the position of the left margin. right_margin is the position of the right margin. Returns the formatted message. """ curs = left_margin fmsg = " " * left_margin for w in msg.split(): l = len(w) if curs != left_margin and curs + l > right_margin: fmsg = fmsg + "\n" + (" " * left_margin) curs = left_margin if curs > left_margin: fmsg = fmsg + " " curs = curs + 1 fmsg = fmsg + w curs = curs + l return fmsg class _ConfigurationFileParser: """ A parser for configuration files. """ def __init__(self, config_file): """ Read and parse a configuration file. """ self._config = {} self._extrapolating = [] cfg = open(config_file) line_nr = 0 last_name = None section = '' section_config = {} self._config[section] = section_config for l in cfg: line_nr += 1 # Strip comments. l = l.split('#')[0] # See if this might be part of a multi-line. multiline = (last_name is not None and len(l) != 0 and l[0] == ' ') l = l.strip() if l == '': last_name = None continue # See if this is a new section. if l[0] == '[' and l[-1] == ']': section = l[1:-1].strip() if section == '': error( "%s:%d: Empty section name." % ( config_file, line_nr)) if section in self._config: error( "%s:%d: Section '%s' defined more than once." % ( config_file, line_nr, section)) section_config = {} self._config[section] = section_config last_name = None continue parts = l.split('=', 1) if len(parts) == 2: name = parts[0].strip() value = parts[1].strip() elif multiline: name = last_name value = section_config[last_name] value += ' ' + l else: name = value = '' if name == '' or value == '': error("%s:%d: Invalid line." % (config_file, line_nr)) section_config[name] = value last_name = name cfg.close() def sections(self): """ Return the list of sections, excluding the default one. """ return [s for s in self._config.keys() if s != ''] def preset(self, name, value): """ Add a preset value to the configuration. """ self._config[''][name] = value def get(self, section, name, default=None): """ Get a configuration value while extrapolating. """ # Get the name from the section, or the default section. value = self._config[section].get(name) if value is None: value = self._config[''].get(name) if value is None: if default is None: error( "Configuration file references non-existent name " "'%s'." % name) return default # Handle any extrapolations. parts = value.split('%(', 1) while len(parts) == 2: prefix, tail = parts parts = tail.split(')', 1) if len(parts) != 2: error( "Configuration file contains unterminated " "extrapolated name '%s'." % tail) xtra_name, suffix = parts if xtra_name in self._extrapolating: error( "Configuration file contains a recursive reference to " "'%s'." % xtra_name) self._extrapolating.append(xtra_name) xtra_value = self.get(section, xtra_name) self._extrapolating.pop() value = prefix + xtra_value + suffix parts = value.split('%(', 1) return value def getboolean(self, section, name, default): """ Get a boolean configuration value while extrapolating. """ value = self.get(section, name, default) # In case the default was returned. if isinstance(value, bool): return value if value in ('True', 'true', '1'): return True if value in ('False', 'false', '0'): return False error( "Configuration file contains invalid boolean value for " "'%s'." % name) def getlist(self, section, name, default): """ Get a list configuration value while extrapolating. """ value = self.get(section, name, default) # In case the default was returned. if isinstance(value, list): return value return value.split() class _HostPythonConfiguration: """ A container for the host Python configuration. """ def __init__(self): """ Initialise the configuration. """ self.platform = sys.platform self.version = sys.hexversion >> 8 self.inc_dir = sysconfig.get_python_inc() self.venv_inc_dir = sysconfig.get_python_inc(prefix=sys.prefix) self.module_dir = sysconfig.get_python_lib(plat_specific=1) self.debug = hasattr(sys, 'gettotalrefcount') if sys.platform == 'win32': try: # Python v3.3 and later. base_prefix = sys.base_prefix except AttributeError: try: # virtualenv for Python v2. base_prefix = sys.real_prefix except AttributeError: # We can't detect the base prefix in Python v3 prior to # v3.3. base_prefix = sys.prefix self.data_dir = sys.prefix self.lib_dir = base_prefix + '\\libs' else: self.data_dir = sys.prefix + '/share' self.lib_dir = sys.prefix + '/lib' class _TargetQtConfiguration: """ A container for the target Qt configuration. """ def __init__(self, qmake): """ Initialise the configuration. qmake is the full pathname of the qmake executable that will provide the configuration. """ pipe = os.popen(quote(qmake) + ' -query') for l in pipe: l = l.strip() tokens = l.split(':', 1) if isinstance(tokens, list): if len(tokens) != 2: error("Unexpected output from qmake: '%s'\n" % l) name, value = tokens else: name = tokens value = None name = name.replace('/', '_') setattr(self, name, value) pipe.close() class _TargetConfiguration: """ A container for the target configuration. """ def __init__(self, pkg_config): """ Initialise the configuration with default values. pkg_config is the package configuration. """ # Values based on the host Python configuration. py_config = _HostPythonConfiguration() self.py_debug = py_config.debug self.py_platform = py_config.platform self.py_version = py_config.version self.py_module_dir = py_config.module_dir self.py_inc_dir = py_config.inc_dir self.py_venv_inc_dir = py_config.venv_inc_dir self.py_pylib_dir = py_config.lib_dir self.py_sip_dir = os.path.join(py_config.data_dir, 'sip') # Remaining values. self.abi_version = None self.debug = False self.pyqt_sip_flags = None self.pyqt_version_str = '' self.qmake = self._find_exe('qmake') self.qmake_spec = '' self.qmake_variables = [] self.qt_version = 0 self.qt_version_str = '' self.sip = self._find_exe('sip5', 'sip') self.sip_inc_dir = None self.sip_version = None self.sip_version_str = None self.sysroot = '' self.stubs_dir = '' self.distinfo = False self.prot_is_public = (self.py_platform.startswith('linux') or self.py_platform == 'darwin') if pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: pyqt = 'PyQt5' if pkg_config.pyqt5_is_default else 'PyQt4' elif pkg_config.pyqt5_is_supported and not pkg_config.pyqt4_is_supported: pyqt = 'PyQt5' elif not pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: pyqt = 'PyQt4' else: pyqt = None if pyqt is not None: self.module_dir = os.path.join(py_config.module_dir, pyqt) self.pyqt_sip_dir = os.path.join(self.py_sip_dir, pyqt) else: self.module_dir = py_config.module_dir self.pyqt_sip_dir = None self.pyqt_package = pyqt pkg_config.init_target_configuration(self) def update_from_configuration_file(self, config_file): """ Update the configuration with values from a file. config_file is the name of the configuration file. """ inform("Reading configuration from %s..." % config_file) parser = _ConfigurationFileParser(config_file) # Populate some presets from the command line. parser.preset('py_major', str(self.py_version >> 16)) parser.preset('py_minor', str((self.py_version >> 8) & 0xff)) parser.preset('sysroot', self.sysroot) if self.pyqt_package is None: section = '' else: # At the moment we only need to distinguish between PyQt4 and # PyQt5. If that changes we may need a --target-pyqt-version # command line option. pyqt_version = 0x050000 if self.pyqt_package == 'PyQt5' else 0x040000 # Find the section corresponding to the version of PyQt. section = None latest_section = -1 for name in parser.sections(): parts = name.split() if len(parts) != 2 or parts[0] != 'PyQt': continue section_pyqt_version = version_from_string(parts[1]) if section_pyqt_version is None: continue # Major versions must match. if section_pyqt_version >> 16 != pyqt_version >> 16: continue # It must be no later that the version of PyQt. if section_pyqt_version > pyqt_version: continue # Save it if it is the latest so far. if section_pyqt_version > latest_section: section = name latest_section = section_pyqt_version if section is None: error( "%s does not define a section that covers PyQt " "v%s." % (config_file, self.pyqt_version_str)) self.py_platform = parser.get(section, 'py_platform', self.py_platform) self.py_inc_dir = parser.get(section, 'py_inc_dir', self.py_inc_dir) self.py_venv_inc_dir = self.py_inc_dir self.py_pylib_dir = parser.get(section, 'py_pylib_dir', self.py_pylib_dir) self.module_dir = parser.get(section, 'module_dir', self.module_dir) if self.pyqt_package is not None: self.py_sip_dir = parser.get(section, 'py_sip_dir', self.py_sip_dir) # Construct the SIP flags. flags = [] sip_module = parser.get(section, 'sip_module') if sip_module is not None: flags.append('-n') flags.append(sip_module) flags.append('-t') flags.append(self._get_platform_tag()) if self.pyqt_package == 'PyQt5': if self.qt_version < 0x050000: error("PyQt5 requires Qt v5.0 or later.") if self.qt_version > 0x060000: self.qt_version = 0x060000 else: if self.qt_version > 0x050000: self.qt_version = 0x050000 major = (self.qt_version >> 16) & 0xff minor = (self.qt_version >> 8) & 0xff patch = self.qt_version & 0xff # Qt v5.12.4 was the last release where we updated PyQt for a # patch version. if (major, minor) >= (5, 13): patch = 0 elif (major, minor) == (5, 12): if patch > 4: patch = 4 flags.append('-t') flags.append('Qt_%d_%d_%d' % (major, minor, patch)) for feat in parser.getlist(section, 'pyqt_disabled_features', []): flags.append('-x') flags.append(feat) self.pyqt_sip_flags = ' '.join(flags) def _get_platform_tag(self): """ Return the tag for the target platform. """ # This replicates the logic in PyQt's configure scripts. if self.py_platform == 'win32': plattag = 'WS_WIN' elif self.py_platform == 'darwin': plattag = 'WS_MACX' else: plattag = 'WS_X11' return plattag def introspect_pyqt(self, pkg_config): """ Introspect PyQt to determine the sip flags required. pkg_config is the package configuration. """ if self.pyqt_package == 'PyQt5': try: from PyQt5 import QtCore except ImportError: error( "Unable to import PyQt5.QtCore. Make sure PyQt5 is " "installed.") else: try: from PyQt4 import QtCore except ImportError: error( "Unable to import PyQt4.QtCore. Make sure PyQt4 is " "installed.") self.pyqt_version_str = QtCore.PYQT_VERSION_STR self.qt_version_str = QtCore.qVersion() # See if we have a PyQt that embeds its configuration. try: pyqt_config = QtCore.PYQT_CONFIGURATION except AttributeError: pyqt_config = None if pyqt_config is None: if pkg_config.legacy_configuration_script: # Fallback to the old configuration script. config_script = sys.argv[0].replace('configure', 'configure-old') args = [sys.executable, config_script] + sys.argv[1:] try: os.execv(sys.executable, args) except OSError: pass error("Unable to execute '%s'" % config_script) error("PyQt v4.10 or later is required.") self.pyqt_sip_flags = pyqt_config['sip_flags'] # This is a hack to remove the -t Qt_5_15_0 which doesn't seem to work with sip5 and > Qt_5_15_0 # There must be a better fix but until then...... XXXXXXXXXXXXXXXX if self.using_sip5() and self.pyqt_package == 'PyQt5': for f in pyqt_config['sip_flags'].split(): if len(f) > 6 and f[0:5] == "Qt_5_" and f >= "Qt_5_15_0": self.pyqt_sip_flags = "-n PyQt5.sip" #pyqt_config['sip_flags'] break def apply_sysroot(self): """ Apply sysroot where necessary. """ if self.sysroot != '': self.py_inc_dir = self._apply_sysroot(self.py_inc_dir) self.py_venv_inc_dir = self._apply_sysroot(self.py_venv_inc_dir) self.py_pylib_dir = self._apply_sysroot(self.py_pylib_dir) self.py_sip_dir = self._apply_sysroot(self.py_sip_dir) self.module_dir = self._apply_sysroot(self.module_dir) def _apply_sysroot(self, dir_name): """ Replace any leading sys.prefix of a directory name with sysroot. """ if dir_name.startswith(sys.prefix): dir_name = self.sysroot + dir_name[len(sys.prefix):] return dir_name def get_qt_configuration(self, opts): """ Get the Qt configuration that can be extracted from qmake. opts are the command line options. """ # Query qmake. qt_config = _TargetQtConfiguration(self.qmake) self.qt_version_str = getattr(qt_config, 'QT_VERSION', '') self.qt_version = version_from_string(self.qt_version_str) if self.qt_version is None: error("Unable to determine the version of Qt.") # On Windows for Qt versions prior to v5.9.0 we need to be explicit # about the qmake spec. if self.qt_version < 0x050900 and self.py_platform == 'win32': if self.py_version >= 0x030500: self.qmake_spec = 'win32-msvc2015' elif self.py_version >= 0x030300: self.qmake_spec = 'win32-msvc2010' elif self.py_version >= 0x020600: self.qmake_spec = 'win32-msvc2008' elif self.py_version >= 0x020400: self.qmake_spec = 'win32-msvc.net' else: self.qmake_spec = 'win32-msvc' else: # Otherwise use the default. self.qmake_spec = '' # The binary MacOS/X Qt installer used to default to XCode. If so then # use macx-clang (Qt v5) or macx-g++ (Qt v4). if sys.platform == 'darwin': try: # Qt v5. if qt_config.QMAKE_SPEC == 'macx-xcode': # This will exist (and we can't check anyway). self.qmake_spec = 'macx-clang' else: # No need to explicitly name the default. self.qmake_spec = '' except AttributeError: # Qt v4. self.qmake_spec = 'macx-g++' self.api_dir = os.path.join(qt_config.QT_INSTALL_DATA, 'qwt') self.qt_inc_dir = qt_config.QT_INSTALL_HEADERS self.qt_lib_dir = qt_config.QT_INSTALL_LIBS if self.sysroot == '': self.sysroot = getattr(qt_config, 'QT_SYSROOT', '') def apply_pre_options(self, opts): """ Apply options from the command line that influence subsequent configuration. opts are the command line options. """ # On Windows the interpreter must be a debug build if a debug version # is to be built and vice versa. if sys.platform == 'win32': if opts.debug: if not self.py_debug: error( "A debug version of Python must be used when " "--debug is specified.") elif self.py_debug: error( "--debug must be specified when a debug version of " "Python is used.") self.debug = opts.debug # Get the system root. if opts.sysroot is not None: self.sysroot = opts.sysroot # Determine how to run qmake. if opts.qmake is not None: self.qmake = opts.qmake # On Windows add the directory that probably contains the Qt DLLs # to PATH. if sys.platform == 'win32': path = os.environ['PATH'] path = os.path.dirname(self.qmake) + ';' + path os.environ['PATH'] = path if self.qmake is None: error( "Use the --qmake argument to explicitly specify a working " "Qt qmake.") if opts.qmakespec is not None: self.qmake_spec = opts.qmakespec if self.pyqt_package is not None: try: self.pyqt_package = opts.pyqt_package except AttributeError: # Multiple PyQt versions are not supported. pass self.module_dir = os.path.join(self.py_module_dir, self.pyqt_package) def apply_post_options(self, opts, pkg_config): """ Apply options from the command line that override the previous configuration. opts are the command line options. pkg_config is the package configuration. """ if self.pyqt_package is not None: if pkg_config.user_pyqt_sip_flags_is_supported: if opts.pyqt_sip_flags is not None: self.pyqt_sip_flags = opts.pyqt_sip_flags if opts.pyqt_sip_dir is not None: self.pyqt_sip_dir = opts.pyqt_sip_dir else: # If sip v5 or later installed a bindings directory then assume # the PyQt .sip files are there. bindings_dir = os.path.join(self.module_dir, 'bindings') if os.path.isdir(bindings_dir): self.pyqt_sip_dir = bindings_dir else: self.pyqt_sip_dir = os.path.join(self.py_sip_dir, self.pyqt_package) if _has_stubs(pkg_config): if opts.stubsdir is not None: self.stubs_dir = opts.stubsdir if opts.no_stubs: self.stubs_dir = '' elif self.stubs_dir == '': self.stubs_dir = self.module_dir if pkg_config.qwt_api_file: if opts.apidir is not None: self.api_dir = opts.apidir if opts.no_qwt_api: self.api_dir = '' if opts.destdir is not None: self.module_dir = opts.destdir if pkg_config.protected_is_public_is_supported: if opts.prot_is_public is not None: self.prot_is_public = opts.prot_is_public else: self.prot_is_public = False if opts.sip_inc_dir is not None: self.sip_inc_dir = opts.sip_inc_dir if opts.sip is not None: self.sip = opts.sip if opts.abi_version is not None: if not self.using_sip5(): error("The --abi-version argument can only be used with sip5.") self.abi_version = opts.abi_version if pkg_config.distinfo_name and opts.distinfo: self.distinfo = True pkg_config.apply_options(self, opts) def using_sip5(self): """ Return True if sip5 is being used. """ return os.path.basename(self.sip).startswith('sip5') @staticmethod def _find_exe(*exes): """ Find an executable, ie. the first on the path. """ path_dirs = os.environ.get('PATH', '').split(os.pathsep) for exe in exes: # Strip any surrounding quotes. if exe.startswith('"') and exe.endswith('"'): exe = exe[1:-1] if sys.platform == 'win32': exe = exe + '.exe' for d in path_dirs: exe_path = os.path.join(d, exe) if os.access(exe_path, os.X_OK): return exe_path return None def _create_optparser(target_config, pkg_config): """ Create the parser for the command line. target_config is the target configuration containing default values. pkg_config is the package configuration. """ pkg_name = pkg_config.descriptive_name p = optparse.OptionParser(usage="python %prog [options]", version=pkg_config.version) p.add_option('--spec', dest='qmakespec', default=None, action='store', metavar="SPEC", help="pass -spec SPEC to qmake") if pkg_config.distinfo_name: p.add_option("--no-dist-info", action="store_false", default=True, dest="distinfo", help="do not install the dist-info directory") if _has_stubs(pkg_config): p.add_option('--stubsdir', dest='stubsdir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="the PEP 484 stubs will be installed in DIR [default: " "with the module]") p.add_option('--no-stubs', dest='no_stubs', default=False, action='store_true', help="disable the installation of the PEP 484 stubs " "[default: enabled]") if pkg_config.qwt_api_file: p.add_option('--apidir', '-a', dest='apidir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="the Qwt API file will be installed in DIR " "[default: QT_INSTALL_DATA/qwt]") p.add_option('--no-qwt-api', dest='no_qwt_api', default=False, action='store_true', help="disable the installation of the Qwt API file " "[default: enabled]") if pkg_config.user_configuration_file_is_supported: p.add_option('--configuration', dest='config_file', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="FILE", help="FILE defines the target configuration") p.add_option('--destdir', '-d', dest='destdir', type='string', default=None, action='callback', callback=optparser_store_abspath, metavar="DIR", help="install %s in DIR [default: %s]" % (pkg_name, target_config.module_dir)) if pkg_config.protected_is_public_is_supported: p.add_option('--protected-is-public', dest='prot_is_public', default=None, action='store_true', help="enable building with 'protected' redefined as 'public' " "[default: %s]" % target_config.prot_is_public) p.add_option('--protected-not-public', dest='prot_is_public', action='store_false', help="disable building with 'protected' redefined as 'public'") if target_config.pyqt_package is not None: pyqt = target_config.pyqt_package if pkg_config.pyqt5_is_supported and pkg_config.pyqt4_is_supported: p.add_option('--pyqt', dest='pyqt_package', type='choice', choices=['PyQt4', 'PyQt5'], default=pyqt, action='store', metavar="PyQtn", help="configure for PyQt4 or PyQt5 [default: %s]" % pyqt) if pkg_config.user_pyqt_sip_flags_is_supported: p.add_option('--pyqt-sip-flags', dest='pyqt_sip_flags', default=None, action='store', metavar="FLAGS", help="the sip flags used to build PyQt [default: query PyQt]") p.add_option('--qmake', '-q', dest='qmake', type='string', default=None, action='callback', callback=optparser_store_abspath_exe, metavar="FILE", help="the pathname of qmake is FILE [default: %s]" % ( target_config.qmake or "search PATH")) p.add_option('--sip', dest='sip', type='string', default=None, action='callback', callback=optparser_store_abspath_exe, metavar="FILE", help="the pathname of sip is FILE [default: " "%s]" % (target_config.sip or "None")) p.add_option('--sip-incdir', dest='sip_inc_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the sip.h header file file is DIR " "[default: %s]" % target_config.sip_inc_dir) p.add_option("--abi-version", dest='abi_version', default=None, metavar="VERSION", help="the SIP ABI version to use (sip5 only)") if target_config.pyqt_package is not None: p.add_option('--pyqt-sipdir', dest='pyqt_sip_dir', type='string', default=None, action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="the directory containing the PyQt .sip files is DIR " "[default: %s]" % target_config.pyqt_sip_dir) p.add_option('--concatenate', '-c', dest='concat', default=False, action='store_true', help="concatenate the C++ source files") p.add_option('--concatenate-split', '-j', dest='split', type='int', default=1, metavar="N", help="split the concatenated C++ source files into N pieces " "[default: 1]") p.add_option('--static', '-k', dest='static', default=False, action='store_true', help="build a static %s" % pkg_name) p.add_option("--sysroot", dest='sysroot', type='string', action='callback', callback=optparser_store_abspath_dir, metavar="DIR", help="DIR is the target system root directory") p.add_option('--no-docstrings', dest='no_docstrings', default=False, action='store_true', help="disable the generation of docstrings") p.add_option('--trace', '-r', dest='tracing', default=False, action='store_true', help="build %s with tracing enabled" % pkg_name) p.add_option('--debug', '-u', default=False, action='store_true', help="build %s with debugging symbols" % pkg_name) p.add_option('--verbose', '-w', dest='verbose', default=False, action='store_true', help="enable verbose output during configuration") pkg_config.init_optparser(p, target_config) return p def _has_stubs(pkg_config): """ See if a stub file for any of the modules will be generated. pkg_config is the package configuration. """ for module_config in pkg_config.modules: if module_config.pep484_stub_file: return True return False def _inform_user(target_config, pkg_config): """ Tell the user the values that are going to be used. target_config is the target configuration. pkg_config is the package configuration. """ pkg_name = pkg_config.descriptive_name inform("Configuring %s %s..." % (pkg_name, pkg_config.version)) pkg_config.inform_user(target_config) inform("%s will be installed in %s." % (pkg_name, target_config.module_dir)) if target_config.debug: inform("A debug version of %s will be built." % pkg_name) if target_config.py_debug: inform("A debug build of Python is being used.") if target_config.pyqt_version_str != '': inform("PyQt %s is being used." % target_config.pyqt_version_str) else: inform("%s is being used." % target_config.pyqt_package) if target_config.qt_version_str != '': inform("Qt %s is being used." % target_config.qt_version_str) if target_config.sysroot != '': inform("The system root directory is %s." % target_config.sysroot) inform("sip %s is being used." % target_config.sip_version_str) inform("The sip executable is %s." % target_config.sip) if target_config.prot_is_public: inform("%s is being built with 'protected' redefined as 'public'." % pkg_name) if target_config.stubs_dir != '': inform("The PEP 484 stubs will be installed in %s." % target_config.stubs_dir) if pkg_config.qwt_api_file and target_config.api_dir != '': inform("The Qwt API file will be installed in %s." % os.path.join(target_config.api_dir, 'api', 'python')) def _generate_code(target_config, opts, pkg_config, module_config, all_installs): """ Generate the code for the module. target_config is the target configuration. opts are the command line options. pkg_config is the package configuration. module_config is the module configuration. all_installs is a list that is updated with the files installed for this module. """ inform( "Generating the C++ source for the %s module..." % module_config.name) # Generate the code in a module-specific sub-directory. try: os.mkdir(module_config.name) except: pass # Build the SIP command line. argv = [quote(target_config.sip)] if target_config.abi_version: argv.append('--abi-version') argv.append(target_config.abi_version) # Tell SIP if this is a debug build of Python (SIP v4.19.1 and later). if target_config.sip_version >= 0x041301 and target_config.py_debug: argv.append('-D') # This assumes that, for multi-module packages, each modules' .sip files # will be rooted in a common root directory. We must do this now so that # any '-I' needed appears first. pkg_root = os.path.dirname(os.path.abspath(__file__)) sip_file = module_config.get_sip_file(target_config) head, tail = os.path.split(sip_file) while head: head, tail = os.path.split(head) if tail != sip_file: argv.append('-I') argv.append(quote(os.path.join(pkg_root, tail))) # Add the PyQt-specific flags. if target_config.pyqt_package is not None: # Add PyQt's .sip files to the search path. argv.append('-I') argv.append(quote(target_config.pyqt_sip_dir)) # Get the flags used for the main PyQt module. argv.extend(target_config.pyqt_sip_flags.split()) # Add the backstop version. argv.append('-B') argv.append('Qt_6_0_0' if target_config.pyqt_package == 'PyQt5' else 'Qt_5_0_0') # Add the module-specific flags. argv.extend(pkg_config.get_sip_flags(target_config)) if target_config.stubs_dir != '': # Generate the stub file. argv.append('-y') argv.append(quote(module_config.pep484_stub_file + '.pyi')) if pkg_config.qwt_api_file and target_config.api_dir != '': # Generate the API file. argv.append('-a') argv.append(quote(module_config.name + '.api')) if target_config.prot_is_public: argv.append('-P'); if not opts.no_docstrings: argv.append('-o'); if opts.concat: argv.append('-j') argv.append(str(opts.split)) if opts.tracing: argv.append('-r') argv.append('-c') argv.append(os.path.abspath(module_config.name)) argv.append(os.path.join(pkg_root, sip_file)) check_file = os.path.join(module_config.name, 'sipAPI%s.h' % module_config.name) _remove_file(check_file) _run_command(' '.join(argv), opts.verbose) if not os.access(check_file, os.F_OK): error("Unable to create the C++ code.") # Generate the .pro file. _generate_pro(target_config, opts, module_config, all_installs) def _get_qt_qmake_config(qmake_config, qt_version): """ Return a dict of qmake configuration values for a specific Qt version. """ qt_qmake_config = {} for name, value in qmake_config.items(): name_parts = name.split(':') if len(name_parts) == 2 and name_parts[0] == qt_version: qt_qmake_config[name_parts[1]] = value return qt_qmake_config def _write_qt_qmake_config(qt_qmake_config, pro): """ Write the qmake configuration values to a .pro file. """ for name in ('QT', 'CONFIG', 'DEFINES', 'INCLUDEPATH', 'LIBS'): value = qt_qmake_config.get(name) if value: pro.write(' %s += %s\n' % (name, value)) def _generate_pro(target_config, opts, module_config, all_installs): """ Generate the .pro file for the module. target_config is the target configuration. opts are the command line options. module_config is the module configuration. all_installs is a list that is updated with the files installed for this module. """ inform("Generating the .pro file for the %s module..." % module_config.name) # Without the 'no_check_exist' magic the target.files must exist when qmake # is run otherwise the install and uninstall targets are not generated. qmake_config = module_config.get_qmake_configuration(target_config) pro = open(os.path.join(module_config.name, module_config.name + '.pro'), 'w') pro.write('TEMPLATE = lib\n') qt = qmake_config.get('QT') if qt: pro.write('QT += %s\n' % qt) if target_config.pyqt_package == 'PyQt5': pro.write("QT += core gui widgets printsupport\n") pro.write('CONFIG += %s\n' % ('debug' if target_config.debug else 'release')) pro.write('CONFIG += %s\n' % ('staticlib' if opts.static else 'plugin plugin_bundle')) config = qmake_config.get('CONFIG') if config: pro.write('CONFIG += %s\n' % config) # Work around QTBUG-39300. pro.write('CONFIG -= android_install\n') qt5_qmake_config = _get_qt_qmake_config(qmake_config, 'Qt5') qt4_qmake_config = _get_qt_qmake_config(qmake_config, 'Qt4') if qt5_qmake_config or qt4_qmake_config: pro.write(''' greaterThan(QT_MAJOR_VERSION, 4) { ''') if qt5_qmake_config: _write_qt_qmake_config(qt5_qmake_config, pro) if qt4_qmake_config: pro.write('} else {\n') _write_qt_qmake_config(qt4_qmake_config, pro) pro.write('}\n') mname = module_config.name pro.write('TARGET = %s\n' % mname) if not opts.static: pro.write(''' win32 { PY_MODULE = %s.pyd PY_MODULE_SRC = $(DESTDIR_TARGET) LIBS += -L%s } else { PY_MODULE = %s.so macx { PY_MODULE_SRC = $(TARGET).plugin/Contents/MacOS/$(TARGET) QMAKE_LFLAGS += "-undefined dynamic_lookup" equals(QT_MAJOR_VERSION, 5) { equals(QT_MINOR_VERSION, 5) { QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS] } } } else { PY_MODULE_SRC = $(TARGET) } } QMAKE_POST_LINK = $(COPY_FILE) $$PY_MODULE_SRC $$PY_MODULE target.CONFIG = no_check_exist target.files = $$PY_MODULE ''' % (mname, quote(target_config.py_pylib_dir), mname)) pro.write(''' target.path = %s INSTALLS += target ''' % quote(target_config.module_dir)) if sys.platform == 'win32': fs = '{}.lib' if opts.static else '{}.pyd' else: fs = 'lib{}.a' if opts.static else '{}.so' all_installs.append(target_config.module_dir + '/' + fs.format(mname)) # Change to the directory containing this script (in case of out-of-source # builds). pkg_root = os.path.dirname(os.path.abspath(__file__)) old_cwd = os.getcwd() os.chdir(pkg_root) sip_installs = module_config.get_sip_installs(target_config) os.chdir(old_cwd) if sip_installs is not None: path, files = sip_installs pro.write(''' sip.path = %s sip.files =''' % quote(path)) rel_pkg_root = os.path.relpath(pkg_root) for fn in files: # The filename should be relative to the current directory and use # POSIX separators. fn = fn.replace('/', os.sep) fn = os.path.join(rel_pkg_root, fn) fn = fn.replace(os.sep, '/') fn = os.path.normpath(fn) pro.write(' \\\n ../%s' % fn) pro.write(''' INSTALLS += sip ''') all_installs.append(path) pro.write('\n') # These optimisations could apply to other platforms. if module_config.no_exceptions: if target_config.py_platform.startswith('linux') or target_config.py_platform == 'darwin': pro.write('QMAKE_CXXFLAGS += -fno-exceptions\n') if target_config.py_platform.startswith('linux') and not opts.static: if target_config.py_version >= 0x030000: entry_point = 'PyInit_%s' % mname else: entry_point = 'init%s' % mname exp = open(os.path.join(mname, mname + '.exp'), 'wt') exp.write('{ global: %s; local: *; };' % entry_point) exp.close() pro.write('QMAKE_LFLAGS += -Wl,--version-script=%s.exp\n' % mname) if target_config.prot_is_public: pro.write('DEFINES += SIP_PROTECTED_IS_PUBLIC protected=public\n') defines = qmake_config.get('DEFINES') if defines: pro.write('DEFINES += %s\n' % defines) pro.write('DEFINES += QWT_PYTHON_WRAPPER\n') includepath = qmake_config.get('INCLUDEPATH') if includepath: pro.write('INCLUDEPATH += %s\n' % includepath) # Make sure the SIP include directory is searched before the Python include # directory if they are different. pro.write('INCLUDEPATH += %s\n' % quote(target_config.sip_inc_dir)) if target_config.py_inc_dir != target_config.sip_inc_dir: pro.write('INCLUDEPATH += %s\n' % quote(target_config.py_inc_dir)) libs = qmake_config.get('LIBS') if libs: if target_config.qwt_lib == None: pro.write('LIBS += %s -lqwt\n' % libs) else: pro.write('LIBS += %s -l%s\n' % (libs,target_config.qwt_lib)) if not opts.static: dylib = module_config.get_mac_wrapped_library_file(target_config) if dylib: pro.write(''' macx { QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\\\n\\\\t)$$quote(install_name_tool -change %s %s $$PY_MODULE) } ''' % (os.path.basename(dylib), dylib)) pro.write('\n') pro.write('HEADERS = sipAPI%s.h\n' % mname) pro.write('SOURCES =') for s in sorted(os.listdir(module_config.name)): if s.endswith('.cpp'): pro.write(' \\\n %s' % s) pro.write('\n') if target_config.qmake_variables: pro.write('\n'.join(target_config.qmake_variables) + '\n') pro.close() def _run_qmake(target_config, verbose, pro_name): """ Run qmake against a .pro file. target_config is the target configuration. verbose is set if the output is to be displayed. pro_name is the name of the .pro file. """ inform("Generating the Makefiles...") # qmake doesn't behave consistently if it is not run from the directory # containing the .pro file - so make sure it is. pro_dir, pro_file = os.path.split(pro_name) if pro_dir != '': cwd = os.getcwd() os.chdir(pro_dir) else: cwd = None mf = 'Makefile' _remove_file(mf) args = [quote(target_config.qmake)] # Make sure all Makefiles are generated now in case qmake has been # configured with environment variables. args.append('-recursive') if target_config.qmake_spec != '': args.append('-spec') args.append(target_config.qmake_spec) args.append(pro_file) _run_command(' '.join(args), verbose) if not os.access(mf, os.F_OK): error( "%s failed to create a Makefile from %s." % (target_config.qmake, pro_name)) # Restore the current directory. if cwd is not None: os.chdir(cwd) def _run_command(cmd, verbose): """ Run a command and display the output if requested. cmd is the command to run. verbose is set if the output is to be displayed. """ if verbose: sys.stdout.write(cmd + "\n") fout = _get_command_output(cmd) # Read stdout and stderr until there is no more output. lout = fout.readline() while lout: if verbose: if sys.hexversion >= 0x03000000: sys.stdout.write(str(lout, encoding=sys.stdout.encoding)) else: sys.stdout.write(lout) lout = fout.readline() fout.close() try: os.wait() except: pass def _get_command_output(cmd): """ Return a pipe from which a command's output can be read. cmd is the command. """ try: import subprocess except ImportError: _, sout = os.popen4(cmd) return sout p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return p.stdout def _remove_file(fname): """ Remove a file which may or may not exist. fname is the name of the file. """ try: os.remove(fname) except OSError: pass def _check_sip(target_config, pkg_config, verbose): """ Check that the version of sip is good enough. target_config is the target configuration. pkg_config is the package configuration. verbose is set if the output is to be displayed. """ if target_config.sip is None: error( "Make sure you have a working sip on your PATH or use the " "--sip argument to explicitly specify a working sip.") pipe = os.popen(' '.join([quote(target_config.sip), '-V'])) for l in pipe: version_str = l.strip() break else: error("'%s -V' did not generate any output." % target_config.sip) pipe.close() if '.dev' in version_str or 'snapshot' in version_str: # We only need to distinguish between sip v4 and sip v5. if target_config.using_sip5(): version = 0x050000 else: version = 0x040000 else: version = version_from_string(version_str) if version is None: error( "'%s -V' generated unexpected output: '%s'." % ( target_config.sip, version_str)) min_sip_version = pkg_config.minimum_sip_version if min_sip_version: min_version = version_from_string(min_sip_version) if version < min_version: error( "This version of %s requires sip %s or later." % (pkg_config.descriptive_name, min_sip_version)) if version >= 0x050000: # Install the sip.h file for the private sip module. if target_config.sip_inc_dir is None: target_config.sip_inc_dir = os.path.join( os.path.abspath(os.getcwd()), 'include') inform("Installing sip.h in %s..." % target_config.sip_inc_dir) os.makedirs(target_config.sip_inc_dir, exist_ok=True) argv = ['sip-module', '--sip-h'] if target_config.abi_version: argv.append('--abi-version') argv.append(target_config.abi_version) argv.append('--target-dir') argv.append(quote(target_config.sip_inc_dir)), argv.append('PyQt5.sip') _run_command(' '.join(argv), verbose) if not os.access(os.path.join(target_config.sip_inc_dir, 'sip.h'), os.F_OK): error( "sip-module failed to install sip.h in %s." % target_config.sip_inc_dir) else: if target_config.sip_inc_dir is None: target_config.sip_inc_dir = target_config.py_venv_inc_dir target_config.sip_version = version target_config.sip_version_str = version_str def _main(argv, pkg_config): """ Create the configured package. argv is the list of command line arguments. pkg_config is the package configuration. """ # Create the default target configuration. target_config = _TargetConfiguration(pkg_config) # Parse the command line. p = _create_optparser(target_config, pkg_config) opts, target_config.qmake_variables = p.parse_args() target_config.apply_pre_options(opts) # Query qmake for the basic configuration information. target_config.get_qt_configuration(opts) # Update the target configuration. if pkg_config.user_configuration_file_is_supported: config_file = opts.config_file else: config_file = None if config_file is not None: target_config.update_from_configuration_file(config_file) else: target_config.apply_sysroot() target_config.apply_post_options(opts, pkg_config) if target_config.pyqt_package is not None: if target_config.pyqt_sip_flags is None: target_config.introspect_pyqt(pkg_config) # Check SIP is new enough. _check_sip(target_config, pkg_config, opts.verbose) # Perform any package specific checks now that all other information has # been captured. pkg_config.check_package(target_config) # Tell the user what's been found. _inform_user(target_config, pkg_config) # Allow for module specific hacks. pkg_config.pre_code_generation(target_config) # Generate the code. all_installs = [] for module_config in pkg_config.modules: _generate_code(target_config, opts, pkg_config, module_config, all_installs) # Concatenate any .api files. if pkg_config.qwt_api_file and target_config.api_dir != '': inform("Generating the Qwt API file...") f = open(pkg_config.qwt_api_file + '.api', 'w') for module_config in pkg_config.modules: api = open(module_config.name + '.api') for l in api: if target_config.pyqt_package is not None: l = target_config.pyqt_package + '.' + l f.write(l) api.close() os.remove(module_config.name + '.api') f.close() # Generate the top-level .pro file. inform("Generating the top-level .pro file...") pro_name = pkg_config.descriptive_name + '.pro' pro = open(pro_name, 'w') pro.write('''TEMPLATE = subdirs CONFIG += ordered nostrip SUBDIRS = %s ''' % ' '.join([module.name for module in pkg_config.modules])) if target_config.stubs_dir != '': stubs = [module.pep484_stub_file + '.pyi' for module in pkg_config.modules if module.pep484_stub_file] if stubs: pro.write(''' pep484_stubs.path = %s pep484_stubs.files = %s INSTALLS += pep484_stubs ''' % (target_config.stubs_dir, ' '.join(stubs))) all_installs.extend( [target_config.stubs_dir + '/' + pyi for pyi in stubs]) if pkg_config.qwt_api_file and target_config.api_dir != '': api_dir = target_config.api_dir + '/api/python' api_file = pkg_config.qwt_api_file + '.api' pro.write(''' api.path = %s api.files = %s INSTALLS += api ''' % (api_dir, api_file)) all_installs.append(api_dir + '/' + api_file) if target_config.distinfo: # Allow for out-of-tree builds. distinfo_dir = os.path.join(target_config.py_module_dir, pkg_config.distinfo_name + '-' + pkg_config.version + '.dist-info') mk_distinfo = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mk_distinfo.py') run_mk_distinfo = '%s %s \\"$(INSTALL_ROOT)\\" %s installed.txt' % ( quote(sys.executable), quote(mk_distinfo), quote(distinfo_dir)) pro.write(''' distinfo.extra = %s distinfo.path = %s INSTALLS += distinfo ''' % (run_mk_distinfo, target_config.module_dir)) # Create the file containing the names of all installed files. installed = open('installed.txt', 'w') for install in all_installs: installed.write(install + '\n') installed.close() pro.close() # Generate the Makefile. _run_qmake(target_config, opts.verbose, pro_name) ############################################################################### # The script starts here. ############################################################################### if __name__ == '__main__': # Assume the product is a package containing multiple modules. If it isn't # then create a dummy package containing the single module. try: pkg_config_type = PackageConfiguration except NameError: pkg_config_type = type('PackageConfiguration', (object, ), {}) if hasattr(pkg_config_type, 'modules'): # Provide some default values. pkg_config_type.distinfo_name = getattr(pkg_config_type, 'distinfo_name', '') else: mod_config_type = ModuleConfiguration # Extract the package-specific attributes and methods. pkg_config_type.descriptive_name = mod_config_type.descriptive_name pkg_config_type.distinfo_name = getattr(mod_config_type, 'distinfo_name', '') pkg_config_type.legacy_configuration_script = mod_config_type.legacy_configuration_script pkg_config_type.minimum_sip_version = mod_config_type.minimum_sip_version pkg_config_type.protected_is_public_is_supported = mod_config_type.protected_is_public_is_supported pkg_config_type.pyqt4_is_supported = mod_config_type.pyqt4_is_supported pkg_config_type.pyqt5_is_supported = mod_config_type.pyqt5_is_supported pkg_config_type.pyqt5_is_default = mod_config_type.pyqt5_is_default pkg_config_type.qwt_api_file = mod_config_type.qwt_api_file pkg_config_type.support_email_address = mod_config_type.support_email_address pkg_config_type.user_configuration_file_is_supported = mod_config_type.user_configuration_file_is_supported pkg_config_type.user_pyqt_sip_flags_is_supported = mod_config_type.user_pyqt_sip_flags_is_supported pkg_config_type.version = mod_config_type.version pkg_config_type.init_target_configuration = staticmethod( mod_config_type.init_target_configuration) pkg_config_type.init_optparser = staticmethod( mod_config_type.init_optparser) pkg_config_type.apply_options = staticmethod( mod_config_type.apply_options) pkg_config_type.inform_user = staticmethod( mod_config_type.inform_user) pkg_config_type.pre_code_generation = staticmethod( mod_config_type.pre_code_generation) pkg_config_type.get_sip_flags = staticmethod( mod_config_type.get_sip_flags) # Note the name change. pkg_config_type.check_package = staticmethod( mod_config_type.check_module) pkg_config_type.modules = [mod_config_type()] pkg_config = pkg_config_type() try: _main(sys.argv, pkg_config) except SystemExit: raise except: if pkg_config.support_email_address: sys.stderr.write( """An internal error occured. Please report all the output from the program, including the following traceback, to %s. """ % pkg_config.support_email_address) raise PyQt-Qwt-1.02.02/header/000077500000000000000000000000001377204562100145615ustar00rootroot00000000000000PyQt-Qwt-1.02.02/header/qwt_series_data.h000066400000000000000000000223441377204562100201150ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ #ifndef QWT_SERIES_DATA_H #define QWT_SERIES_DATA_H 1 #include "qwt_global.h" #include "qwt_samples.h" #include "qwt_point_3d.h" #include "qwt_point_polar.h" #include #include /*! \brief Abstract interface for iterating over samples Qwt offers several implementations of the QwtSeriesData API, but in situations, where data of an application specific format needs to be displayed, without having to copy it, it is recommended to implement an individual data access. A subclass of QwtSeriesData must implement: - size()\n Should return number of data points. - sample()\n Should return values x and y values of the sample at specific position as QPointF object. - boundingRect()\n Should return the bounding rectangle of the data series. It is used for autoscaling and might help certain algorithms for displaying the data. You can use qwtBoundingRect() for an implementation but often it is possible to implement a more efficient algorithm depending on the characteristics of the series. The member d_boundingRect is intended for caching the calculated rectangle. */ template class QwtSeriesData { public: //! Constructor QwtSeriesData(); //! Destructor virtual ~QwtSeriesData(); //! \return Number of samples #ifndef QWT_PYTHON_WRAPPER virtual size_t size() const = 0; #else virtual size_t size() const {return 0;}; #endif /*! Return a sample \param i Index \return Sample at position i */ #ifndef QWT_PYTHON_WRAPPER virtual T sample( size_t i ) const = 0; #else virtual T sample( size_t i ) const {return T();}; #endif /*! Calculate the bounding rect of all samples The bounding rect is necessary for autoscaling and can be used for a couple of painting optimizations. qwtBoundingRect(...) offers slow implementations iterating over the samples. For large sets it is recommended to implement something faster f.e. by caching the bounding rectangle. \return Bounding rectangle */ #ifndef QWT_PYTHON_WRAPPER virtual QRectF boundingRect() const = 0; #else virtual QRectF boundingRect() const {return d_boundingRect;}; #endif /*! Set a the "rect of interest" QwtPlotSeriesItem defines the current area of the plot canvas as "rectangle of interest" ( QwtPlotSeriesItem::updateScaleDiv() ). It can be used to implement different levels of details. The default implementation does nothing. \param rect Rectangle of interest */ virtual void setRectOfInterest( const QRectF &rect ); protected: //! Can be used to cache a calculated bounding rectangle mutable QRectF d_boundingRect; private: QwtSeriesData &operator=( const QwtSeriesData & ); }; template QwtSeriesData::QwtSeriesData(): d_boundingRect( 0.0, 0.0, -1.0, -1.0 ) { } template QwtSeriesData::~QwtSeriesData() { } template void QwtSeriesData::setRectOfInterest( const QRectF & ) { } /*! \brief Template class for data, that is organized as QVector QVector uses implicit data sharing and can be passed around as argument efficiently. */ template class QwtArraySeriesData: public QwtSeriesData { public: //! Constructor QwtArraySeriesData(); /*! Constructor \param samples Array of samples */ QwtArraySeriesData( const QVector &samples ); /*! Assign an array of samples \param samples Array of samples */ void setSamples( const QVector &samples ); //! \return Array of samples const QVector samples() const; //! \return Number of samples virtual size_t size() const; /*! \return Sample at a specific position \param index Index \return Sample at position index */ virtual T sample( size_t index ) const; protected: //! Vector of samples QVector d_samples; }; template QwtArraySeriesData::QwtArraySeriesData() { } template QwtArraySeriesData::QwtArraySeriesData( const QVector &samples ): d_samples( samples ) { } template void QwtArraySeriesData::setSamples( const QVector &samples ) { QwtSeriesData::d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); d_samples = samples; } template const QVector QwtArraySeriesData::samples() const { return d_samples; } template size_t QwtArraySeriesData::size() const { return d_samples.size(); } template T QwtArraySeriesData::sample( size_t i ) const { return d_samples[ static_cast( i ) ]; } //! Interface for iterating over an array of points class QWT_EXPORT QwtPointSeriesData: public QwtArraySeriesData { public: QwtPointSeriesData( const QVector & = QVector() ); virtual QRectF boundingRect() const; }; //! Interface for iterating over an array of 3D points class QWT_EXPORT QwtPoint3DSeriesData: public QwtArraySeriesData { public: QwtPoint3DSeriesData( const QVector & = QVector() ); virtual QRectF boundingRect() const; }; //! Interface for iterating over an array of intervals class QWT_EXPORT QwtIntervalSeriesData: public QwtArraySeriesData { public: QwtIntervalSeriesData( const QVector & = QVector() ); virtual QRectF boundingRect() const; }; //! Interface for iterating over an array of samples class QWT_EXPORT QwtSetSeriesData: public QwtArraySeriesData { public: QwtSetSeriesData( const QVector & = QVector() ); virtual QRectF boundingRect() const; }; /*! Interface for iterating over an array of OHLC samples */ class QWT_EXPORT QwtTradingChartData: public QwtArraySeriesData { public: QwtTradingChartData( const QVector & = QVector() ); virtual QRectF boundingRect() const; }; QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); QWT_EXPORT QRectF qwtBoundingRect( const QwtSeriesData &, int from = 0, int to = -1 ); /*! Binary search for a sorted series of samples qwtUpperSampleIndex returns the index of sample that is the upper bound of value. Is the the value smaller than the smallest value the return value will be 0. Is the value greater or equal than the largest value the return value will be -1. \par Example The following example shows finds a point of curve from an x coordinate \verbatim #include #include struct compareX { inline bool operator()( const double x, const QPointF &pos ) const { return ( x < pos.x() ); } }; QLineF curveLineAt( const QwtPlotCurve *curve, double x ) { int index = qwtUpperSampleIndex( *curve->data(), x, compareX() ); if ( index == -1 && x == curve->sample( curve->dataSize() - 1 ).x() ) { // the last sample is excluded from qwtUpperSampleIndex index = curve->dataSize() - 1; } QLineF line; // invalid if ( index > 0 ) { line.setP1( curve->sample( index - 1 ) ); line.setP2( curve->sample( index ) ); } return line; } \endverbatim \param series Series of samples \param value Value \param lessThan Compare operation \note The samples must be sorted according to the order specified by the lessThan object of the range [begin, end) and returns the position of the one-past-the-last occurrence of value. If no such item is found, returns the position where the item should be inserted. */ template inline int qwtUpperSampleIndex( const QwtSeriesData &series, double value, LessThan lessThan ) { const int indexMax = series.size() - 1; if ( indexMax < 0 || !lessThan( value, series.sample( indexMax ) ) ) return -1; int indexMin = 0; int n = indexMax; while ( n > 0 ) { const int half = n >> 1; const int indexMid = indexMin + half; if ( lessThan( value, series.sample( indexMid ) ) ) { n = half; } else { indexMin = indexMid + 1; n -= half + 1; } } return indexMin; } #endif PyQt-Qwt-1.02.02/header/qwt_series_store.h000066400000000000000000000121141377204562100203320ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ #ifndef QWT_SERIES_STORE_H #define QWT_SERIES_STORE_H #include "qwt_global.h" #include "qwt_series_data.h" /*! \brief Bridge between QwtSeriesStore and QwtPlotSeriesItem QwtAbstractSeriesStore is an abstract interface only to make it possible to isolate the template based methods ( QwtSeriesStore ) from the regular methods ( QwtPlotSeriesItem ) to make it possible to derive from QwtPlotSeriesItem without any hassle with templates. */ class QwtAbstractSeriesStore { protected: //! Destructor virtual ~QwtAbstractSeriesStore() {} //! dataChanged() indicates, that the series has been changed. #ifndef QWT_PYTHON_WRAPPER virtual void dataChanged() = 0; #else virtual void dataChanged() {}; #endif /*! Set a the "rectangle of interest" for the stored series \sa QwtSeriesData::setRectOfInterest() */ #ifndef QWT_PYTHON_WRAPPER virtual void setRectOfInterest( const QRectF & ) = 0; #else virtual void setRectOfInterest( const QRectF & ) {}; #endif //! \return Bounding rectangle of the stored series #ifndef QWT_PYTHON_WRAPPER virtual QRectF dataRect() const = 0; #else virtual QRectF dataRect() const {return QRectF( 0.0, 0.0, -1.0, -1.0 );}; #endif //! \return Number of samples #ifndef QWT_PYTHON_WRAPPER virtual size_t dataSize() const = 0; #else virtual size_t dataSize() const {return 0;}; #endif }; /*! \brief Class storing a QwtSeriesData object QwtSeriesStore and QwtPlotSeriesItem are intended as base classes for all plot items iterating over a series of samples. Both classes share a virtual base class ( QwtAbstractSeriesStore ) to bridge between them. QwtSeriesStore offers the template based part for the plot item API, so that QwtPlotSeriesItem can be derived without any hassle with templates. */ template class QwtSeriesStore: public virtual QwtAbstractSeriesStore { public: /*! \brief Constructor The store contains no series */ explicit QwtSeriesStore(); //! Destructor ~QwtSeriesStore(); /*! Assign a series of samples \param series Data \warning The item takes ownership of the data object, deleting it when its not used anymore. */ void setData( QwtSeriesData *series ); //! \return the the series data QwtSeriesData *data(); //! \return the the series data const QwtSeriesData *data() const; /*! \param index Index \return Sample at position index */ T sample( int index ) const; /*! \return Number of samples of the series \sa setData(), QwtSeriesData::size() */ virtual size_t dataSize() const; /*! \return Bounding rectangle of the series or an invalid rectangle, when no series is stored \sa QwtSeriesData::boundingRect() */ virtual QRectF dataRect() const; /*! Set a the "rect of interest" for the series \param rect Rectangle of interest \sa QwtSeriesData::setRectOfInterest() */ virtual void setRectOfInterest( const QRectF &rect ); /*! Replace a series without deleting the previous one \param series New series \return Previously assigned series */ QwtSeriesData *swapData( QwtSeriesData *series ); private: QwtSeriesData *d_series; }; template QwtSeriesStore::QwtSeriesStore(): d_series( NULL ) { } template QwtSeriesStore::~QwtSeriesStore() { delete d_series; } template inline QwtSeriesData *QwtSeriesStore::data() { return d_series; } template inline const QwtSeriesData *QwtSeriesStore::data() const { return d_series; } template inline T QwtSeriesStore::sample( int index ) const { return d_series ? d_series->sample( index ) : T(); } template void QwtSeriesStore::setData( QwtSeriesData *series ) { if ( d_series != series ) { delete d_series; d_series = series; dataChanged(); } } template size_t QwtSeriesStore::dataSize() const { if ( d_series == NULL ) return 0; return d_series->size(); } template QRectF QwtSeriesStore::dataRect() const { if ( d_series == NULL ) return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid return d_series->boundingRect(); } template void QwtSeriesStore::setRectOfInterest( const QRectF &rect ) { if ( d_series ) d_series->setRectOfInterest( rect ); } template QwtSeriesData* QwtSeriesStore::swapData( QwtSeriesData *series ) { QwtSeriesData * swappedSeries = d_series; d_series = series; return swappedSeries; } #endif PyQt-Qwt-1.02.02/mk_distinfo.py000066400000000000000000000067161377204562100162230ustar00rootroot00000000000000# This script handles the creation of the PEP 376 .dist-info directory for a # package. # # Copyright (c) 2018 Riverbank Computing Limited # # This script is distributed under the terms of the GNU General Public License # v3 as published by the Free Software Foundation. # # This script is supplied WITHOUT ANY WARRANTY; without even the implied # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. import base64 import hashlib import os import shutil import sys def error(message): """ Display an error message and terminate. """ sys.stderr.write(message + '\n') sys.exit(1) # Parse the command line. if len(sys.argv) != 4: error("usage: {0} prefix dist-info installed".format(sys.argv[0])) prefix_dir = sys.argv[1] distinfo_dir = sys.argv[2] installed_fn = sys.argv[3] # Read the list of installed files. installed_f = open(installed_fn) installed = installed_f.read().strip().split('\n') installed_f.close() # The prefix directory corresponds to DESTDIR or INSTALL_ROOT. real_distinfo_dir = prefix_dir + distinfo_dir # Remove any existing dist-info directory and create an empty one. if os.path.exists(real_distinfo_dir): try: shutil.rmtree(real_distinfo_dir) except: error("unable to delete existing {0}".format(real_distinfo_dir)) try: os.mkdir(real_distinfo_dir) except: error("unable to create {0}".format(real_distinfo_dir)) # Create the INSTALLER file. We pretend that pip was the installer. installer_fn = os.path.join(distinfo_dir, 'INSTALLER') installer_f = open(prefix_dir + installer_fn, 'w') installer_f.write('pip\n') installer_f.close() installed.append(installer_fn) # Create the METADATA file. METADATA = '''Metadata-Version: 1.1 Name: {0} Version: {1} ''' distinfo_path, distinfo_base = os.path.split(distinfo_dir) pkg_name, version = os.path.splitext(distinfo_base)[0].split('-') metadata_fn = os.path.join(distinfo_dir, 'METADATA') metadata_f = open(prefix_dir + metadata_fn, 'w') metadata_f.write(METADATA.format(pkg_name, version)) metadata_f.close() installed.append(metadata_fn) # Create the RECORD file. record_fn = os.path.join(distinfo_dir, 'RECORD') record_f = open(prefix_dir + record_fn, 'w') for name in installed: native_name = prefix_dir + name.replace('/', os.sep) if os.path.isdir(native_name): all_fns = [] for root, dirs, files in os.walk(native_name): # Reproducable builds. dirs.sort() files.sort() for f in files: all_fns.append(os.path.join(root, f).replace(os.sep, '/')) if '__pycache__' in dirs: dirs.remove('__pycache__') else: all_fns = [prefix_dir + name] for fn in all_fns: real_distinfo_path = prefix_dir + distinfo_path if fn.startswith(real_distinfo_path): fn_name = fn[len(real_distinfo_path) + 1:].replace('\\', '/') elif fn.startswith(prefix_dir + sys.prefix): fn_name = os.path.relpath( fn, real_distinfo_path).replace('\\', '/') else: fn_name = fn[len(prefix_dir):] fn_f = open(fn, 'rb') data = fn_f.read() fn_f.close() digest = base64.urlsafe_b64encode( hashlib.sha256(data).digest()).rstrip(b'=').decode('ascii') record_f.write( '{0},sha256={1},{2}\n'.format(fn_name, digest, len(data))) record_f.write('{0}/RECORD,,\n'.format(distinfo_base)) record_f.close() PyQt-Qwt-1.02.02/project.py000066400000000000000000000041341377204562100153530ustar00rootroot00000000000000"""The build configuration file for PyQt-Qwt, used by sip.""" import os from os.path import abspath, join from sipbuild import Option from pyqtbuild import PyQtBindings, PyQtProject import PyQt5 class QwtProject(PyQtProject): """The Qwt Project class.""" def __init__(self): super().__init__() self.bindings_factories = [QwtBindings] def update(self, tool): """Allows SIP to find PyQt5 .sip files.""" super().update(tool) self.sip_include_dirs.append(join(PyQt5.__path__[0], 'bindings')) class QwtBindings(PyQtBindings): """The Qwt Bindings class.""" def __init__(self, project): super().__init__(project, name='Qwt', sip_file='Qwt_Qt5.sip', qmake_QT=['widgets']) def get_options(self): """Our custom options that a user can pass to sip-build.""" options = super().get_options() options += [ Option('qwt_incdir', help='the directory containing the Qwt header file', metavar='DIR'), Option('qwt_featuresdir', help='the directory containing the qwt.prf features file', metavar='DIR'), Option('qwt_libdir', help='the directory containing the Qwt library', metavar='DIR'), Option('qwt_lib', help='the Qwt library', metavar='LIB', default='qwt'), ] return options def apply_user_defaults(self, tool): """Apply values from user-configurable options.""" if self.qwt_incdir is not None: self.include_dirs.append(self.qwt_incdir) if self.qwt_featuresdir is not None: os.environ['QMAKEFEATURES'] = abspath(self.qsci_features_dir) if self.qwt_libdir is not None: self.library_dirs.append(self.qwt_libdir) if self.qwt_lib is not None: self.libraries.append(self.qwt_lib) self.define_macros.append('QWT_PYTHON_WRAPPER') super().apply_user_defaults(tool) PyQt-Qwt-1.02.02/pyproject.toml000066400000000000000000000012071377204562100162450ustar00rootroot00000000000000[build-system] requires = ["sip >=5", "PyQt-builder", "PyQt5"] build-backend = "sipbuild.api" [tool.sip.metadata] name = "PyQt-Qwt" version = "1.02.02" summary = "Python wrapper for Qwt6" description-file = "README.md" description-content-type = "text/markdown" home-page = "https://github.com/GauiStori/PyQt-Qwt" maintainer = "Gudjon I. Gudjonsson" maintainer-email = "gudjon@gudjon.org" license = "Qwt License 1.0" requires-dist = "PyQt5" [tool.sip.project] sip-files-dir = "sip" sdist-excludes = [ "version.sip", ".git/*", ".git/*/*", ".git/*/*/*", ".git/*/*/*/*", ".git/*/*/*/*/*", ".git/*/*/*/*/*/*", ".git/*/*/*/*/*/*/*" ] PyQt-Qwt-1.02.02/qt4examples/000077500000000000000000000000001377204562100156005ustar00rootroot00000000000000PyQt-Qwt-1.02.02/qt4examples/animation.py000066400000000000000000000136521377204562100201400ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import Qt, QTime, QPointF, QSize from PyQt4.QtGui import QColor, QTransform, QApplication, QFrame, QPolygonF class Curve(Qwt.QwtPlotCurve): def __init__(self): Qwt.QwtPlotCurve.__init__(self) self.d_transform = QTransform() def setTransformation(self, transform ): self.d_transform = transform; class Curve1(Curve): def __init__(self): Curve.__init__(self) self.setPen( QColor( 150, 150, 200 ), 2 ) self.setStyle( Qwt.QwtPlotCurve.Lines ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setSplineSize( 150 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.XCross ) symbol.setPen( Qt.yellow ) symbol.setSize( 7 ) self.setSymbol( symbol ) # somewhere to the left self.transform = QTransform() self.transform.scale( 1.5, 1.0 ); self.transform.translate( 1.5, 3.0 ); self.setTransformation( self.transform ) def points(self, phase ): pnts = QPolygonF() numSamples = 15; for i in range(numSamples): v = 6.28 * i / ( numSamples - 1 ) pnts += QPointF( math.sin( v - phase ), v ) return pnts def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Curve2(Curve): def __init__(self): Curve.__init__(self) self.setStyle( Qwt.QwtPlotCurve.Sticks ); self.setPen( QColor( 200, 150, 50 ) ); self.setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Ellipse,QColor( Qt.gray ), QColor( Qt.yellow ), QSize( 5, 5 ) ) ) def points(self, phase ): points = QPolygonF() numSamples = 50 for i in range(numSamples): v = 10.0 * i / ( numSamples - 1 ) points += QPointF( v, math.cos( 3.0 * ( v + phase ) ) ) return points def updateSamples( self, phase ): a=self.points(phase) b= self.d_transform.map(a) self.setSamples( b ) class Curve3(Curve): def __init__(self): Curve.__init__(self) self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( QColor( 100, 200, 150 ), 2 ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setFitMode( Qwt.QwtSplineCurveFitter.ParametricSpline ) curveFitter.setSplineSize( 200 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) # somewhere in the top right corner transform = QTransform() transform.translate( 7.0, 7.5 ) transform.scale( 2.0, 2.0 ) self.setTransformation( transform ) def points( self, phase ): points = QPolygonF() numSamples = 9 for i in range(numSamples): v = i * 2.0 * 3.14159 / ( numSamples - 1 ) points += QPointF( math.sin( v - phase ), math.cos( 3.0 * ( v + phase ) ) ) return points; def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Curve4(Curve): def __init__(self): Curve.__init__(self) self.d_points = QPolygonF() self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( Qt.red, 2 ) self.initSamples() # somewhere in the center transform = QTransform() transform.translate( 7.0, 3.0 ) transform.scale( 1.5, 1.5 ) self.setTransformation( transform ) def points(self, phase ): speed = 0.05 s = speed * math.sin( phase ); c = math.sqrt( 1.0 - s * s ); for i in range(len(self.d_points)): p = self.d_points[i] u = p.x() v = p.y() self.d_points[i].setX( u * c - v * s ) self.d_points[i].setY( v * c + u * s ) return self.d_points; def initSamples(self): numSamples = 15 for i in range(numSamples): angle = i * ( 2.0 * 3.14159 / ( numSamples - 1 ) ); p= QPointF( math.cos( angle ), math.sin( angle ) ); if ( i % 2 ): p *= 0.4 self.d_points += p def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Plot( Qwt.QwtPlot): def __init__(self,parent=None): Qwt.QwtPlot.__init__(self, parent) self.d_time = QTime() self.d_curves = [] self.setAutoReplot( False ) self.setTitle( "Animated Curves" ) # hide all axes for axis in range(Qwt.QwtPlot.axisCnt): self.enableAxis( axis, False ) #self.plotLayout.setCanvasMargin( 10 ) self.d_curves.append(Curve1()) self.d_curves.append(Curve2()) self.d_curves.append(Curve3()) self.d_curves.append(Curve4()) self.updateCurves() for i in range(len(self.d_curves)): self.d_curves[i].attach( self ) self.d_time.start() self.startTimer( 40 ) def timerEvent( self, event ): self.updateCurves() self.replot() def updateCurves(self): speed = 2 * 3.14159 / 25000.0 # a cycle every 25 seconds phase = self.d_time.elapsed() * speed for i in range(len(self.d_curves)): self.d_curves[i].updateSamples( phase ) #QApplication a( argc, argv ); if __name__ == '__main__': a = QApplication(sys.argv) plot = Plot() #if USE_OPENGL #canvas = Qwt.QwtPlotGLCanvas() #canvas.setFrameStyle( Qwt.QwtPlotGLCanvas.NoFrame ) #else canvas = Qwt.QwtPlotCanvas(); canvas.setFrameStyle( QFrame.NoFrame ); canvas.setPaintAttribute( Qwt.QwtPlotCanvas.BackingStore, False ) #endif plot.setCanvas( canvas ) plot.setCanvasBackground( QColor( 30, 30, 50 ) ) plot.resize( 400, 400 ) plot.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/barchart.py000066400000000000000000000124511377204562100177430ustar00rootroot00000000000000#!/usr/bin/python import sys #import Qwt from PyQt4 import Qwt sys.path.append('../sip/') import math, random from PyQt4.QtCore import Qt, QTime, QPointF, QSize from PyQt4.QtGui import QColor, QTransform, QPalette, QApplication, QMainWindow, QFrame, QWidget, QToolBar, QComboBox, QSizePolicy, QToolButton class BarChart( Qwt.QwtPlot ): def __init__(self, parent): Qwt.QwtPlot.__init__(self, parent) self.setAutoFillBackground( True ) self.setPalette( QPalette(Qt.white) ) #self.canvas.setPalette( QColor( "LemonChiffon" ) ) #FIXME #self.canvas.setPalette( QColor( "LemonChiffon" ) ) #FIXME self.setTitle( "Bar Chart" ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Whatever" ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Whatever" ) self.d_barChartItem = Qwt.QwtPlotMultiBarChart( "Bar Chart " ) self.d_barChartItem.setLayoutPolicy( Qwt.QwtPlotMultiBarChart.AutoAdjustSamples ) self.d_barChartItem.setSpacing( 20 ) self.d_barChartItem.setMargin( 3 ) self.d_barChartItem.attach( self ) self.insertLegend( Qwt.QwtLegend() ) self.populate() self.setOrientation( 0 ) self.setAutoReplot( True ) def populate(self): #colors = ["DarkOrchid", "SteelBlue", "Gold"] colors = [Qt.magenta, Qt.blue, Qt.yellow] numSamples = 5 numBars = len(colors ) titles = [] for i in range(numBars): titles.append(Qwt.QwtText("Bar %d"%i)) self.d_barChartItem.setBarTitles( titles ) self.d_barChartItem.setLegendIconSize( QSize( 10, 14 ) ) for i in range(numBars): symbol = Qwt.QwtColumnSymbol( Qwt.QwtColumnSymbol.Box ) symbol.setLineWidth( 2 ) symbol.setFrameStyle( Qwt.QwtColumnSymbol.Raised ) symbol.setPalette( QPalette( colors[i] ) ) #self.d_barChartItem.setSymbol( i, symbol ) #FIXME Segfaults self.series = [] for i in range(numSamples): values = [] for j in range(numBars): values.append( 2.0 + random.randint(0, 8) % 8 ) self.series.append(values) print(self.series) self.d_barChartItem.setSamples( self.series ) def setMode( self, mode ): if ( mode == 0 ): self.d_barChartItem.setStyle( Qwt.QwtPlotMultiBarChart.Grouped ) else: self.d_barChartItem.setStyle( Qwt.QwtPlotMultiBarChart.Stacked ) def setOrientation( self, orientation ): axis1 = Qwt.QwtPlot.Axis() axis2 = Qwt.QwtPlot.Axis() if ( orientation == 0 ): axis1 = Qwt.QwtPlot.xBottom axis2 = Qwt.QwtPlot.yLeft self.d_barChartItem.setOrientation( Qt.Vertical ) else: axis1 = Qwt.QwtPlot.yLeft axis2 = Qwt.QwtPlot.xBottom self.d_barChartItem.setOrientation( Qt.Horizontal ) self.setAxisScale( axis1, 0, len(self.series) -1, 1.0 ) #self.setAxisScale( axis1, 0, self.d_barChartItem.dataSize() - 1, 1.0 ) self.setAxisAutoScale( axis2 ) self.scaleDraw1 = self.axisScaleDraw( axis1 ) self.scaleDraw1.enableComponent( Qwt.QwtScaleDraw.Backbone, False ) self.scaleDraw1.enableComponent( Qwt.QwtScaleDraw.Ticks, False ) self.scaleDraw2 = self.axisScaleDraw( axis2 ) self.scaleDraw2.enableComponent( Qwt.QwtScaleDraw.Backbone, True ) self.scaleDraw2.enableComponent( Qwt.QwtScaleDraw.Ticks, True ) self.plotLayout().setAlignCanvasToScale( axis1, True ) self.plotLayout().setAlignCanvasToScale( axis2, False ) self.plotLayout().setCanvasMargin( 0 ) self.updateCanvasMargins() self.replot() def exportChart(self): renderer = Qwt.QwtPlotRenderer() renderer.exportTo( self, "barchart.pdf" ) class MainWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.d_chart = BarChart( self ) self.setCentralWidget( self.d_chart ) self.toolBar = QToolBar( self ) self.typeBox = QComboBox( self.toolBar ) self.typeBox.addItem( "Grouped" ) self.typeBox.addItem( "Stacked" ) self.typeBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.orientationBox = QComboBox( self.toolBar ) self.orientationBox.addItem( "Vertical" ) self.orientationBox.addItem( "Horizontal" ) self.orientationBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.btnExport = QToolButton(self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.btnExport.clicked.connect(self.d_chart.exportChart) self.toolBar.addWidget( self.typeBox ) self.toolBar.addWidget( self.orientationBox ) self.toolBar.addWidget( self.btnExport ) self.addToolBar( self.toolBar ) self.d_chart.setMode( self.typeBox.currentIndex() ) self.typeBox.currentIndexChanged['int'].connect(self.d_chart.setMode ) self.d_chart.setOrientation( self.orientationBox.currentIndex() ) self.orientationBox.currentIndexChanged['int'].connect(self.d_chart.setOrientation) a = QApplication(sys.argv) m = MainWindow() m.resize( 600, 400 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/bode.py000066400000000000000000000351161377204562100170710ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import Qt, QSize from PyQt4.QtGui import QColor, QPixmap, QFont, QIcon, QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication #from PyQt4.QtPrintSupport import QPrintDialog, QPrinter def logSpace(size, xmin, xmax ): array = []#np.zeros(0,float) for i in range(size): array.append(0.0) if ( ( xmin <= 0.0 ) or ( xmax <= 0.0 ) or ( size <= 0 ) ): return array; imax = size - 1; array[0] = xmin; array[imax] = xmax; lxmin = math.log( xmin ) lxmax = math.log( xmax ) lstep = ( lxmax - lxmin ) / imax for i in range(imax): array[i] = math.exp( lxmin + i * lstep ) return array print_xpm = ["32 32 12 1", "a c #ffffff", "h c #ffff00", "c c #ffffff", "f c #dcdcdc", "b c #c0c0c0", "j c #a0a0a4", "e c #808080", "g c #808000", "d c #585858", "i c #00ff00", "# c #000000", ". c None", "................................", "................................", "...........###..................", "..........#abb###...............", ".........#aabbbbb###............", ".........#ddaaabbbbb###.........", "........#ddddddaaabbbbb###......", ".......#deffddddddaaabbbbb###...", "......#deaaabbbddddddaaabbbbb###", ".....#deaaaaaaabbbddddddaaabbbb#", "....#deaaabbbaaaa#ddedddfggaaad#", "...#deaaaaaaaaaa#ddeeeeafgggfdd#", "..#deaaabbbaaaa#ddeeeeabbbbgfdd#", ".#deeefaaaaaaa#ddeeeeabbhhbbadd#", "#aabbbeeefaaa#ddeeeeabbbbbbaddd#", "#bbaaabbbeee#ddeeeeabbiibbadddd#", "#bbbbbaaabbbeeeeeeabbbbbbaddddd#", "#bjbbbbbbaaabbbbeabbbbbbadddddd#", "#bjjjjbbbbbbaaaeabbbbbbaddddddd#", "#bjaaajjjbbbbbbaaabbbbadddddddd#", "#bbbbbaaajjjbbbbbbaaaaddddddddd#", "#bjbbbbbbaaajjjbbbbbbddddddddd#.", "#bjjjjbbbbbbaaajjjbbbdddddddd#..", "#bjaaajjjbbbbbbjaajjbddddddd#...", "#bbbbbaaajjjbbbjbbaabdddddd#....", "###bbbbbbaaajjjjbbbbbddddd#.....", "...###bbbbbbaaajbbbbbdddd#......", "......###bbbbbbjbbbbbddd#.......", ".........###bbbbbbbbbdd#........", "............###bbbbbbd#.........", "...............###bbb#..........", "..................###..........."] zoom_xpm = ["32 32 8 1", "# c #000000", "b c #c0c0c0", "a c #ffffff", "e c #585858", "d c #a0a0a4", "c c #0000ff", "f c #00ffff", ". c None", "..######################........", ".#a#baaaaaaaaaaaaaaaaaa#........", "#aa#baaaaaaaaaaaaaccaca#........", "####baaaaaaaaaaaaaaaaca####.....", "#bbbbaaaaaaaaaaaacccaaa#da#.....", "#aaaaaaaaaaaaaaaacccaca#da#.....", "#aaaaaaaaaaaaaaaaaccaca#da#.....", "#aaaaaaaaaabe###ebaaaaa#da#.....", "#aaaaaaaaa#########aaaa#da#.....", "#aaaaaaaa###dbbbb###aaa#da#.....", "#aaaaaaa###aaaaffb###aa#da#.....", "#aaaaaab##aaccaaafb##ba#da#.....", "#aaaaaae#daaccaccaad#ea#da#.....", "#aaaaaa##aaaaaaccaab##a#da#.....", "#aaaaaa##aacccaaaaab##a#da#.....", "#aaaaaa##aaccccaccab##a#da#.....", "#aaaaaae#daccccaccad#ea#da#.....", "#aaaaaab##aacccaaaa##da#da#.....", "#aaccacd###aaaaaaa###da#da#.....", "#aaaaacad###daaad#####a#da#.....", "#acccaaaad##########da##da#.....", "#acccacaaadde###edd#eda#da#.....", "#aaccacaaaabdddddbdd#eda#a#.....", "#aaaaaaaaaaaaaaaaaadd#eda##.....", "#aaaaaaaaaaaaaaaaaaadd#eda#.....", "#aaaaaaaccacaaaaaaaaadd#eda#....", "#aaaaaaaaaacaaaaaaaaaad##eda#...", "#aaaaaacccaaaaaaaaaaaaa#d#eda#..", "########################dd#eda#.", "...#dddddddddddddddddddddd##eda#", "...#aaaaaaaaaaaaaaaaaaaaaa#.####", "...########################..##."] class Plot( Qwt.QwtPlot): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent) self.setAutoReplot( False ) self.setTitle( "Frequency Response of a Second-Order System" ) canvas = Qwt.QwtPlotCanvas() canvas.setBorderRadius( 10 ) self.setCanvas( canvas ) self.setCanvasBackground( QColor( "MidnightBlue" ) ) # legend legend = Qwt.QwtLegend() self.insertLegend( legend, Qwt.QwtPlot.BottomLegend ) # grid grid = Qwt.QwtPlotGrid() grid.enableXMin( True ) grid.setMajorPen( Qt.white, 0, Qt.DotLine ) grid.setMinorPen( Qt.gray, 0 , Qt.DotLine ) grid.attach( self ) # axes self.enableAxis( Qwt.QwtPlot.yRight ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Normalized Frequency" ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Amplitude [dB]" ) self.setAxisTitle( Qwt.QwtPlot.yRight, "Phase [deg]" ) self.setAxisMaxMajor( Qwt.QwtPlot.xBottom, 6 ) self.setAxisMaxMinor( Qwt.QwtPlot.xBottom, 9 ) self.setAxisScaleEngine( Qwt.QwtPlot.xBottom, Qwt.QwtLogScaleEngine() ) # curves self.d_curve1 = Qwt.QwtPlotCurve( "Amplitude" ) self.d_curve1.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) self.d_curve1.setPen( Qt.yellow ) self.d_curve1.setLegendAttribute( Qwt.QwtPlotCurve.LegendShowLine ) self.d_curve1.setYAxis( Qwt.QwtPlot.yLeft ) self.d_curve1.attach( self ) self.d_curve2 = Qwt.QwtPlotCurve( "Phase" ) self.d_curve2.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) self.d_curve2.setPen( Qt.cyan ) self.d_curve2.setLegendAttribute( Qwt.QwtPlotCurve.LegendShowLine ) self.d_curve2.setYAxis( Qwt.QwtPlot.yRight ) self.d_curve2.attach( self ) # marker self.d_marker1 = Qwt.QwtPlotMarker() self.d_marker1.setValue( 0.0, 0.0 ) self.d_marker1.setLineStyle( Qwt.QwtPlotMarker.VLine ) self.d_marker1.setLabelAlignment( Qt.AlignRight | Qt.AlignBottom ) self.d_marker1.setLinePen( Qt.green, 0, Qt.DashDotLine ) self.d_marker1.attach( self ) self.d_marker2 = Qwt.QwtPlotMarker() self.d_marker2.setLineStyle( Qwt.QwtPlotMarker.HLine ) self.d_marker2.setLabelAlignment( Qt.AlignRight | Qt.AlignBottom ) self.d_marker2.setLinePen( QColor( 200, 150, 0 ), 0, Qt.DashDotLine ) self.d_marker2.setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Diamond,QColor( Qt.yellow ), QColor( Qt.green ), QSize( 8, 8 ) ) ) self.d_marker2.attach( self ) self.setDamp( 0 ) self.setAutoReplot( True ) def showData(self, frequency, amplitude, phase, count ): self.d_curve1.setSamples( frequency, amplitude) self.d_curve2.setSamples( frequency, phase) def showPeak( self, freq, amplitude ): label = "Peak: %.3g dB"%amplitude text = Qwt.QwtText( label ) text.setFont( QFont( "Helvetica", 10, QFont.Bold ) ) text.setColor( QColor( 200, 150, 0 ) ) self.d_marker2.setValue( freq, amplitude ) self.d_marker2.setLabel( text ) def show3dB( self, freq ): label = "-3 dB at f = %.3g"%freq text = Qwt.QwtText( label ) text.setFont( QFont( "Helvetica", 10, QFont.Bold ) ) text.setColor( Qt.green ) self.d_marker1.setValue( freq, 0.0 ) self.d_marker1.setLabel( text ) #re-calculate frequency response def setDamp( self, damping ): doReplot = self.autoReplot() self.setAutoReplot( False ) ArraySize = 200; #amplitude = np.zeros(ArraySize, float) amplitude = [] for i in range(ArraySize): amplitude.append(0.0) #phase = np.zeros(ArraySize, float) phase = [] for i in range(ArraySize): phase.append(0.0) # build frequency vector with logarithmic division frequency = logSpace( ArraySize, 0.01, 100 ) i3 = 1 fmax = 1 amax = -1000.0 for i in range(ArraySize): f = frequency[i]; g = complex( 1.0 ) / complex( 1.0 - f * f, 2.0 * damping * f ) amplitude[i] = 20.0 * math.log10( math.sqrt( g.real * g.real + g.imag * g.imag ) ) phase[i] = math.atan2( g.imag, g.real ) * ( 180.0 / 3.14159)#M_PI ) if ( ( i3 <= 1 ) and ( amplitude[i] < -3.0 ) ): i3 = i if ( amplitude[i] > amax ): amax = amplitude[i]; fmax = frequency[i]; f3 = frequency[i3] - ( frequency[i3] - frequency[i3 - 1] ) / ( amplitude[i3] - amplitude[i3 -1] ) * ( amplitude[i3] + 3 ) self.showPeak( fmax, amax ) self.show3dB( f3 ) self.showData( frequency, amplitude, phase, ArraySize ) self.setAutoReplot( doReplot ) self.replot() class Zoomer(Qwt.QwtPlotZoomer): def __init__(self, xAxis, yAxis, canvas ): Qwt.QwtPlotZoomer.__init__(self, xAxis, yAxis, canvas ) self.setTrackerMode( Qwt.QwtPicker.AlwaysOff ) self.setRubberBand( Qwt.QwtPicker.NoRubberBand ) # RightButton: zoom out by 1 # Ctrl+RightButton: zoom out to full size self.setMousePattern( Qwt.QwtEventPattern.MouseSelect2, Qt.RightButton, Qt.ControlModifier ) self.setMousePattern( Qwt.QwtEventPattern.MouseSelect3, Qt.RightButton ) class MainWindow( QMainWindow ): def __init__(self, *args): QMainWindow.__init__(self, *args) self.d_plot = Plot( self ) margin = 5; self.d_plot.setContentsMargins( margin, margin, margin, 0 ) self.setContextMenuPolicy( Qt.NoContextMenu ) self.d_zoomer=[None,None] self.d_zoomer[0] = Zoomer( Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, self.d_plot.canvas() ) self.d_zoomer[0].setRubberBand( Qwt.QwtPicker.RectRubberBand ) self.d_zoomer[0].setRubberBandPen( QColor( Qt.green ) ) self.d_zoomer[0].setTrackerMode( Qwt.QwtPicker.ActiveOnly ) self.d_zoomer[0].setTrackerPen( QColor( Qt.white ) ) self.d_zoomer[1] = Zoomer( Qwt.QwtPlot.xTop, Qwt.QwtPlot.yRight, self.d_plot.canvas() ) self.d_panner = Qwt.QwtPlotPanner( self.d_plot.canvas() ) self.d_panner.setMouseButton( Qt.MidButton ) self.d_picker = Qwt.QwtPlotPicker( Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPlotPicker.CrossRubberBand, Qwt.QwtPicker.AlwaysOn, self.d_plot.canvas() ) self.d_picker.setStateMachine( Qwt.QwtPickerDragPointMachine() ) self.d_picker.setRubberBandPen( QColor( Qt.green ) ) self.d_picker.setRubberBand( Qwt.QwtPicker.CrossRubberBand ) self.d_picker.setTrackerPen( QColor( Qt.white ) ) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.btnZoom = QToolButton( self.toolBar ) self.btnZoom.setText( "Zoom" ) self.btnZoom.setIcon( QIcon(QPixmap( zoom_xpm ) )) self.btnZoom.setCheckable( True ) self.btnZoom.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnZoom ) self.btnZoom.toggled.connect(self.enableZoomMode) self.btnPrint = QToolButton( self.toolBar ) self.btnPrint.setText( "Print" ) self.btnPrint.setIcon( QIcon(QPixmap( print_xpm ) ) ) self.btnPrint.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnPrint ) self.btnPrint.clicked.connect(self.mprint) self.btnExport = QToolButton( self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setIcon( QIcon(QPixmap( print_xpm ) ) ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnExport ) self.btnExport.clicked.connect(self.exportDocument) self.toolBar.addSeparator() hBox = QWidget( self.toolBar ) self.layout = QHBoxLayout( hBox ) self.layout.setSpacing( 0 ) self.layout.addWidget( QWidget( hBox ), 10 ) # spacer self.layout.addWidget( QLabel( "Damping Factor", hBox ), 0 ) self.layout.addSpacing( 10 ) self.cntDamp = Qwt.QwtCounter( hBox ) self.cntDamp.setRange( 0.0, 5.0 ) self.cntDamp.setSingleStep( 0.01 ) self.cntDamp.setValue( 0.0 ) self.layout.addWidget( self.cntDamp, 0 ) self.toolBar.addWidget( hBox ) self.addToolBar( self.toolBar ) self.statusBar() self.enableZoomMode( False ) self.showInfo("humm") self.cntDamp.valueChanged['double'].connect(self.d_plot.setDamp) self.d_picker.moved.connect(self.moved) #connect( d_picker, SIGNAL( moved( const QPoint & ) ), SLOT( moved( const QPoint & ) ) ) #connect( d_picker, SIGNAL( selected( const QPolygon & ) ), SLOT( selected( const QPolygon & ) ) ) def mprint(self): printer = QPrinter( QPrinter.HighResolution ) docName = "Humm" #self.d_plot.title().text() #if ( not docName.isEmpty() ): #docName.replace ( QRegExp ( QString.fromLatin1 ( "\n" ) ), tr ( " -- " ) ) printer.setDocName ( docName ) printer.setCreator( "Bode example" ) printer.setOrientation( QPrinter.Landscape ) dialog = QPrintDialog( printer ) if ( dialog.exec_() ): renderer = Qwt.QwtPlotRenderer() if ( printer.colorMode() == QPrinter.GrayScale ): renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasFrame ) renderer.setLayoutFlag( Qwt.QwtPlotRenderer.FrameWithScales ) renderer.renderTo( self.d_plot, printer ) def exportDocument(self): print("Not implemented") #renderer = Qwt.QwtPlotRenderer() #renderer.exportTo( self.d_plot, "bode.pdf" ) def enableZoomMode( self, on ): self.d_panner.setEnabled( on ) self.d_zoomer[0].setEnabled( on ) self.d_zoomer[0].zoom( 0 ) self.d_zoomer[1].setEnabled( on ) self.d_zoomer[1].zoom( 0 ) self.d_picker.setEnabled( not on ) #self.showInfo() def showInfo( self, text ): if ( text=="" ): if ( self.d_picker.rubberBand() ): text = "Cursor Pos: Press left mouse button in plot region" else: text = "Zoom: Press mouse button and drag" #self.statusBar.showMessage( text ) def moved( self, pos ): info = "Freq=%g, Ampl=%g, Phase=%g"%( self.d_plot.invTransform( Qwt.QwtPlot.xBottom, pos.x() ), self.d_plot.invTransform( Qwt.QwtPlot.yLeft, pos.y() ), self.d_plot.invTransform( Qwt.QwtPlot.yRight, pos.y() )) self.showInfo( info ) def selected(self): self.showInfo("selected") a = QApplication(sys.argv) m = MainWindow() m.resize( 540, 400 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/radio.py000066400000000000000000000243331377204562100172550ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import pyqtSignal, Qt, QSize, QBasicTimer from PyQt4.QtGui import (QColor, QPixmap, QFont, QIcon, QPalette, QLinearGradient, QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QSizePolicy, QVBoxLayout, QFrame ) #from PyQt4.QtPrintSupport import QPrintDialog, QPrinter M_PI = 3.14159 class Knob(QWidget): def __init__(self, title, min, max, parent ): QWidget.__init__(self, parent) self.d_knob = Qwt.QwtKnob( self ) self.d_knob.setScale( min, max ) self.d_knob.setTotalSteps( 0 ) # disable self.d_knob.setScaleMaxMajor( 10 ) self.d_knob.setKnobStyle( Qwt.QwtKnob.Raised ) self.d_knob.setKnobWidth( 50 ) self.d_knob.setBorderWidth( 2 ) self.d_knob.setMarkerStyle( Qwt.QwtKnob.Notch ) self.d_knob.setMarkerSize( 8 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MinorTick, 4 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MediumTick, 4 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MajorTick, 6 ) self.d_label = QLabel( title, self ) self.d_label.setAlignment( Qt.AlignTop | Qt.AlignHCenter ) self.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding ) def sizeHint(self): sz1 = self.d_knob.sizeHint() sz2 = self.d_label.sizeHint() w = max( sz1.width(), sz2.width() ) h = sz1.height() + sz2.height() off = math.ceil( self.d_knob.scaleDraw().extent( self.d_knob.font() ) ) off -= 10 # spacing return QSize( w, h - off ) def setValue( self, value ): self.d_knob.setValue( value ) def value(self): return self.d_knob.value() def resizeEvent( self, e ): sz = e.size() h = self.d_label.sizeHint().height() self.d_label.setGeometry( 0, sz.height() - h, sz.width(), h ) h = self.d_knob.sizeHint().height() off = math.ceil( self.d_knob.scaleDraw().extent( self.d_knob.font() ) ) off -= 10 # spacing self.d_knob.setGeometry( 0, self.d_label.pos().y() - h + off, sz.width(), h ) class Thermo(QWidget): def __init__( self, title, parent ): QWidget.__init__(self, parent) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setPipeWidth( 6 ) self.d_thermo.setScale( -40, 10 ) self.d_thermo.setFillBrush( Qt.green ) self.d_thermo.setAlarmBrush( Qt.red ) self.d_thermo.setAlarmLevel( 0.0 ) self.d_thermo.setAlarmEnabled( True ) label = QLabel( title, self ) label.setAlignment( Qt.AlignTop | Qt.AlignLeft ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) self.layout.setSpacing( 0 ) self.layout.addWidget( self.d_thermo, 10 ) self.layout.addWidget( label ) def setValue( self, value ): self.d_thermo.setValue( value ) class AmpFrame( QFrame ): def __init__(self, p): QFrame.__init__( self, p ) self.phs = 0 self.d_knbVolume = Knob( "Volume", 0.0, 10.0, self ) self.d_knbBalance = Knob( "Balance", -10.0, 10.0, self ) self.d_knbTreble = Knob( "Treble", -10.0, 10.0, self ) self.d_knbBass = Knob( "Bass", -10.0, 10.0, self ) self.d_thmLeft = Thermo( "Left [dB]", self ) self.d_thmRight = Thermo( "Right [dB]", self ) self.layout = QHBoxLayout( self ) self.layout.setSpacing( 0 ) #self.layout.setMargin( 10 ) self.layout.addWidget( self.d_knbVolume ) self.layout.addWidget( self.d_knbBalance) self.layout.addWidget( self.d_knbTreble) self.layout.addWidget( self.d_knbBass ) self.layout.addSpacing( 20 ) self.layout.addStretch( 10 ) self.layout.addWidget( self.d_thmLeft ) self.layout.addSpacing( 10 ) self.layout.addWidget( self.d_thmRight ) self.d_knbVolume.setValue( 7.0 ) self.startTimer( 50 ) self.d_master = 0 def timerEvent( self, event ): #self.phs = 0.0 # This amplifier generates its own input signal... sig_bass = ( 1.0 + 0.1 * self.d_knbBass.value() ) * math.sin( 13.0 * self.phs ) sig_mid_l = math.sin( 17.0 * self.phs ) sig_mid_r = math.cos( 17.5 * self.phs ) sig_trbl_l = 0.5 * ( 1.0 + 0.1 * self.d_knbTreble.value() ) * math.sin( 35.0 * self.phs ) sig_trbl_r = 0.5 * ( 1.0 + 0.1 * self.d_knbTreble.value() ) * math.sin( 34.0 * self.phs ) sig_l = 0.05 * self.d_master * self.d_knbVolume.value() * ( sig_bass + sig_mid_l + sig_trbl_l )*( sig_bass + sig_mid_l + sig_trbl_l ) sig_r = 0.05 * self.d_master * self.d_knbVolume.value() * ( sig_bass + sig_mid_r + sig_trbl_r )*( sig_bass + sig_mid_r + sig_trbl_r ) balance = 0.1 * self.d_knbBalance.value() if ( balance > 0 ): sig_l *= ( 1.0 - balance ) else: sig_r *= ( 1.0 + balance ) if ( sig_l > 0.01 ): sig_l = 20.0 * math.log10( sig_l ) else: sig_l = -40.0 if ( sig_r > 0.01 ): sig_r = 20.0 * math.log10( sig_r ) else: sig_r = - 40.0 self.d_thmLeft.setValue( sig_l ) self.d_thmRight.setValue( sig_r ) self.phs += M_PI / 100 if ( self.phs > M_PI ): self.phs = 0 def setMaster( self, v ): self.d_master = v class TuningThermo(QWidget): def __init__(self, parent): QWidget.__init__( self, parent ) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setOrientation( Qt.Horizontal ) self.d_thermo.setScalePosition( Qwt.QwtThermo.NoScale ) self.d_thermo.setScale( 0.0, 1.0 ) self.d_thermo.setFillBrush( Qt.green ) self.label = QLabel( "Tuning", self ) self.label.setAlignment( Qt.AlignCenter ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) FIXME self.layout.addWidget( self.d_thermo ) self.layout.addWidget( self.label ) self.setFixedWidth( 3 * self.label.sizeHint().width() ) def setValue( self, value ): self.d_thermo.setValue( value ) class TunerFrame( QWidget ): fieldChanged = pyqtSignal(float) def __init__(self, parent): QWidget.__init__(self, parent ) self.freqMin = 87.5 self.freqMax = 108 self.d_sliderFrequency = Qwt.QwtSlider( self ) self.d_sliderFrequency.setOrientation( Qt.Horizontal ) self.d_sliderFrequency.setScalePosition( Qwt.QwtSlider.TrailingScale ) self.d_sliderFrequency.setScale( self.freqMin, self.freqMax ) #self.d_sliderFrequency.setTotalSteps( math.round( ( self.freqMax - self.freqMin ) / 0.01 ) ) FIXME self.d_sliderFrequency.setTotalSteps( int(math.ceil( ( self.freqMax - self.freqMin ) / 0.01 ) ) ) self.d_sliderFrequency.setSingleSteps( 1 ) self.d_sliderFrequency.setPageSteps( 10 ) self.d_sliderFrequency.setScaleMaxMinor( 5 ) self.d_sliderFrequency.setScaleMaxMajor( 12 ) self.d_sliderFrequency.setHandleSize( QSize( 80, 20 ) ) self.d_sliderFrequency.setBorderWidth( 1 ) self.d_thermoTune = TuningThermo( self ) self.d_wheelFrequency = Qwt.QwtWheel( self ) self.d_wheelFrequency.setMass( 0.5 ) self.d_wheelFrequency.setRange( 87.5, 108 ) self.d_wheelFrequency.setSingleStep( 0.01 ) self.d_wheelFrequency.setPageStepCount( 10 ) self.d_wheelFrequency.setTotalAngle( 3600.0 ) self.d_wheelFrequency.setFixedHeight( 30 ) self.d_wheelFrequency.valueChanged['double'].connect(self.adjustFreq ) self.d_sliderFrequency.valueChanged['double'].connect(self.adjustFreq ) self.mainLayout = QVBoxLayout( self ) #self.mainLayout.setMargin( 10 ) self.mainLayout.setSpacing( 5 ) self.mainLayout.addWidget( self.d_sliderFrequency ) self.hLayout = QHBoxLayout() #self.hLayout.setMargin( 0 ) #self.hLayout.addWidget( self.d_thermoTune, 0 ) self.hLayout.addStretch( 5 ) self.hLayout.addWidget( self.d_wheelFrequency, 2 ) self.mainLayout.addLayout( self.hLayout ) def adjustFreq( self, frq ): factor = 13.0 / ( 108 - 87.5 ) x = ( frq - 87.5 ) * factor field = ( math.sin( x ) * math.cos( 4.0 * x ) )*( math.sin( x ) * math.cos( 4.0 * x ) ) self.d_thermoTune.setValue( field ) if ( self.d_sliderFrequency.value() != frq ): self.d_sliderFrequency.setValue( frq ) if ( self.d_wheelFrequency.value() != frq ): self.d_wheelFrequency.setValue( frq ) self.fieldChanged.emit( field ) def setFreq( self, frq ): self.d_wheelFrequency.setValue( frq ) class MainWindow(QWidget): def __init__(self): QWidget.__init__(self) self.frmTuner = TunerFrame( self ) #self.frmTuner.setFrameStyle( QFrame.Panel | QFrame.Raised ) self.frmAmp = AmpFrame( self ) self.frmAmp.setFrameStyle( QFrame.Panel | QFrame.Raised ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) self.layout.setSpacing( 0 ) self.layout.addWidget( self.frmTuner ) self.layout.addWidget( self.frmAmp ) self.frmTuner.fieldChanged['double'].connect(self.frmAmp.setMaster) self.frmTuner.setFreq( 90.0 ) self.setPalette( QPalette( QColor( 192, 192, 192 ) ) ) self.updateGradient() def resizeEvent(self, QResizeEvent ): # Qt 4.7.1: QGradient.StretchToDeviceMode is buggy on X11 self.updateGradient() def updateGradient(self): self.pal = QPalette() self.buttonColor = self.pal.color( QPalette.Button ) self.midLightColor = self.pal.color( QPalette.Midlight ) #self.gradient = QLinearGradient( rect().topLeft(), rect().topRight() ) FIXME self.gradient = QLinearGradient( ) self.gradient.setColorAt( 0.0, self.midLightColor ) self.gradient.setColorAt( 0.7, self.buttonColor ) self.gradient.setColorAt( 1.0, self.buttonColor ) self.pal.setBrush( QPalette.Window, self.gradient ) self.setPalette( self.pal ) a = QApplication(sys.argv) m = MainWindow() m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/scatterplot.py000066400000000000000000000070171377204562100205230ustar00rootroot00000000000000 #!/usr/bin/python # python scatterplot.py # Tested for python3 Qt5. Crashes if mose is over plot canvas import sys sys.path.append('../sip/') import math #import Qwt from PyQt4 import Qwt #import numpy as np from PyQt4.QtCore import Qt, QSize, qrand, QPointF from PyQt4.QtGui import QColor, QPixmap, QFont, QIcon, QPen, QPolygonF, QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication def randomValue(): #a number between [ 0.0, 1.0 ] return ( qrand() % 100000 ) / 100000.0 class DistancePicker(Qwt.QwtPlotPicker): def __init__(self, canvas): Qwt.QwtPlotPicker.__init__(self, canvas) self.setTrackerMode( Qwt.QwtPicker.ActiveOnly ) self.setStateMachine( Qwt.QwtPickerDragLineMachine() ) self.setRubberBand( Qwt.QwtPlotPicker.PolygonRubberBand ) def trackerTextF(self, pos ): text = QwtText() points = self.selection(); if ( not points.isEmpty() ): #QString num #num.setNum( QLineF( pos, invTransform( points[0] ) ).length() ) num = "123" bg = QColor( Qt.white ) bg.setAlpha( 200 ) text.setBackgroundBrush( QBrush( bg ) ) text.setText( num ) return text class Plot( Qwt.QwtPlot ): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent) self.canvas().setStyleSheet( "border: 2px solid Black;" "border-radius: 15px;" "background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1," "stop: 0 LemonChiffon, stop: 1 PaleGoldenrod );" ) # attach curve self.d_curve = Qwt.QwtPlotCurve( "Scattered Points" ) self.d_curve.setPen( QColor( "Purple" ) ) # when using QwtPlotCurve.ImageBuffer simple dots can be # rendered in parallel on multicore systems. self.d_curve.setRenderThreadCount( 0 ) # 0: use QThread.idealThreadCount() self.d_curve.attach( self ) self.setSymbol( None ) # panning with the left mouse button Qwt.QwtPlotPanner( self.canvas() ) # zoom in/out with the wheel #magnifier = Qwt.QwtPlotMagnifier( self.canvas() ) FIXME #magnifier.setMouseButton( Qt.NoButton ) # distanve measurement with the right mouse button self.picker = DistancePicker( self.canvas() ) self.picker.setMousePattern( Qwt.QwtPlotPicker.MouseSelect1, Qt.RightButton ) self.picker.setRubberBandPen( QPen( Qt.blue ) ) def setSymbol( self, symbol ): self.d_curve.setSymbol( symbol ) if ( symbol == None): self.d_curve.setStyle( Qwt.QwtPlotCurve.Dots ) def setSamples(self, samples ): self.d_curve.setPaintAttribute( Qwt.QwtPlotCurve.ImageBuffer, samples.size() > 1000 ) self.d_curve.setSamples( samples ) class MainWindow(QMainWindow): def __init__(self, *args): QMainWindow.__init__(self, *args) self.d_plot = Plot( self ) self.d_plot.setTitle( "Scatter Plot" ) self.setCentralWidget( self.d_plot ) # a million points self.setSamples( 100000 ); def setSamples(self, numPoints ): samples = QPolygonF() for i in range(numPoints): x = randomValue() * 24.0 + 1.0; y = math.log( 10.0 * ( x - 1.0 ) + 1.0 ) * ( randomValue() * 0.5 + 0.9 ) samples += QPointF( x, y ) self.d_plot.setSamples( samples ) a = QApplication( sys.argv ) m = MainWindow() m.resize( 800, 600 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/simpleplot.py000066400000000000000000000015371377204562100203500ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import Qt, QSize from PyQt4.QtGui import QBrush, QPen, QApplication a = QApplication(sys.argv) plot=Qwt.QwtPlot() plot.setTitle("Plot Demo") plot.setCanvasBackground(Qt.white) plot.insertLegend( Qwt.QwtLegend() ) grid = Qwt.QwtPlotGrid() grid.attach( plot ) curve = Qwt.QwtPlotCurve() curve.setTitle("Some Points") curve.setPen(Qt.blue,4) curve.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased, True ); symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.Ellipse, QBrush( Qt.yellow ), QPen( Qt.red, 2 ), QSize( 8, 8 ) ); curve.setSymbol( symbol ) #x=np.arange(0,10,0.1) x = [] y = [] for i in range(101): x.append(0.1*i) y.append(math.sin(0.1*i)) #y=np.sin(x) curve.setSamples(x,y) curve.attach(plot) plot.resize(600,400) plot.replot() plot.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/spectrogram.py000066400000000000000000000235521377204562100205070ustar00rootroot00000000000000#!/usr/bin/python import sys #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import Qt, qIsNaN, qRound from PyQt4.QtGui import QColor, QPen, QBrush, qRgb, QFontMetrics, QApplication, QWidget, QCheckBox, QToolBar, QToolButton, QLabel, QComboBox, QSlider, QSizePolicy, QMainWindow #from PyQt4.QtPrintSupport import QPrintDialog, QPrinter class MyZoomer(Qwt.QwtPlotZoomer): def __init__(self, canvas): Qwt.QwtPlotZoomer.__init__(self, canvas ) self.setTrackerMode( Qwt.QwtPicker.AlwaysOn ) def trackerTextF( self, pos ): bg = QColor( Qt.white ) bg.setAlpha( 200 ) text = Qwt.QwtPlotZoomer.trackerTextF( pos ) text.setBackgroundBrush( QBrush( bg ) ) return text class SpectrogramData(Qwt.QwtRasterData): def __init__(self): Qwt.QwtRasterData.__init__(self) self.setInterval( Qt.XAxis, Qwt.QwtInterval( -1.5, 1.5 ) ) self.setInterval( Qt.YAxis, Qwt.QwtInterval( -1.5, 1.5 ) ) self.setInterval( Qt.ZAxis, Qwt.QwtInterval( 0.0, 10.0 ) ) def value( self, x, y ): c = 0.842 #c = 0.33 v1 = x * x + ( y - c ) * ( y + c ) v2 = x * ( y + c ) + x * ( y + c ) return 1.0 / ( v1 * v1 + v2 * v2 ) class LinearColorMapRGB(Qwt.QwtLinearColorMap): def __init__(self): Qwt.QwtLinearColorMap.__init__(self, Qt.darkCyan, Qt.red, Qwt.QwtColorMap.RGB ) self.addColorStop( 0.1, Qt.cyan ) self.addColorStop( 0.6, Qt.green ) self.addColorStop( 0.95, Qt.yellow ) class LinearColorMapIndexed(Qwt.QwtLinearColorMap): def __init__(self): Qwt.QwtLinearColorMap.__init__( self, Qt.darkCyan, Qt.red, Qwt.QwtColorMap.Indexed ) self.addColorStop( 0.1, Qt.cyan ) self.addColorStop( 0.6, Qt.green ) self.addColorStop( 0.95, Qt.yellow ) class HueColorMap(Qwt.QwtColorMap): def __init__(self): self.d_hue1 = 0 self.d_hue2 = 359 self.d_saturation = 150 self.d_value = 200 self.d_rgbMin = qRgb() self.d_rgbMax = 0 self.d_rgbTable[360] self.updateTable() def rgb(self, interval, value ): if ( qIsNaN(value) ): return 0 width = interval.width() if ( width <= 0 ): return 0 if ( value <= interval.minValue() ): return self.d_rgbMin if ( value >= interval.maxValue() ): return self.d_rgbMax ratio = ( value - interval.minValue() ) / width hue = self.d_hue1 + qRound( ratio * ( self.d_hue2 - self.d_hue1 ) ) if ( hue >= 360 ): hue -= 360 if ( hue >= 360 ): hue = hue % 360 return self.d_rgbTable[hue] def colorIndex(self, a0, a1 ): # we don't support indexed colors return 0 def updateTable(self): for i in range(360): self.d_rgbTable[i] = QColor.fromHsv( i, self.d_saturation, self.d_value ).rgb() self.d_rgbMin = self.d_rgbTable[ self.d_hue1 % 360 ] self.d_rgbMax = self.d_rgbTable[ self.d_hue2 % 360 ] class AlphaColorMap(Qwt.QwtAlphaColorMap): def __init__(self): #setColor( QColor("DarkSalmon") ) self.setColor( QColor("SteelBlue") ) class Plot( Qwt.QwtPlot ): def __init__(self, parent): Qwt.QwtPlot.__init__(self, parent ) self.RGBMap = 0 self.IndexMap = 1 self.HueMap = 2 self.AlphaMap = 3 self.d_alpha = 255 self.d_spectrogram = Qwt.QwtPlotSpectrogram() self.d_spectrogram.setRenderThreadCount( 0 ) # use system specific thread count self.d_spectrogram.setCachePolicy( Qwt.QwtPlotRasterItem.PaintCache ) contourLevels=[] for level in range(1,20,2): contourLevels.append(0.5*level) self.d_spectrogram.setContourLevels( contourLevels ) self.d_spectrogram.setData( SpectrogramData() ) self.d_spectrogram.attach( self ) zInterval = self.d_spectrogram.data().interval( Qt.ZAxis ) # A color bar on the right axis self.rightAxis = self.axisWidget( Qwt.QwtPlot.yRight ) self.rightAxis.setTitle( "Intensity" ) self.rightAxis.setColorBarEnabled( True ) self.setAxisScale( Qwt.QwtPlot.yRight, zInterval.minValue(), zInterval.maxValue() ) self.enableAxis( Qwt.QwtPlot.yRight ) self.plotLayout().setAlignCanvasToScales( True ) self.setColorMap( self.RGBMap ) # LeftButton for the zooming # MidButton for the panning # RightButton: zoom out by 1 # Ctrl+RighButton: zoom out to full size self.zoomer = MyZoomer( self.canvas() ) self.zoomer.setMousePattern( Qwt.QwtEventPattern.MouseSelect2, Qt.RightButton, Qt.ControlModifier ) self.zoomer.setMousePattern( Qwt.QwtEventPattern.MouseSelect3, Qt.RightButton ) self.panner = Qwt.QwtPlotPanner( self.canvas() ) self.panner.setAxisEnabled( Qwt.QwtPlot.yRight, False ) self.panner.setMouseButton( Qt.MidButton ) # Avoid jumping when labels with more/less digits # appear/disappear when scrolling vertically fm = QFontMetrics ( self.axisWidget( Qwt.QwtPlot.yLeft ).font() ) sd = self.axisScaleDraw( Qwt.QwtPlot.yLeft ) sd.setMinimumExtent( fm.width( "100.00" ) ) c = QColor( Qt.darkBlue ) self.zoomer.setRubberBandPen( c ) self.zoomer.setTrackerPen( c ) def showContour( self, on ): self.d_spectrogram.setDisplayMode( Qwt.QwtPlotSpectrogram.ContourMode, on ) self.replot() def showSpectrogram( self, on ): self.d_spectrogram.setDisplayMode( Qwt.QwtPlotSpectrogram.ImageMode, on ) if (on): self.d_spectrogram.setDefaultContourPen( QPen( Qt.black, 0 ) ) else: self.d_spectrogram.setDefaultContourPen( QPen( Qt.NoPen ) ) self.replot() def setColorMap( self, type ): self.axis = self.axisWidget( Qwt.QwtPlot.yRight ) zInterval = self.d_spectrogram.data().interval( Qt.ZAxis ) self.d_mapType = type alpha = self.d_alpha if ( type == self.HueMap ): self.d_spectrogram.setColorMap( HueColorMap() ) self.axis.setColorMap( zInterval, HueColorMap() ) elif ( type == self.AlphaMap): self.alpha = 255 self.d_spectrogram.setColorMap( AlphaColorMap() ) self.axis.setColorMap( zInterval, AlphaColorMap() ) elif ( type == self.IndexMap): self.d_spectrogram.setColorMap( LinearColorMapIndexed() ) self.axis.setColorMap( zInterval, LinearColorMapIndexed() ) elif ( type == self.RGBMap): self.d_spectrogram.setColorMap( LinearColorMapRGB() ) self.axis.setColorMap( zInterval, LinearColorMapRGB() ) self.d_spectrogram.setAlpha( alpha ) self.replot() def setAlpha( self, alpha ): # setting an alpha value doesn't make sense in combination # with a color map interpolating the alpha value self.d_alpha = alpha if ( self.d_mapType != self.AlphaMap ): self.d_spectrogram.setAlpha( alpha ) self.replot() """def printPlot(self): self.printer = QPrinter( QPrinter.HighResolution ) self.printer.setOrientation( QPrinter.Landscape ) self.printer.setOutputFileName( "spectrogram.pdf" ) self.dialog = QPrintDialog ( self.printer ) if ( self.dialog.exec() ): renderer = Qwt.QwtPlotRenderer() if ( self.printer.colorMode() == QPrinter.GrayScale ): renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasFrame ) renderer.setLayoutFlag( Qwt.QwtPlotRenderer.FrameWithScales ) renderer.renderTo( self, self.printer )""" class MainWindow( QMainWindow ): def __init__(self, *args): QMainWindow.__init__(self, *args ) self.d_plot = Plot( self ) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.btnPrint = QToolButton( self.toolBar ) self.btnPrint.setText( "Print" ) self.btnPrint.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnPrint ) #self.btnPrint.clicked.connect(self.d_plot.printPlot() ) self.toolBar.addSeparator() self.toolBar.addWidget( QLabel("Color Map " ) ) self.mapBox = QComboBox( self.toolBar ) self.mapBox.addItem( "RGB" ) self.mapBox.addItem( "Indexed Colors" ) self.mapBox.addItem( "Hue" ) self.mapBox.addItem( "Alpha" ) self.mapBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.toolBar.addWidget( self.mapBox ) self.mapBox.currentIndexChanged['int'].connect(self.d_plot.setColorMap ) self.toolBar.addWidget( QLabel( " Opacity " ) ) self.slider = QSlider( Qt.Horizontal ) self.slider.setRange( 0, 255 ) self.slider.setValue( 255 ) self.slider.valueChanged['int'].connect(self.d_plot.setAlpha ) self.toolBar.addWidget( self.slider ) self.toolBar.addWidget( QLabel(" " ) ) self.btnSpectrogram = QCheckBox( "Spectrogram", self.toolBar ) self.toolBar.addWidget( self.btnSpectrogram ) self.btnSpectrogram.toggled['bool'].connect(self.d_plot.showSpectrogram ) self.btnContour = QCheckBox( "Contour", self.toolBar ) self.toolBar.addWidget( self.btnContour ) #self.btnContour.toggled['bool'](self.d_plot.showContour ) self.addToolBar( self.toolBar ) self.btnSpectrogram.setChecked( True ) self.btnContour.setChecked( False ) if __name__ == '__main__': a = QApplication(sys.argv) a.setStyle( "Windows" ) mainWindow = MainWindow() mainWindow.resize( 600, 400 ) mainWindow.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/sysinfo.py000066400000000000000000000074671377204562100176620ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import pyqtSignal, Qt, QSize, QBasicTimer from PyQt4.QtGui import (QColor, QPixmap, QFont, QIcon, QPalette, QLinearGradient, QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QSizePolicy, QVBoxLayout, QFrame, QGroupBox, QVBoxLayout ) class ValueBar(QWidget): def __init__(self, orientation, text, parent, value = 0.0 ): QWidget.__init__(self, parent) self.d_label = QLabel( text, self ) self.d_label.setFont( QFont( "Helvetica", 10 ) ) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setOrientation( orientation ) self.d_thermo.setScale( 0.0, 100.0 ) self.d_thermo.setValue( value ) self.d_thermo.setFont( QFont( "Helvetica", 8 ) ) self.d_thermo.setPipeWidth( 6 ) self.d_thermo.setScaleMaxMajor( 6 ) self.d_thermo.setScaleMaxMinor( 5 ) self.d_thermo.setFillBrush( Qt.darkMagenta ) """#if 0 QwtLinearColorMap *colorMap = QwtLinearColorMap( Qt.blue, Qt.red ) colorMap.addColorStop( 0.2, Qt.yellow ) colorMap.addColorStop( 0.3, Qt.cyan ) colorMap.addColorStop( 0.4, Qt.green ) #dcolorMap.addColorStop( 0.5, Qt.magenta ) colorMap.setMode( QwtLinearColorMap.FixedColors ) d_thermo.setColorMap( colorMap ) #endif""" self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) self.layout.setSpacing( 0 ) if ( orientation == Qt.Horizontal ): self.d_label.setAlignment( Qt.AlignCenter ) self.d_thermo.setScalePosition( Qwt.QwtThermo.LeadingScale ) self.layout.addWidget( self.d_label ) self.layout.addWidget( self.d_thermo ) else: self.d_label.setAlignment( Qt.AlignRight ) self.d_thermo.setScalePosition( Qwt.QwtThermo.TrailingScale ) self.layout.addWidget( self.d_thermo, 10, Qt.AlignHCenter ) self.layout.addWidget( self.d_label, 0 ) def setValue(self, value ): self.d_thermo.setValue( value ) class SysInfo(QFrame): def __init__(self, parent = None): QFrame.__init__(self, parent ) self.memBox = QGroupBox( "Memory Usage", self ) self.memBox.setFont( QFont( "Helvetica", 10 ) ) self.memLayout = QVBoxLayout( self.memBox ) #self.memLayout.setMargin( 15 ) self.memLayout.setSpacing( 5 ) o = Qt.Horizontal self.memLayout.addWidget( ValueBar( o, "Used", self.memBox, 57 ) ) self.memLayout.addWidget( ValueBar( o, "Shared", self.memBox, 17 ) ) self.memLayout.addWidget( ValueBar( o, "Cache", self.memBox, 30 ) ) self.memLayout.addWidget( ValueBar( o, "Buffers", self.memBox, 22 ) ) self.memLayout.addWidget( ValueBar( o, "Swap Used", self.memBox, 57 ) ) self.memLayout.addWidget( QWidget( self.memBox ), 10 ) # spacer self.cpuBox = QGroupBox( "Cpu Usage", self ) self.cpuBox.setFont( QFont( "Helvetica", 10 ) ) self.cpuLayout = QHBoxLayout( self.cpuBox ) #self.cpuLayout.setMargin( 15 ) self.cpuLayout.setSpacing( 5 ) o = Qt.Vertical self.cpuLayout.addWidget( ValueBar( o, "User", self.cpuBox, 57 ) ) self.cpuLayout.addWidget( ValueBar( o, "Total", self.cpuBox, 73 ) ) self.cpuLayout.addWidget( ValueBar( o, "System", self.cpuBox, 16 ) ) self.cpuLayout.addWidget( ValueBar( o, "Idle", self.cpuBox, 27 ) ) self.layout = QHBoxLayout( self ) #self.layout.setMargin( 10 ) self.layout.addWidget( self.memBox, 10 ) self.layout.addWidget( self.cpuBox, 0 ) a = QApplication(sys.argv) info = SysInfo() info.resize( info.sizeHint().expandedTo( QSize( 600, 400 ) ) ) info.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt4examples/tvplot.py000066400000000000000000000131731377204562100175070ustar00rootroot00000000000000#!/usr/bin/python import sys #import Qwt from PyQt4 import Qwt from PyQt4.QtCore import Qt, QSize from PyQt4.QtGui import QColor, QPixmap, QFont, QBrush, QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QPalette, QComboBox, QSizePolicy class Histogram(Qwt.QwtPlotHistogram): def __init__(self,title, symbolColor ): Qwt.QwtPlotHistogram.__init__(self,title) self.setStyle( Qwt.QwtPlotHistogram.Columns ) self.setColor( symbolColor ) def setValues(self, values ): numValues = len(values) #QVector samples( numValues ) samples = [] for i in range(numValues): interval = Qwt.QwtInterval( i , i + 1.0 ) interval.setBorderFlags( Qwt.QwtInterval.ExcludeMaximum ) samples.append(Qwt.QwtIntervalSample( values[i], interval )) self.setSamples( samples ) def setColor(self, color ): c = QColor(color) c.setAlpha( 180 ) self.setBrush( QBrush( c ) ) class TVPlot( Qwt.QwtPlot): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent ) self.grid=None self.setTitle( "Watching TV during a weekend" ) canvas = Qwt.QwtPlotCanvas() canvas.setPalette( QPalette(Qt.gray) ) canvas.setBorderRadius( 10 ) self.setCanvas( canvas ) self.plotLayout().setAlignCanvasToScales( True ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Number of People" ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Number of Hours" ) self.legend = Qwt.QwtLegend() self.legend.setDefaultItemMode( Qwt.QwtLegendData.Checkable ) self.insertLegend( self.legend, Qwt.QwtPlot.RightLegend ) self.populate() self.legend.checked['QVariant','bool','int'].connect(self.showItem ) self.replot() # creating the legend items """self.items = Qwt.QwtPlotDict.itemList( Qwt.QwtPlotItem.Rtti_PlotHistogram ) for i in range(len(self.items)): if ( i == 0 ): #const QVariant itemInfo = itemToInfo( self.items[i] ) #QwtLegendLabel * legendLabel = legend.legendWidget( itemInfo ) if ( legendLabel ): legendLabel.setChecked( True ) self.items[i].setVisible( True ) else: self.items[i].setVisible( False )""" self.setAutoReplot( True ) def populate(self): self.grid = Qwt.QwtPlotGrid() self.grid.enableX( False ) self.grid.enableY( True ) self.grid.enableXMin( False ) self.grid.enableYMin( False ) self.grid.setMajorPen( Qt.black, 0, Qt.DotLine ) self.grid.attach( self ) juneValues = [ 7.0, 19.0, 24.0, 32.0, 10.0, 5.0, 3.0 ] novemberValues = [ 4.0, 15.0, 22.0, 34.0, 13.0, 8.0, 4.0 ] histogramJune = Histogram( "Summer", Qt.red ) histogramJune.setValues( juneValues ) histogramJune.attach( self ) histogramNovember = Histogram( "Winter", Qt.blue ) histogramNovember.setValues( novemberValues ) histogramNovember.attach( self ) def exportPlot(self): print("Export Plot") #renderer = Qwt.QwtPlotRenderer() #renderer.exportTo( self, "tvplot.pdf" ) def setMode( self, mode): #QwtPlotItemList print("Set mode %d"%mode) """items = self.itemList( Qwt.QwtPlotItem.Rtti_PlotHistogram ) for i in range(len(items)): histogram = items[i] if ( mode < 3 ): histogram.setStyle(mode) histogram.setSymbol( ) pen = QPen( Qt.black, 0 ) if ( mode == Qwt.QwtPlotHistogram.Lines ): pen.setBrush( histogram.brush() ) histogram.setPen( pen ) else: histogram.setStyle( Qwt.QwtPlotHistogram.Columns ) symbol = Qwt.QwtColumnSymbol( Qwt.QwtColumnSymbol.Box ) symbol.setFrameStyle( Qwt.QwtColumnSymbol.Raised ) symbol.setLineWidth( 2 ) symbol.setPalette( QPalette( histogram.brush().color() ) ) histogram.setSymbol( symbol )""" def showItem( self, itemInfo, on ): print("Doesn't work yet.") plotItem = self.infoToItem( itemInfo ) if ( plotItem): plotItem.setVisible( on ) class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.d_plot = TVPlot(self) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.typeBox = QComboBox( self.toolBar ) self.typeBox.addItem( "Outline" ) self.typeBox.addItem( "Columns" ) self.typeBox.addItem( "Lines" ) self.typeBox.addItem( "Column Symbol" ) self.typeBox.setCurrentIndex( self.typeBox.count() - 1 ) self.typeBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.btnExport = QToolButton( self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) #connect( btnExport, SIGNAL( clicked() ), d_plot, SLOT( exportPlot() ) ) self.btnExport.clicked.connect(self.d_plot.exportPlot) self.toolBar.addWidget( self.typeBox ) self.toolBar.addWidget( self.btnExport ) self.addToolBar( self.toolBar ) self.d_plot.setMode( self.typeBox.currentIndex() ) self.typeBox.currentIndexChanged['int'].connect(self.d_plot.setMode) a = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.resize( 600, 400 ) mainWindow.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/000077500000000000000000000000001377204562100156015ustar00rootroot00000000000000PyQt-Qwt-1.02.02/qt5examples/animation.py000077500000000000000000000136521377204562100201440ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt5 import Qwt from PyQt5.QtCore import Qt, QTime, QPointF, QSize from PyQt5.QtGui import QColor, QTransform from PyQt5.QtWidgets import QApplication, QFrame from PyQt5.QtGui import QPolygonF class Curve(Qwt.QwtPlotCurve): def __init__(self): Qwt.QwtPlotCurve.__init__(self) self.d_transform = QTransform() def setTransformation(self, transform ): self.d_transform = transform; class Curve1(Curve): def __init__(self): Curve.__init__(self) self.setPen( QColor( 150, 150, 200 ), 2 ) self.setStyle( Qwt.QwtPlotCurve.Lines ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setSplineSize( 150 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.XCross ) symbol.setPen( Qt.yellow ) symbol.setSize( 7 ) self.setSymbol( symbol ) # somewhere to the left self.transform = QTransform() self.transform.scale( 1.5, 1.0 ); self.transform.translate( 1.5, 3.0 ); self.setTransformation( self.transform ) def points(self, phase ): points = QPolygonF() numSamples = 15; for i in range(numSamples): v = 6.28 * i / ( numSamples - 1 ) points += QPointF( math.sin( v - phase ), v ) return points def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Curve2(Curve): def __init__(self): Curve.__init__(self) self.setStyle( Qwt.QwtPlotCurve.Sticks ); self.setPen( QColor( 200, 150, 50 ) ); self.setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Ellipse,QColor( Qt.gray ), QColor( Qt.yellow ), QSize( 5, 5 ) ) ) def points(self, phase ): points = QPolygonF() numSamples = 50 for i in range(numSamples): v = 10.0 * i / ( numSamples - 1 ) points += QPointF( v, math.cos( 3.0 * ( v + phase ) ) ) return points def updateSamples( self, phase ): a=self.points(phase) b= self.d_transform.map(a) self.setSamples( b ) class Curve3(Curve): def __init__(self): Curve.__init__(self) self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( QColor( 100, 200, 150 ), 2 ) curveFitter = Qwt.QwtSplineCurveFitter() curveFitter.setFitMode( Qwt.QwtSplineCurveFitter.ParametricSpline ) curveFitter.setSplineSize( 200 ) self.setCurveFitter( curveFitter ) self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True ) # somewhere in the top right corner transform = QTransform() transform.translate( 7.0, 7.5 ) transform.scale( 2.0, 2.0 ) self.setTransformation( transform ) def points( self, phase ): points = QPolygonF() numSamples = 9 for i in range(numSamples): v = i * 2.0 * 3.14159 / ( numSamples - 1 ) points += QPointF( math.sin( v - phase ), math.cos( 3.0 * ( v + phase ) ) ) return points; def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Curve4(Curve): def __init__(self): Curve.__init__(self) self.d_points = QPolygonF() self.setStyle( Qwt.QwtPlotCurve.Lines ) self.setPen( Qt.red, 2 ) self.initSamples() # somewhere in the center transform = QTransform() transform.translate( 7.0, 3.0 ) transform.scale( 1.5, 1.5 ) self.setTransformation( transform ) def points(self, phase ): speed = 0.05 s = speed * math.sin( phase ); c = math.sqrt( 1.0 - s * s ); for i in range(len(self.d_points)): p = self.d_points[i] u = p.x() v = p.y() self.d_points[i].setX( u * c - v * s ) self.d_points[i].setY( v * c + u * s ) return self.d_points; def initSamples(self): numSamples = 15 for i in range(numSamples): angle = i * ( 2.0 * 3.14159 / ( numSamples - 1 ) ); p= QPointF( math.cos( angle ), math.sin( angle ) ); if ( i % 2 ): p *= 0.4 self.d_points += p def updateSamples( self, phase ): self.setSamples( self.d_transform.map( self.points( phase ))) class Plot( Qwt.QwtPlot): def __init__(self,parent=None): Qwt.QwtPlot.__init__(self, parent) self.d_time = QTime() self.d_curves = [] self.setAutoReplot( False ) self.setTitle( "Animated Curves" ) # hide all axes for axis in range(Qwt.QwtPlot.axisCnt): self.enableAxis( axis, False ) #self.plotLayout.setCanvasMargin( 10 ) self.d_curves.append(Curve1()) self.d_curves.append(Curve2()) self.d_curves.append(Curve3()) self.d_curves.append(Curve4()) self.updateCurves() for i in range(len(self.d_curves)): self.d_curves[i].attach( self ) self.d_time.start() self.startTimer( 40 ) def timerEvent( self, event ): self.updateCurves() self.replot() def updateCurves(self): speed = 2 * 3.14159 / 25000.0 # a cycle every 25 seconds phase = self.d_time.elapsed() * speed for i in range(len(self.d_curves)): self.d_curves[i].updateSamples( phase ) if __name__ == '__main__': a = QApplication(sys.argv) plot = Plot() #if USE_OPENGL #canvas = Qwt.QwtPlotGLCanvas() #canvas.setFrameStyle( Qwt.QwtPlotGLCanvas.NoFrame ) #else canvas = Qwt.QwtPlotCanvas(); canvas.setFrameStyle( QFrame.NoFrame ); canvas.setPaintAttribute( Qwt.QwtPlotCanvas.BackingStore, False ) #endif plot.setCanvas( canvas ) plot.setCanvasBackground( QColor( 30, 30, 50 ) ) plot.resize( 400, 400 ) plot.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/barchart.py000077500000000000000000000123621377204562100177500ustar00rootroot00000000000000#!/usr/bin/python3 import sys import random from PyQt5 import Qwt from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QPalette, QColor from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QComboBox, QSizePolicy, QToolButton colours={"DarkOrchid":QColor(153, 50, 204), "Gold":QColor(255, 215, 0), "LemonChiffon":QColor(255, 250, 205), "SteelBlue":QColor( 70, 130, 180) } class BarChart( Qwt.QwtPlot ): def __init__(self, parent): Qwt.QwtPlot.__init__(self, parent) self.setAutoFillBackground( True ) self.setPalette( QPalette(Qt.white) ) self.canvas().setPalette( QPalette( colours["LemonChiffon"])) self.setTitle( "Bar Chart" ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Whatever" ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Whatever" ) self.d_barChartItem = Qwt.QwtPlotMultiBarChart( "Bar Chart" ) self.d_barChartItem.setLayoutPolicy( Qwt.QwtPlotMultiBarChart.AutoAdjustSamples ) self.d_barChartItem.setSpacing( 20 ) self.d_barChartItem.setMargin( 3 ) self.d_barChartItem.attach( self ) self.insertLegend( Qwt.QwtLegend() ) self.populate() self.setOrientation( 0 ) self.setAutoReplot( True ) def populate(self): colors = [colours["DarkOrchid"], colours["SteelBlue"], colours["Gold"]] numSamples = 5 numBars = len(colors ) titles = [] for i in range(numBars): titles.append(Qwt.QwtText("Bar %d"%i)) self.d_barChartItem.setBarTitles( titles ) self.d_barChartItem.setLegendIconSize( QSize( 10, 14 ) ) for i in range(numBars): symbol = Qwt.QwtColumnSymbol( Qwt.QwtColumnSymbol.Box ) symbol.setLineWidth( 2 ) symbol.setFrameStyle( Qwt.QwtColumnSymbol.Raised ) symbol.setPalette( QPalette( colors[i] ) ) self.d_barChartItem.setSymbol( i, symbol ) self.series = [] for i in range(numSamples): values = [] for j in range(numBars): values.append( 2.0 + random.randint(0, 8) % 8 ) self.series.append(values) print(self.series) self.d_barChartItem.setSamples( self.series ) def setMode( self, mode ): if ( mode == 0 ): self.d_barChartItem.setStyle( Qwt.QwtPlotMultiBarChart.Grouped ) else: self.d_barChartItem.setStyle( Qwt.QwtPlotMultiBarChart.Stacked ) def setOrientation( self, orientation ): axis1 = Qwt.QwtPlot.Axis() axis2 = Qwt.QwtPlot.Axis() if ( orientation == 0 ): axis1 = Qwt.QwtPlot.xBottom axis2 = Qwt.QwtPlot.yLeft self.d_barChartItem.setOrientation( Qt.Vertical ) else: axis1 = Qwt.QwtPlot.yLeft axis2 = Qwt.QwtPlot.xBottom self.d_barChartItem.setOrientation( Qt.Horizontal ) self.setAxisScale( axis1, 0, len(self.series) -1, 1.0 ) self.setAxisAutoScale( axis2 ) self.scaleDraw1 = self.axisScaleDraw( axis1 ) self.scaleDraw1.enableComponent( Qwt.QwtScaleDraw.Backbone, False ) self.scaleDraw1.enableComponent( Qwt.QwtScaleDraw.Ticks, False ) self.scaleDraw2 = self.axisScaleDraw( axis2 ) self.scaleDraw2.enableComponent( Qwt.QwtScaleDraw.Backbone, True ) self.scaleDraw2.enableComponent( Qwt.QwtScaleDraw.Ticks, True ) self.plotLayout().setAlignCanvasToScale( axis1, True ) self.plotLayout().setAlignCanvasToScale( axis2, False ) self.plotLayout().setCanvasMargin( 0 ) self.updateCanvasMargins() self.replot() def exportChart(self): renderer = Qwt.QwtPlotRenderer() renderer.exportTo( self, "barchart.pdf" ) class MainWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.d_chart = BarChart( self ) self.setCentralWidget( self.d_chart ) self.toolBar = QToolBar( self ) self.typeBox = QComboBox( self.toolBar ) self.typeBox.addItem( "Grouped" ) self.typeBox.addItem( "Stacked" ) self.typeBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.orientationBox = QComboBox( self.toolBar ) self.orientationBox.addItem( "Vertical" ) self.orientationBox.addItem( "Horizontal" ) self.orientationBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.btnExport = QToolButton(self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.btnExport.clicked.connect(self.d_chart.exportChart) self.toolBar.addWidget( self.typeBox ) self.toolBar.addWidget( self.orientationBox ) self.toolBar.addWidget( self.btnExport ) self.addToolBar( self.toolBar ) self.d_chart.setMode( self.typeBox.currentIndex() ) self.typeBox.currentIndexChanged['int'].connect(self.d_chart.setMode ) self.d_chart.setOrientation( self.orientationBox.currentIndex() ) self.orientationBox.currentIndexChanged['int'].connect(self.d_chart.setOrientation) a = QApplication(sys.argv) m = MainWindow() m.resize( 600, 400 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/bode.py000077500000000000000000000347561377204562100171060ustar00rootroot00000000000000#!/usr/bin/python3 import sys import math #import Qwt from PyQt5 import Qwt import numpy as np from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QColor, QPixmap, QFont, QIcon from PyQt5.QtWidgets import QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication from PyQt5.QtPrintSupport import QPrintDialog, QPrinter def logSpace(size, xmin, xmax ): if ( ( xmin <= 0.0 ) or ( xmax <= 0.0 ) or ( size <= 0 ) ): array = np.zeros(0,float) return array; array = np.zeros(size,float) imax = size - 1; array[0] = xmin; array[imax] = xmax; lxmin = math.log( xmin ) lxmax = math.log( xmax ) lstep = ( lxmax - lxmin ) / imax for i in range(imax): array[i] = math.exp( lxmin + i * lstep ) return array print_xpm = ["32 32 12 1", "a c #ffffff", "h c #ffff00", "c c #ffffff", "f c #dcdcdc", "b c #c0c0c0", "j c #a0a0a4", "e c #808080", "g c #808000", "d c #585858", "i c #00ff00", "# c #000000", ". c None", "................................", "................................", "...........###..................", "..........#abb###...............", ".........#aabbbbb###............", ".........#ddaaabbbbb###.........", "........#ddddddaaabbbbb###......", ".......#deffddddddaaabbbbb###...", "......#deaaabbbddddddaaabbbbb###", ".....#deaaaaaaabbbddddddaaabbbb#", "....#deaaabbbaaaa#ddedddfggaaad#", "...#deaaaaaaaaaa#ddeeeeafgggfdd#", "..#deaaabbbaaaa#ddeeeeabbbbgfdd#", ".#deeefaaaaaaa#ddeeeeabbhhbbadd#", "#aabbbeeefaaa#ddeeeeabbbbbbaddd#", "#bbaaabbbeee#ddeeeeabbiibbadddd#", "#bbbbbaaabbbeeeeeeabbbbbbaddddd#", "#bjbbbbbbaaabbbbeabbbbbbadddddd#", "#bjjjjbbbbbbaaaeabbbbbbaddddddd#", "#bjaaajjjbbbbbbaaabbbbadddddddd#", "#bbbbbaaajjjbbbbbbaaaaddddddddd#", "#bjbbbbbbaaajjjbbbbbbddddddddd#.", "#bjjjjbbbbbbaaajjjbbbdddddddd#..", "#bjaaajjjbbbbbbjaajjbddddddd#...", "#bbbbbaaajjjbbbjbbaabdddddd#....", "###bbbbbbaaajjjjbbbbbddddd#.....", "...###bbbbbbaaajbbbbbdddd#......", "......###bbbbbbjbbbbbddd#.......", ".........###bbbbbbbbbdd#........", "............###bbbbbbd#.........", "...............###bbb#..........", "..................###..........."] zoom_xpm = ["32 32 8 1", "# c #000000", "b c #c0c0c0", "a c #ffffff", "e c #585858", "d c #a0a0a4", "c c #0000ff", "f c #00ffff", ". c None", "..######################........", ".#a#baaaaaaaaaaaaaaaaaa#........", "#aa#baaaaaaaaaaaaaccaca#........", "####baaaaaaaaaaaaaaaaca####.....", "#bbbbaaaaaaaaaaaacccaaa#da#.....", "#aaaaaaaaaaaaaaaacccaca#da#.....", "#aaaaaaaaaaaaaaaaaccaca#da#.....", "#aaaaaaaaaabe###ebaaaaa#da#.....", "#aaaaaaaaa#########aaaa#da#.....", "#aaaaaaaa###dbbbb###aaa#da#.....", "#aaaaaaa###aaaaffb###aa#da#.....", "#aaaaaab##aaccaaafb##ba#da#.....", "#aaaaaae#daaccaccaad#ea#da#.....", "#aaaaaa##aaaaaaccaab##a#da#.....", "#aaaaaa##aacccaaaaab##a#da#.....", "#aaaaaa##aaccccaccab##a#da#.....", "#aaaaaae#daccccaccad#ea#da#.....", "#aaaaaab##aacccaaaa##da#da#.....", "#aaccacd###aaaaaaa###da#da#.....", "#aaaaacad###daaad#####a#da#.....", "#acccaaaad##########da##da#.....", "#acccacaaadde###edd#eda#da#.....", "#aaccacaaaabdddddbdd#eda#a#.....", "#aaaaaaaaaaaaaaaaaadd#eda##.....", "#aaaaaaaaaaaaaaaaaaadd#eda#.....", "#aaaaaaaccacaaaaaaaaadd#eda#....", "#aaaaaaaaaacaaaaaaaaaad##eda#...", "#aaaaaacccaaaaaaaaaaaaa#d#eda#..", "########################dd#eda#.", "...#dddddddddddddddddddddd##eda#", "...#aaaaaaaaaaaaaaaaaaaaaa#.####", "...########################..##."] class Plot( Qwt.QwtPlot): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent) self.setAutoReplot( False ) self.setTitle( "Frequency Response of a Second-Order System" ) canvas = Qwt.QwtPlotCanvas() canvas.setBorderRadius( 10 ) self.setCanvas( canvas ) self.setCanvasBackground( QColor( "MidnightBlue" ) ) # legend legend = Qwt.QwtLegend() self.insertLegend( legend, Qwt.QwtPlot.BottomLegend ) # grid grid = Qwt.QwtPlotGrid() grid.enableXMin( True ) grid.setMajorPen( Qt.white, 0, Qt.DotLine ) grid.setMinorPen( Qt.gray, 0 , Qt.DotLine ) grid.attach( self ) # axes self.enableAxis( Qwt.QwtPlot.yRight ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Normalized Frequency" ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Amplitude [dB]" ) self.setAxisTitle( Qwt.QwtPlot.yRight, "Phase [deg]" ) self.setAxisMaxMajor( Qwt.QwtPlot.xBottom, 6 ) self.setAxisMaxMinor( Qwt.QwtPlot.xBottom, 9 ) self.setAxisScaleEngine( Qwt.QwtPlot.xBottom, Qwt.QwtLogScaleEngine() ) # curves self.d_curve1 = Qwt.QwtPlotCurve( "Amplitude" ) self.d_curve1.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) self.d_curve1.setPen( Qt.yellow ) self.d_curve1.setLegendAttribute( Qwt.QwtPlotCurve.LegendShowLine ) self.d_curve1.setYAxis( Qwt.QwtPlot.yLeft ) self.d_curve1.attach( self ) self.d_curve2 = Qwt.QwtPlotCurve( "Phase" ) self.d_curve2.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) self.d_curve2.setPen( Qt.cyan ) self.d_curve2.setLegendAttribute( Qwt.QwtPlotCurve.LegendShowLine ) self.d_curve2.setYAxis( Qwt.QwtPlot.yRight ) self.d_curve2.attach( self ) # marker self.d_marker1 = Qwt.QwtPlotMarker() self.d_marker1.setValue( 0.0, 0.0 ) self.d_marker1.setLineStyle( Qwt.QwtPlotMarker.VLine ) self.d_marker1.setLabelAlignment( Qt.AlignRight | Qt.AlignBottom ) self.d_marker1.setLinePen( Qt.green, 0, Qt.DashDotLine ) self.d_marker1.attach( self ) self.d_marker2 = Qwt.QwtPlotMarker() self.d_marker2.setLineStyle( Qwt.QwtPlotMarker.HLine ) self.d_marker2.setLabelAlignment( Qt.AlignRight | Qt.AlignBottom ) self.d_marker2.setLinePen( QColor( 200, 150, 0 ), 0, Qt.DashDotLine ) self.d_marker2.setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Diamond,QColor( Qt.yellow ), QColor( Qt.green ), QSize( 8, 8 ) ) ) self.d_marker2.attach( self ) self.setDamp( 0 ) self.setAutoReplot( True ) def showData(self, frequency, amplitude, phase, count ): self.d_curve1.setSamples( frequency, amplitude) self.d_curve2.setSamples( frequency, phase) def showPeak( self, freq, amplitude ): label = "Peak: %.3g dB"%amplitude text = Qwt.QwtText( label ) text.setFont( QFont( "Helvetica", 10, QFont.Bold ) ) text.setColor( QColor( 200, 150, 0 ) ) self.d_marker2.setValue( freq, amplitude ) self.d_marker2.setLabel( text ) def show3dB( self, freq ): label = "-3 dB at f = %.3g"%freq text = Qwt.QwtText( label ) text.setFont( QFont( "Helvetica", 10, QFont.Bold ) ) text.setColor( Qt.green ) self.d_marker1.setValue( freq, 0.0 ) self.d_marker1.setLabel( text ) #re-calculate frequency response def setDamp( self, damping ): doReplot = self.autoReplot() self.setAutoReplot( False ) ArraySize = 200; amplitude = np.zeros(ArraySize, float) phase = np.zeros(ArraySize, float) # build frequency vector with logarithmic division frequency = logSpace( ArraySize, 0.01, 100 ) i3 = 1 fmax = 1 amax = -1000.0 for i in range(ArraySize): f = frequency[i]; g = complex( 1.0 ) / complex( 1.0 - f * f, 2.0 * damping * f ) amplitude[i] = 20.0 * math.log10( math.sqrt( g.real * g.real + g.imag * g.imag ) ) phase[i] = math.atan2( g.imag, g.real ) * ( 180.0 / 3.14159)#M_PI ) if ( ( i3 <= 1 ) and ( amplitude[i] < -3.0 ) ): i3 = i if ( amplitude[i] > amax ): amax = amplitude[i]; fmax = frequency[i]; f3 = frequency[i3] - ( frequency[i3] - frequency[i3 - 1] ) / ( amplitude[i3] - amplitude[i3 -1] ) * ( amplitude[i3] + 3 ) self.showPeak( fmax, amax ) self.show3dB( f3 ) self.showData( frequency, amplitude, phase, ArraySize ) self.setAutoReplot( doReplot ) self.replot() class Zoomer(Qwt.QwtPlotZoomer): def __init__(self, xAxis, yAxis, canvas ): Qwt.QwtPlotZoomer.__init__(self, xAxis, yAxis, canvas ) self.setTrackerMode( Qwt.QwtPicker.AlwaysOff ) self.setRubberBand( Qwt.QwtPicker.NoRubberBand ) # RightButton: zoom out by 1 # Ctrl+RightButton: zoom out to full size self.setMousePattern( Qwt.QwtEventPattern.MouseSelect2, Qt.RightButton, Qt.ControlModifier ) self.setMousePattern( Qwt.QwtEventPattern.MouseSelect3, Qt.RightButton ) class MainWindow( QMainWindow ): def __init__(self, *args): QMainWindow.__init__(self, *args) self.d_plot = Plot( self ) margin = 5; self.d_plot.setContentsMargins( margin, margin, margin, 0 ) self.setContextMenuPolicy( Qt.NoContextMenu ) self.d_zoomer=[None,None] self.d_zoomer[0] = Zoomer( Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, self.d_plot.canvas() ) self.d_zoomer[0].setRubberBand( Qwt.QwtPicker.RectRubberBand ) self.d_zoomer[0].setRubberBandPen( QColor( Qt.green ) ) self.d_zoomer[0].setTrackerMode( Qwt.QwtPicker.ActiveOnly ) self.d_zoomer[0].setTrackerPen( QColor( Qt.white ) ) self.d_zoomer[1] = Zoomer( Qwt.QwtPlot.xTop, Qwt.QwtPlot.yRight, self.d_plot.canvas() ) self.d_panner = Qwt.QwtPlotPanner( self.d_plot.canvas() ) self.d_panner.setMouseButton( Qt.MidButton ) self.d_picker = Qwt.QwtPlotPicker( Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPlotPicker.CrossRubberBand, Qwt.QwtPicker.AlwaysOn, self.d_plot.canvas() ) self.d_picker.setStateMachine( Qwt.QwtPickerDragPointMachine() ) self.d_picker.setRubberBandPen( QColor( Qt.green ) ) self.d_picker.setRubberBand( Qwt.QwtPicker.CrossRubberBand ) self.d_picker.setTrackerPen( QColor( Qt.white ) ) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.btnZoom = QToolButton( self.toolBar ) self.btnZoom.setText( "Zoom" ) self.btnZoom.setIcon( QIcon(QPixmap( zoom_xpm ) )) self.btnZoom.setCheckable( True ) self.btnZoom.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnZoom ) self.btnZoom.toggled.connect(self.enableZoomMode) self.btnPrint = QToolButton( self.toolBar ) self.btnPrint.setText( "Print" ) self.btnPrint.setIcon( QIcon(QPixmap( print_xpm ) ) ) self.btnPrint.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnPrint ) self.btnPrint.clicked.connect(self.mprint) self.btnExport = QToolButton( self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setIcon( QIcon(QPixmap( print_xpm ) ) ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnExport ) self.btnExport.clicked.connect(self.exportDocument) self.toolBar.addSeparator() hBox = QWidget( self.toolBar ) self.layout = QHBoxLayout( hBox ) self.layout.setSpacing( 0 ) self.layout.addWidget( QWidget( hBox ), 10 ) # spacer self.layout.addWidget( QLabel( "Damping Factor", hBox ), 0 ) self.layout.addSpacing( 10 ) self.cntDamp = Qwt.QwtCounter( hBox ) self.cntDamp.setRange( 0.0, 5.0 ) self.cntDamp.setSingleStep( 0.01 ) self.cntDamp.setValue( 0.0 ) self.layout.addWidget( self.cntDamp, 0 ) self.toolBar.addWidget( hBox ) self.addToolBar( self.toolBar ) self.statusBar() self.enableZoomMode( False ) self.showInfo() self.cntDamp.valueChanged['double'].connect(self.d_plot.setDamp) self.d_picker.moved.connect(self.moved) #connect( d_picker, SIGNAL( moved( const QPoint & ) ), SLOT( moved( const QPoint & ) ) ) #self.d_picker.selected['const QPolygon &'].connect( self.selected ) #connect( d_picker, SIGNAL( selected( const QPolygon & ) ), SLOT( selected( const QPolygon & ) ) ) def mprint(self): printer = QPrinter( QPrinter.HighResolution ) docName = "Humm" #self.d_plot.title().text() #if ( not docName.isEmpty() ): #docName.replace ( QRegExp ( QString.fromLatin1 ( "\n" ) ), tr ( " -- " ) ) printer.setDocName ( docName ) printer.setCreator( "Bode example" ) printer.setOrientation( QPrinter.Landscape ) dialog = QPrintDialog( printer ) if ( dialog.exec_() ): renderer = Qwt.QwtPlotRenderer() if ( printer.colorMode() == QPrinter.GrayScale ): renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasFrame ) renderer.setLayoutFlag( Qwt.QwtPlotRenderer.FrameWithScales ) renderer.renderTo( self.d_plot, printer ) def exportDocument(self): print("Not implemented") #renderer = Qwt.QwtPlotRenderer() #renderer.exportTo( self.d_plot, "bode.pdf" ) def enableZoomMode( self, on ): self.d_panner.setEnabled( on ) self.d_zoomer[0].setEnabled( on ) self.d_zoomer[0].zoom( 0 ) self.d_zoomer[1].setEnabled( on ) self.d_zoomer[1].zoom( 0 ) self.d_picker.setEnabled( not on ) self.showInfo() def showInfo( self, text="" ): if ( text=="" ): if ( self.d_picker.rubberBand() ): text = "Cursor Pos: Press left mouse button in plot region" else: text = "Zoom: Press mouse button and drag" self.statusBar().showMessage( text ) def moved( self, pos ): info = "Freq=%g, Ampl=%g, Phase=%g"%( self.d_plot.invTransform( Qwt.QwtPlot.xBottom, pos.x() ), self.d_plot.invTransform( Qwt.QwtPlot.yLeft, pos.y() ), self.d_plot.invTransform( Qwt.QwtPlot.yRight, pos.y() )) self.showInfo( info ) def selected(self): self.showInfo("selected") a = QApplication(sys.argv) m = MainWindow() m.resize( 540, 400 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/controls.py000077500000000000000000000362551377204562100200340ustar00rootroot00000000000000#!/usr/bin/python import sys import math #import Qwt from PyQt5 import Qwt import numpy as np from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QColor, QPalette, QBrush #, QPixmap, QFont, QIcon from PyQt5.QtWidgets import QApplication, QTabWidget, QWidget, QBoxLayout, QVBoxLayout, QHBoxLayout, QLayout, QGridLayout, QLabel #, QToolBar, QToolButton, QApplication #from PyQt5.QtPrintSupport import QPrintDialog, QPrinter #include #include #include "slidertab.h" #include "wheeltab.h" #include "knobtab.h" #include "dialtab.h" #include #include #include #include #include #include "sliderbox.h" class SliderBox(QWidget): def __init__(self,sliderType,parent = None): QWidget.__init__(self, parent) self.d_slider = self.createSlider( sliderType ) self.alignment = None #QFlags(Qt.AlignmentFlag) if self.d_slider.orientation() == Qt.Horizontal: if self.d_slider.scalePosition() == Qwt.QwtSlider.TrailingScale: self.alignment = Qt.AlignBottom else: self.alignment = Qt.AlignTop self.alignment |= Qt.AlignHCenter else: if self.d_slider.scalePosition() == Qwt.QwtSlider.TrailingScale: self.alignment = Qt.AlignRight else: self.alignment = Qt.AlignLeft self.alignment |= Qt.AlignVCenter self.d_label = QLabel( self ) self.d_label.setAlignment( self.alignment ) self.d_label.setFixedWidth( self.d_label.fontMetrics().width( "10000.9" ) ) self.d_slider.valueChanged['double'].connect(self.setNum) layout = None #QBoxLayout() if self.d_slider.orientation() == Qt.Horizontal: layout = QHBoxLayout( self ) else: layout = QVBoxLayout( self ) layout.addWidget( self.d_slider ) layout.addWidget( self.d_label ) self.setNum( self.d_slider.value() ) def createSlider(self, sliderType ): slider = Qwt.QwtSlider() if sliderType == 0: slider.setOrientation( Qt.Horizontal ) slider.setScalePosition( Qwt.QwtSlider.TrailingScale ) slider.setTrough( True ) slider.setGroove( False ) slider.setSpacing( 0 ) slider.setHandleSize( QSize( 30, 16 ) ) slider.setScale( 10.0, -10.0 ) slider.setTotalSteps( 8 ) slider.setSingleSteps( 1 ) slider.setPageSteps( 1 ) slider.setWrapping( True ) elif sliderType == 1: slider.setOrientation( Qt.Horizontal ) slider.setScalePosition( Qwt.QwtSlider.NoScale ) slider.setTrough( True ) slider.setGroove( True ) slider.setScale( 0.0, 1.0 ) slider.setTotalSteps( 100 ) slider.setSingleSteps( 1 ) slider.setPageSteps( 5 ) elif sliderType == 2: slider.setOrientation( Qt.Horizontal ) slider.setScalePosition( Qwt.QwtSlider.LeadingScale ) slider.setTrough( False ) slider.setGroove( True ) slider.setHandleSize( QSize( 12, 25 ) ) slider.setScale( 1000.0, 3000.0 ) slider.setTotalSteps( 200 ) slider.setSingleSteps( 2 ) slider.setPageSteps( 10 ) elif sliderType == 3: slider.setOrientation( Qt.Horizontal ) slider.setScalePosition( Qwt.QwtSlider.TrailingScale ) slider.setTrough( True ) slider.setGroove( True ) scaleEngine = Qwt.QwtLinearScaleEngine( 2 ) scaleEngine.setTransformation( Qwt.QwtPowerTransform( 2 ) ) slider.setScaleEngine( scaleEngine ) slider.setScale( 0.0, 128.0 ) slider.setTotalSteps( 100 ) slider.setStepAlignment( False ) slider.setSingleSteps( 1 ) slider.setPageSteps( 5 ) elif sliderType == 4: slider.setOrientation( Qt.Vertical ) slider.setScalePosition( Qwt.QwtSlider.TrailingScale ) slider.setTrough( False ) slider.setGroove( True ) slider.setScale( 100.0, 0.0 ) slider.setInvertedControls( True ) slider.setTotalSteps( 100 ) slider.setPageSteps( 5 ) slider.setScaleMaxMinor( 5 ) elif sliderType == 5: slider.setOrientation( Qt.Vertical ) slider.setScalePosition( Qwt.QwtSlider.NoScale ) slider.setTrough( True ) slider.setGroove( False ) slider.setScale( 0.0, 100.0 ) slider.setTotalSteps( 100 ) slider.setPageSteps( 10 ) elif sliderType == 6: slider.setOrientation( Qt.Vertical ) slider.setScalePosition( Qwt.QwtSlider.LeadingScale ) slider.setTrough( True ) slider.setGroove( True ) slider.setScaleEngine( Qwt.QwtLogScaleEngine() ) slider.setStepAlignment( False ) slider.setHandleSize( QSize( 20, 32 ) ) slider.setBorderWidth( 1 ) slider.setScale( 1.0, 1.0e4 ) slider.setTotalSteps( 100 ) slider.setPageSteps( 10 ) slider.setScaleMaxMinor( 9 ) if ( slider ): slider.setObjectName( "Slider %d"%sliderType ) return slider def setNum(self, v ): self.d_label.setText( "%.2f"%v ) class SliderTab( QWidget ): def __init__(self,parent=None): QWidget.__init__(self, parent) self.hLayout = self.createLayout( Qt.Vertical, self ) for i in range(4): self.hLayout.addWidget( SliderBox( i ) ) self.hLayout.addStretch() self.vLayout = self.createLayout( Qt.Horizontal, self ) for i in range(7): self.vLayout.addWidget( SliderBox( i) ) self.mainLayout = self.createLayout( Qt.Horizontal, self ) self.mainLayout.addLayout( self.vLayout ) self.mainLayout.addLayout( self.hLayout, 10 ) def createLayout(self, orientation, widget ): layout = QBoxLayout( QBoxLayout.LeftToRight, widget ) if ( orientation == Qt.Vertical ): layout.setDirection( QBoxLayout.TopToBottom ) layout.setSpacing( 20 ) layout.setContentsMargins( 0, 0, 0, 0) return layout class WheelBox( QWidget ): def __init__(self, orientation, typ, parent=None ): QWidget.__init__(self, parent) box = self.createBox( orientation, typ ) self.d_label = QLabel( self ) self.d_label.setAlignment( Qt.AlignHCenter | Qt.AlignTop ) layout = QVBoxLayout( self ) layout.addWidget( box ) layout.addWidget( self.d_label ) self.setNum( self.d_wheel.value() ) self.d_wheel.valueChanged['double'].connect( self.setNum ) def createBox(self, orientation, typ ): self.d_wheel = Qwt.QwtWheel() self.d_wheel.setValue( 80 ) self.d_wheel.setWheelWidth( 20 ) self.d_wheel.setMass( 1.0 ) self.d_thermo = Qwt.QwtThermo() self.d_thermo.setOrientation( orientation ) if ( orientation == Qt.Horizontal ): self.d_thermo.setScalePosition( Qwt.QwtThermo.LeadingScale ) self.d_wheel.setOrientation( Qt.Vertical ) else: self.d_thermo.setScalePosition( Qwt.QwtThermo.TrailingScale ) self.d_wheel.setOrientation( Qt.Horizontal ) if typ == 0: colorMap = Qwt.QwtLinearColorMap() colorMap.setColorInterval( Qt.blue, Qt.red ) self.d_thermo.setColorMap( colorMap ) elif typ == 1: colorMap = Qwt.QwtLinearColorMap() colorMap.setMode( Qwt.QwtLinearColorMap.FixedColors ) idx = 4 colorMap.setColorInterval( Qt.GlobalColor( idx ), Qt.GlobalColor( idx + 10 ) ) for i in range(10): colorMap.addColorStop( i / 10.0, Qt.GlobalColor( idx + i ) ) self.d_thermo.setColorMap( colorMap ) elif typ == 2: self.d_wheel.setRange( 10, 1000 ) self.d_wheel.setSingleStep( 1.0 ) #self.d_thermo.setScaleEngine( Qwt.QwtLogScaleEngine ) self.d_thermo.setScaleMaxMinor( 10 ) self.d_thermo.setFillBrush( Qt.darkCyan ) self.d_thermo.setAlarmBrush( Qt.magenta ) self.d_thermo.setAlarmLevel( 500.0 ) self.d_wheel.setValue( 800 ) elif typ == 3: self.d_wheel.setRange( -1000, 1000 ) self.d_wheel.setSingleStep( 1.0 ) #self.d_wheel.setPalette( QColor( "Tan" ) ) #scaleEngine = Qwt.QwtLinearScaleEngine() #scaleEngine.setTransformation( Qwt.QwtPowerTransform( 2 ) ) self.d_thermo.setScaleMaxMinor( 5 ) #self.d_thermo.setScaleEngine( scaleEngine ) pal = QPalette() pal.setColor( QPalette.Base, Qt.darkGray ) #pal.setColor( QPalette.ButtonText, QColor( "darkKhaki" ) ) self.d_thermo.setPalette( pal ) elif typ == 4: self.d_wheel.setRange( -100, 300 ) self.d_wheel.setInverted( True ) colorMap = Qwt.QwtLinearColorMap() colorMap.setColorInterval( Qt.darkCyan, Qt.yellow ) self.d_thermo.setColorMap( colorMap ) self.d_wheel.setValue( 243 ) elif typ == 5: self.d_thermo.setFillBrush( Qt.darkCyan ) self.d_thermo.setAlarmBrush( Qt.magenta ) self.d_thermo.setAlarmLevel( 60.0 ) elif typ == 6: self.d_thermo.setOriginMode( Qwt.QwtThermo.OriginMinimum ) #self.d_thermo.setFillBrush( QBrush( "DarkSlateBlue" ) ) #self.d_thermo.setAlarmBrush( QBrush( "DarkOrange" ) ) self.d_thermo.setAlarmLevel( 60.0 ) elif typ == 7: self.d_wheel.setRange( -100, 100 ) self.d_thermo.setOriginMode( Qwt.QwtThermo.OriginCustom ) self.d_thermo.setOrigin( 0.0 ) self.d_thermo.setFillBrush( Qt.darkBlue ) dmin = self.d_wheel.minimum() dmax = self.d_wheel.maximum() #if ( self.d_wheel.isInverted() ): # tmp = dmin # dmin = dmax # dmax = tmp # #swap( dmin, dmax ) self.d_thermo.setScale( dmin, dmax ) self.d_thermo.setValue( self.d_wheel.value() ) self.d_wheel.valueChanged['double'].connect( self.d_thermo.setValue ) box = QWidget() layout = None if ( orientation == Qt.Horizontal ): layout = QHBoxLayout( box ) else: layout = QVBoxLayout( box ) layout.addWidget( self.d_thermo, Qt.AlignCenter ) layout.addWidget( self.d_wheel ) return box def setNum(self, v ): self.d_label.setText( "%.2f"%v ) class WheelTab( QWidget ): def __init__(self,parent=None): QWidget.__init__(self, parent) numBoxes = 4 layout1 = QGridLayout() for i in range(numBoxes): box = WheelBox( Qt.Vertical, i ) layout1.addWidget( box, i // 2, i % 2 ) layout2 = QGridLayout() for i in range( numBoxes ): box = WheelBox( Qt.Horizontal, i + numBoxes ) layout2.addWidget( box, i // 2, i % 2 ) layout = QHBoxLayout( self ) layout.addLayout( layout1, 2 ) #layout.addLayout( layout2, 5 ) class KnobBox( QWidget ): def __init__( self, knobType, parent=None ): QWidget.__init__(self, parent) self.d_knob = self.createKnob( knobType ) self.d_knob.setKnobWidth( 100 ) self.d_label = QLabel( self ) self.d_label.setAlignment( Qt.AlignCenter ) layout = QVBoxLayout( self ) layout.setSpacing( 0 ) layout.addWidget( self.d_knob, 10 ) layout.addWidget( self.d_label ) layout.addStretch( 10 ) self.d_knob.valueChanged['double'].connect(self.setNum ) self.setNum( self.d_knob.value() ) def createKnob( self, knobType ): knob = Qwt.QwtKnob() knob.setTracking( True ) if knobType == 0: knob.setKnobStyle( Qwt.QwtKnob.Sunken ) knob.setMarkerStyle( Qwt.QwtKnob.Nub ) knob.setWrapping( True ) knob.setNumTurns( 4 ) knob.setScaleStepSize( 10.0 ) knob.setScale( 0, 400 ) knob.setTotalSteps( 400 ) elif knobType == 1: knob.setKnobStyle( Qwt.QwtKnob.Sunken ) knob.setMarkerStyle( Qwt.QwtKnob.Dot ) elif knobType == 2: knob.setKnobStyle( Qwt.QwtKnob.Sunken ) knob.setMarkerStyle( Qwt.QwtKnob.Tick ) #QwtLinearScaleEngine *scaleEngine = new QwtLinearScaleEngine( 2 ) #scaleEngine.setTransformation( new QwtPowerTransform( 2 ) ) #knob.setScaleEngine( scaleEngine ) """QList< double > ticks[ QwtScaleDiv.NTickTypes ] ticks[ QwtScaleDiv.MajorTick ] << 0 << 4 << 16 << 32 << 64 << 96 << 128 ticks[ QwtScaleDiv.MediumTick ] << 24 << 48 << 80 << 112 ticks[ QwtScaleDiv.MinorTick ] << 0.5 << 1 << 2 << 7 << 10 << 13 << 20 << 28 << 40 << 56 << 72 << 88 << 104 << 120 knob.setScale( QwtScaleDiv( 0, 128, ticks ) )""" knob.setTotalSteps( 100 ) knob.setStepAlignment( False ) knob.setSingleSteps( 1 ) knob.setPageSteps( 5 ) elif knobType == 3: knob.setKnobStyle( Qwt.QwtKnob.Flat ) knob.setMarkerStyle( Qwt.QwtKnob.Notch ) knob.setScaleEngine( Qwt.QwtLogScaleEngine() ) knob.setScaleStepSize( 1.0 ) knob.setScale( 0.1, 1000.0 ) knob.setScaleMaxMinor( 10 ) elif knobType == 4: knob.setKnobStyle( Qwt.QwtKnob.Raised ) knob.setMarkerStyle( Qwt.QwtKnob.Dot ) knob.setWrapping( True ) elif knobType == 5: knob.setKnobStyle( Qwt.QwtKnob.Styled ) knob.setMarkerStyle( Qwt.QwtKnob.Triangle ) knob.setTotalAngle( 180.0 ) knob.setScale( 100, -100 ) return knob def setNum( self, v ): self.d_label.setText( "%.2f"%v ) class KnobTab( QWidget ): def __init__(self,parent=None): QWidget.__init__(self, parent) layout = QGridLayout( self ) numRows = 3 for i in range(2*numRows): knobBox = KnobBox( i, self ) layout.addWidget( knobBox, i // numRows, i % numRows ) a = QApplication(sys.argv) tabWidget = QTabWidget() sliderTab = SliderTab() #print(type(sliderTab)) #sliderTab.setAutoFillBackground( True ) #sliderTab.setPalette( QColor( "DimGray" ) ) wheelTab = WheelTab() #wheelTab.setAutoFillBackground( True ) #wheelTab.setPalette( QColor( "Silver" ) ) knobTab = KnobTab() #knobTab.setAutoFillBackground( True ) #knobTab.setPalette( Qt.darkGray ) #dialTab = DialTab() #dialTab.setAutoFillBackground( True ) #dialTab.setPalette( Qt.darkGray ) tabWidget.addTab( sliderTab, "Slider" ) tabWidget.addTab( wheelTab, "Wheel/Thermo" ) tabWidget.addTab( knobTab, "Knob" ) #tabWidget.addTab( dialTab, "Dial" ) tabWidget.resize( 800, 600 ) tabWidget.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/curvdemo1.py000077500000000000000000000114651377204562100200720ustar00rootroot00000000000000#!/usr/bin/python import sys import math import numpy as np from PyQt5 import Qwt from PyQt5.QtCore import Qt, QSize, QRectF from PyQt5.QtGui import QPen, QBrush, QPainter, QFont from PyQt5.QtWidgets import QApplication, QFrame Size = 27 CurvCnt = 6 xval = np.zeros(Size,float) yval = np.zeros(Size,float) xMap = Qwt.QwtScaleMap() yMap = Qwt.QwtScaleMap() class MainWin(QFrame): def __init__(self): QFrame.__init__(self) self.d_curves = [None]*CurvCnt xMap.setScaleInterval( -0.5, 10.5 ) yMap.setScaleInterval( -1.1, 1.1 ) # Frame style FIXME This doesn't seem to work properly self.setFrameStyle( QFrame.Box | QFrame.Raised ) self.setLineWidth( 2 ) self.setMidLineWidth( 3 ) # Calculate values for i in range(Size): xval[i] = i * 10.0 / ( Size - 1.0 ) yval[i] = math.sin( xval[i] ) * math.cos( 2.0 * xval[i] ) # define curve styles i = 0 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Cross, QBrush(Qt.NoBrush), QPen( Qt.black ), QSize( 5, 5 ) ) ) self.d_curves[i].setPen( Qt.darkGreen ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.Lines ) self.d_curves[i].setCurveAttribute( Qwt.QwtPlotCurve.Fitted ) i += 1 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.Ellipse, Qt.yellow, QPen( Qt.blue ), QSize( 5, 5 ) ) ) self.d_curves[i].setPen( Qt.red ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.Sticks ) i += 1 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setPen( Qt.darkBlue ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.Lines ) i += 1 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setPen( Qt.darkBlue ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.Lines ) self.d_curves[i].setRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) i += 1 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setPen( Qt.darkCyan ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.Steps ) i += 1 self.d_curves[i] = Qwt.QwtPlotCurve() self.d_curves[i].setSymbol( Qwt.QwtSymbol( Qwt.QwtSymbol.XCross, QBrush(Qt.NoBrush), QPen( Qt.darkMagenta ), QSize( 5, 5 ) ) ) self.d_curves[i].setStyle( Qwt.QwtPlotCurve.NoCurve ) # attach data for i in range(CurvCnt): self.d_curves[i].setSamples( xval, yval ) def shiftDown(self, rect, offset ): rect.translate( 0, offset ) def paintEvent( self, event ): #QFrame.paintEvent( event ) painter = QPainter( self ) painter.setClipRect( self.contentsRect() ) self.drawContents( painter ) # REDRAW CONTENTS def drawContents( self, painter ): r = self.contentsRect() deltay = r.height() // CurvCnt - 1 r.setHeight( deltay ) # draw curves for i in range( CurvCnt ): xMap.setPaintInterval( r.left(), r.right() ) yMap.setPaintInterval( r.top(), r.bottom() ) painter.setRenderHint( QPainter.Antialiasing, self.d_curves[i].testRenderHint( Qwt.QwtPlotItem.RenderAntialiased ) ) self.d_curves[i].draw( painter, xMap, yMap, QRectF(r) ) self.shiftDown( r, deltay ) # draw titles r = self.contentsRect() # reset r painter.setFont( QFont( "Helvetica", 8 ) ) alignment = Qt.AlignTop | Qt.AlignHCenter painter.setPen( Qt.black ) painter.drawText( 0, r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: Line/Fitted, Symbol: Cross" ) self.shiftDown( r, deltay ) painter.drawText( 0, r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: Sticks, Symbol: Ellipse" ) self.shiftDown( r, deltay ) painter.drawText( 0 , r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: Lines, Symbol: None" ) self.shiftDown( r, deltay ) painter.drawText( 0 , r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: Lines, Symbol: None, Antialiased" ) self.shiftDown( r, deltay ) painter.drawText( 0, r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: Steps, Symbol: None" ) self.shiftDown( r, deltay ) painter.drawText( 0, r.top(), r.width(), painter.fontMetrics().height(), alignment, "Style: NoCurve, Symbol: XCross" ) if __name__ == '__main__': a = QApplication(sys.argv) a.setStyle( "Windows" ) w = MainWin() w.resize( 300, 600 ) w.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/dials.py000077500000000000000000000371771377204562100172710ustar00rootroot00000000000000#!/usr/bin/python3 # python radio.py # Tested for python3 Qt5. Crashes if mouse is over plot canvas import sys from PyQt5 import Qwt from PyQt5.QtCore import Qt, QTimer, QRectF, QPointF, qRound # pyqtSignal, Qt, QSize, QBasicTimer from PyQt5.QtGui import QColor, QPalette, QPainterPath, QPen #, QPixmap, QFont, QIcon, QLinearGradient from PyQt5.QtWidgets import (QWidget, QApplication, QTabWidget, QGridLayout ) #from PyQt5.QtPrintSupport import QPrintDialog, QPrinter M_PI=3.141 class CompassGrid( QWidget ): #QFrame( parent ) def __init__(self, parent=None): QWidget.__init__(self, parent) p = QPalette() p.setColor( self.backgroundRole(), Qt.gray ) self.setPalette( p ) self.setAutoFillBackground( True ) layout = QGridLayout( self ) layout.setSpacing( 5 ) #layout.setMargin( 0 ) for i in range(6): compass = self.createCompass( i ) layout.addWidget( compass, i // 3, i % 3 ) #for i in range(layout.columnCount()): # layout.setColumnStretch( i, 1 ) def createCompass( self, pos ): palette0 = QPalette() for c in range(QPalette.NColorRoles): colorRole = QPalette.ColorRole( c ) palette0.setColor( colorRole, QColor() ) #palette0.setColor( QPalette.Base, palette().color( QPalette.backgroundRole() ).light( 120 ) ) palette0.setColor( QPalette.WindowText, palette0.color( QPalette.Base ) ) compass = Qwt.QwtCompass( self ) compass.setLineWidth( 4 ) compass.setFrameShadow(Qwt.QwtCompass.Sunken) # pos <= 2 ? QwtCompass.Sunken : QwtCompass.Raised ) if pos == 0: #A compass with a rose and no needle. Scale and rose are rotating. compass.setMode( Qwt.QwtCompass.RotateScale ) rose = Qwt.QwtSimpleCompassRose( 16, 2 ) rose.setWidth( 0.15 ) compass.setRose( rose ) elif pos == 1: #A windrose, with a scale indicating the main directions only map = {} map[0.0] = "N" map[90.0] = "E" map[180.0] = "S" map[270.0] = "W" compass.setScaleDraw( Qwt.QwtCompassScaleDraw( map ) ) rose = Qwt.QwtSimpleCompassRose( 4, 1 ) compass.setRose( rose ) compass.setNeedle( Qwt.QwtCompassWindArrow( Qwt.QwtCompassWindArrow.Style2 ) ) compass.setValue( 60.0 ) elif pos == 2: #A compass with a rotating needle in darkBlue. Shows #a ticks for each degree. palette0.setColor( QPalette.Base, Qt.darkBlue ) palette0.setColor( QPalette.WindowText, QColor( Qt.darkBlue ))#.dark( 120 ) ) palette0.setColor( QPalette.Text, Qt.white ) scaleDraw = Qwt.QwtCompassScaleDraw() scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Ticks, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Labels, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Backbone, False ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MinorTick, 1 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MediumTick, 1 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MajorTick, 3 ) compass.setScaleDraw( scaleDraw ) compass.setScaleMaxMajor( 36 ) compass.setScaleMaxMinor( 5 ) compass.setNeedle( Qwt.QwtCompassMagnetNeedle( Qwt.QwtCompassMagnetNeedle.ThinStyle ) ) compass.setValue( 220.0 ) elif pos == 3: #A compass without a frame, showing numbers as tick labels. #The origin is at 220.0 palette0.setColor( QPalette.Base, self.palette().color( self.backgroundRole() ) ) palette0.setColor( QPalette.WindowText, Qt.blue ) compass.setLineWidth( 0 ) map = {} for d in range(0,360,60): map[d] = "%.0f"%(d*1.0) scaleDraw = Qwt.QwtCompassScaleDraw( map ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Ticks, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Labels, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Backbone, True ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MinorTick, 0 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MediumTick, 0 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MajorTick, 3 ) compass.setScaleDraw( scaleDraw ) compass.setScaleMaxMajor( 36 ) compass.setScaleMaxMinor( 5 ) compass.setNeedle( Qwt.QwtDialSimpleNeedle( Qwt.QwtDialSimpleNeedle.Ray, True, Qt.white ) ) compass.setOrigin( 220.0 ) compass.setValue( 20.0 ) elif pos == 4: #A compass showing another needle scaleDraw = Qwt.QwtCompassScaleDraw() scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Ticks, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Labels, True ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Backbone, False ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MinorTick, 0 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MediumTick, 0 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MajorTick, 3 ) compass.setScaleDraw( scaleDraw ) compass.setNeedle( Qwt.QwtCompassMagnetNeedle( Qwt.QwtCompassMagnetNeedle.TriangleStyle, Qt.white, Qt.red ) ) compass.setValue( 220.0 ) elif pos == 5: #A compass with a yellow on black ray palette0.setColor( QPalette.WindowText, Qt.black ) compass.setNeedle( Qwt.QwtDialSimpleNeedle( Qwt.QwtDialSimpleNeedle.Ray, False, Qt.yellow ) ) compass.setValue( 315.0 ) newPalette = compass.palette() for c in range(QPalette.NColorRoles): colorRole = QPalette.ColorRole( c ) if ( palette0.color( colorRole ).isValid() ): newPalette.setColor( colorRole, palette0.color( colorRole ) ) for i in range(QPalette.NColorGroups): colorGroup = QPalette.ColorGroup( i ) light = newPalette.color( colorGroup, QPalette.Base )#.light( 170 ) dark = newPalette.color( colorGroup, QPalette.Base )#.dark( 170 ) #mid = compass.frameShadow() == QwtDial.Raised # ? newPalette.color( colorGroup, QPalette.Base ).dark( 110 ) # : newPalette.color( colorGroup, QPalette.Base ).light( 110 ) mid = newPalette.color( colorGroup, QPalette.Base )#.dark( 110 ) newPalette.setColor( colorGroup, QPalette.Dark, dark ) newPalette.setColor( colorGroup, QPalette.Mid, mid ) newPalette.setColor( colorGroup, QPalette.Light, light ) compass.setPalette( newPalette ) return compass class SpeedoMeter( Qwt.QwtDial ): #QwtDial( parent ), def __init__(self,parent = None): Qwt.QwtDial.__init__(self,parent) self.d_label = "km/h" scaleDraw = Qwt.QwtRoundScaleDraw() scaleDraw.setSpacing( 8 ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Backbone, False ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MinorTick, 0 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MediumTick, 4 ) scaleDraw.setTickLength( Qwt.QwtScaleDiv.MajorTick, 8 ) self. setScaleDraw( scaleDraw ) self.setWrapping( False ) self.setReadOnly( True ) self.setOrigin( 135.0 ) self.setScaleArc( 0.0, 270.0 ) needle = Qwt.QwtDialSimpleNeedle( Qwt.QwtDialSimpleNeedle.Arrow, True, Qt.red, QColor( Qt.gray ))#.light( 130 ) ) self.setNeedle( needle ) def setLabel( self, label ): self.d_label = label self.update() def label(self): return self.d_label def drawScaleContents( self, painter, center, radius ): rect = QRectF( 0.0, 0.0, 2.0 * radius, 2.0 * radius - 10.0 ) rect.moveCenter( center ) color = self.palette().color( QPalette.Text ) painter.setPen( color ) flags = Qt.AlignBottom | Qt.AlignHCenter painter.drawText( rect, flags, self.d_label ) class AttitudeIndicatorNeedle(Qwt.QwtDialNeedle): def __init__(self, color=None): Qwt.QwtDialNeedle.__init__(self) palette = QPalette() palette.setColor( QPalette.Text, color ) #self.setPalette( palette ) def rawNeedle( self, painter, length, colorGroup ): triangleSize = length * 0.1 pos = length - 2.0 path = QPainterPath() path.moveTo( pos, 0 ) path.lineTo( pos - 2 * triangleSize, triangleSize ) path.lineTo( pos - 2 * triangleSize, -triangleSize ) path.closeSubpath() painter.setBrush( self.palette().brush( colorGroup, QPalette.Text ) ) painter.drawPath( path ) l = length - 2 painter.setPen( QPen( self.palette().color( colorGroup, QPalette.Text ), 3 ) ) painter.drawLine( QPointF( 0.0, -l ), QPointF( 0.0, l ) ) class AttitudeIndicator(Qwt.QwtDial): def __init__(self, parent = None): Qwt.QwtDial.__init__( self, parent ) self.d_gradient = 0.0 scaleDraw = Qwt.QwtRoundScaleDraw() scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Backbone, False ) scaleDraw.enableComponent( Qwt.QwtAbstractScaleDraw.Labels, False ) self.setScaleDraw( scaleDraw ) #self.setMode( Qwt.RotateScale ) self.setWrapping( True ) self.setOrigin( 270.0 ) self.setScaleMaxMinor( 0 ) self.setScaleStepSize( 30.0 ) self.setScale( 0.0, 360.0 ) color = self.palette().color( QPalette.Text ) self.setNeedle( AttitudeIndicatorNeedle( color ) ) def setGradient( self, gradient ): if ( gradient < -1.0 ): gradient = -1.0 elif ( gradient > 1.0 ): gradient = 1.0 if ( self.d_gradient != gradient ): self.d_gradient = gradient self.update() def drawScale( self, painter, center, radius ): offset = 4.0 p0 = self.qwtPolar2Pos( center, offset, 1.5 * M_PI ) w = self.innerRect().width() path = QPainterPath() path.moveTo( Qwt.qwtPolar2Pos( p0, w, 0.0 ) ) path.lineTo( Qwt.qwtPolar2Pos( path.currentPosition(), 2 * w, M_PI ) ) path.lineTo( Qwt.qwtPolar2Pos( path.currentPosition(), w, 0.5 * M_PI ) ) path.lineTo( Qwt.qwtPolar2Pos( path.currentPosition(), w, 0.0 ) ) painter.save() painter.setClipPath( path ) # swallow 180 - 360 degrees Qwt.QwtDial.drawScale( painter, center, radius ) painter.restore() def drawScaleContents( self, painter, double ): dir = 360 - qRound( self.origin() - self.value() ) # counter clockwise arc = 90 + qRound( self.gradient() * 90 ) skyColor = QColor( 38, 151, 221 ) painter.save() painter.setBrush( skyColor ) painter.drawChord( self.scaleInnerRect(), ( dir - arc ) * 16, 2 * arc * 16 ) painter.restore() def keyPressEvent( self, event ): k = event.key() if k == Qt.Key_Plus: self.setGradient( self.gradient() + 0.05 ) elif k == Qt.Key_Minus: self.setGradient( self.gradient() - 0.05 ) else: Qwt.QwtDial.keyPressEvent( event ) def angle(self): return self.value() def gradient(self): return self.d_gradient def setAngle( self, angle ): self.setValue( angle ) class CockpitGrid( QWidget ): def __init__(self, parent = None): QWidget.__init__(self, parent) self.setAutoFillBackground( True ) #self.setPalette( self.colorTheme( QColor( Qt.darkGray )))#.dark( 150 ) ) ) layout = QGridLayout( self ) layout.setSpacing( 5 ) #layout.setMargin( 0 ) for i in range(2): # FIXME. Should be 3 but program crashes for the third one. dial = self.createDial( i ) layout.addWidget( dial, 0, i ) for i in range(layout.columnCount()): layout.setColumnStretch( i, 1 ) def createDial( self, pos ): dial = None if pos == 0: self.d_clock = Qwt.QwtAnalogClock( ) # disable minor ticks #d_clock.scaleDraw().setTickLength( QwtScaleDiv.MinorTick, 0 ) knobColor = QColor( Qt.gray ) # .light( 130 ) for i in range(Qwt.QwtAnalogClock.NHands): handColor = QColor( Qt.gray ) #.light( 150 ) width = 8 if i == Qwt.QwtAnalogClock.SecondHand: handColor = Qt.gray width = 5 hand = Qwt.QwtDialSimpleNeedle( Qwt.QwtDialSimpleNeedle.Arrow, True, handColor, knobColor ) hand.setWidth( width ) self.d_clock.setHand( Qwt.QwtAnalogClock.Hand( i ), hand ) timer = QTimer( self.d_clock ) timer.timeout.connect(self.d_clock.setCurrentTime) timer.start( 1000 ) dial = self.d_clock elif pos == 1: self.d_speedo = SpeedoMeter( self ) self.d_speedo.setScaleStepSize( 20.0 ) self.d_speedo.setScale( 0.0, 240.0 ) self.d_speedo.scaleDraw().setPenWidth( 2 ) timer = QTimer( self.d_speedo ) timer.timeout.connect(self.changeSpeed ) timer.start( 50 ) dial = self.d_speedo elif pos == 2: self.d_ai = AttitudeIndicator( self ) self.d_ai.scaleDraw().setPenWidth( 3 ) gradientTimer = QTimer( self.d_ai ) gradientTimer.timeout.connect(self.changeGradient ) gradientTimer.start( 100 ) angleTimer = QTimer( self.d_ai ) angleTimer.timeout.connect( self.changeAngle ) angleTimer.start( 100 ) dial = self.d_ai if ( dial ): dial.setReadOnly( True ) dial.setLineWidth( 4 ) dial.setFrameShadow(Qwt.QwtDial.Sunken ) return dial def colorTheme( self, base ): palette = QPalette palette.setColor( QPalette.Base, base ) palette.setColor( QPalette.Window, base.dark( 150 ) ) palette.setColor( QPalette.Mid, base.dark( 110 ) ) palette.setColor( QPalette.Light, base.light( 170 ) ) palette.setColor( QPalette.Dark, base.dark( 170 ) ) palette.setColor( QPalette.Text, base.dark( 200 ).light( 800 ) ) palette.setColor( QPalette.WindowText, base.dark( 200 ) ) return palette def changeSpeed(self): offset = 0.8 speed = self.d_speedo.value() if ( ( speed < 7.0 and offset < 0.0 ) or ( speed > 203.0 and offset > 0.0 ) ): offset = -offset counter = 0 """switch( counter++ % 12 ) { case 0: case 2: case 7: case 8: break default: }""" self.d_speedo.setValue( speed + offset ) def changeAngle(self): offset = 0.05 angle = self.d_ai.angle() if ( angle > 180.0 ): angle -= 360.0 if ( ( angle < -5.0 and offset < 0.0 ) or ( angle > 5.0 and offset > 0.0 ) ): offset = -offset self.d_ai.setAngle( angle + offset ) def changeGradient(self): offset = 0.005 gradient = self.d_ai.gradient() if ( ( gradient < -0.05 and offset < 0.0 ) or ( gradient > 0.05 and offset > 0.0 ) ): offset = -offset self.d_ai.setGradient( gradient + offset ) a = QApplication(sys.argv) tabWidget = QTabWidget() tabWidget.addTab(CompassGrid(),"Compass") tabWidget.addTab(CockpitGrid(),"Cockpit") tabWidget.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/radio.py000077500000000000000000000245671377204562100172720ustar00rootroot00000000000000#!/usr/bin/python3 # python radio.py # Tested for python3 Qt5. Crashes if mouse is over plot canvas import sys import math #import Qwt from PyQt5 import Qwt import numpy as np from PyQt5.QtCore import pyqtSignal, Qt, QSize, QBasicTimer from PyQt5.QtGui import QColor, QPixmap, QFont, QIcon, QPalette, QLinearGradient from PyQt5.QtWidgets import (QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QSizePolicy, QVBoxLayout, QFrame ) #from PyQt5.QtPrintSupport import QPrintDialog, QPrinter M_PI = 3.14159 class Knob(QWidget): def __init__(self, title, min, max, parent ): QWidget.__init__(self, parent) self.d_knob = Qwt.QwtKnob( self ) self.d_knob.setScale( min, max ) self.d_knob.setTotalSteps( 0 ) # disable self.d_knob.setScaleMaxMajor( 10 ) self.d_knob.setKnobStyle( Qwt.QwtKnob.Raised ) self.d_knob.setKnobWidth( 50 ) self.d_knob.setBorderWidth( 2 ) self.d_knob.setMarkerStyle( Qwt.QwtKnob.Notch ) self.d_knob.setMarkerSize( 8 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MinorTick, 4 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MediumTick, 4 ) self.d_knob.scaleDraw().setTickLength( Qwt.QwtScaleDiv.MajorTick, 6 ) self.d_label = QLabel( title, self ) self.d_label.setAlignment( Qt.AlignTop | Qt.AlignHCenter ) self.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding ) def sizeHint(self): sz1 = self.d_knob.sizeHint() sz2 = self.d_label.sizeHint() w = max( sz1.width(), sz2.width() ) h = sz1.height() + sz2.height() off = math.ceil( self.d_knob.scaleDraw().extent( self.d_knob.font() ) ) off -= 10 # spacing return QSize( w, h - off ) def setValue( self, value ): self.d_knob.setValue( value ) def value(self): return self.d_knob.value() def resizeEvent( self, e ): sz = e.size() h = self.d_label.sizeHint().height() self.d_label.setGeometry( 0, sz.height() - h, sz.width(), h ) h = self.d_knob.sizeHint().height() off = math.ceil( self.d_knob.scaleDraw().extent( self.d_knob.font() ) ) off -= 10 # spacing self.d_knob.setGeometry( 0, self.d_label.pos().y() - h + off, sz.width(), h ) class Thermo(QWidget): def __init__( self, title, parent ): QWidget.__init__(self, parent) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setPipeWidth( 6 ) self.d_thermo.setScale( -40, 10 ) self.d_thermo.setFillBrush( Qt.green ) self.d_thermo.setAlarmBrush( Qt.red ) self.d_thermo.setAlarmLevel( 0.0 ) self.d_thermo.setAlarmEnabled( True ) label = QLabel( title, self ) label.setAlignment( Qt.AlignTop | Qt.AlignLeft ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) self.layout.setSpacing( 0 ) self.layout.addWidget( self.d_thermo, 10 ) self.layout.addWidget( label ) def setValue( self, value ): self.d_thermo.setValue( value ) class AmpFrame( QFrame ): def __init__(self, p): QFrame.__init__( self, p ) self.phs = 0 self.d_knbVolume = Knob( "Volume", 0.0, 10.0, self ) self.d_knbBalance = Knob( "Balance", -10.0, 10.0, self ) self.d_knbTreble = Knob( "Treble", -10.0, 10.0, self ) self.d_knbBass = Knob( "Bass", -10.0, 10.0, self ) self.d_thmLeft = Thermo( "Left [dB]", self ) self.d_thmRight = Thermo( "Right [dB]", self ) self.layout = QHBoxLayout( self ) self.layout.setSpacing( 0 ) #self.layout.setMargin( 10 ) self.layout.addWidget( self.d_knbVolume ) self.layout.addWidget( self.d_knbBalance) self.layout.addWidget( self.d_knbTreble) self.layout.addWidget( self.d_knbBass ) self.layout.addSpacing( 20 ) self.layout.addStretch( 10 ) self.layout.addWidget( self.d_thmLeft ) self.layout.addSpacing( 10 ) self.layout.addWidget( self.d_thmRight ) self.d_knbVolume.setValue( 7.0 ) self.startTimer( 50 ) self.d_master = 0 def timerEvent( self, event ): #self.phs = 0.0 # This amplifier generates its own input signal... sig_bass = ( 1.0 + 0.1 * self.d_knbBass.value() ) * math.sin( 13.0 * self.phs ) sig_mid_l = math.sin( 17.0 * self.phs ) sig_mid_r = math.cos( 17.5 * self.phs ) sig_trbl_l = 0.5 * ( 1.0 + 0.1 * self.d_knbTreble.value() ) * math.sin( 35.0 * self.phs ) sig_trbl_r = 0.5 * ( 1.0 + 0.1 * self.d_knbTreble.value() ) * math.sin( 34.0 * self.phs ) sig_l = 0.05 * self.d_master * self.d_knbVolume.value() * ( sig_bass + sig_mid_l + sig_trbl_l )*( sig_bass + sig_mid_l + sig_trbl_l ) sig_r = 0.05 * self.d_master * self.d_knbVolume.value() * ( sig_bass + sig_mid_r + sig_trbl_r )*( sig_bass + sig_mid_r + sig_trbl_r ) balance = 0.1 * self.d_knbBalance.value() if ( balance > 0 ): sig_l *= ( 1.0 - balance ) else: sig_r *= ( 1.0 + balance ) if ( sig_l > 0.01 ): sig_l = 20.0 * math.log10( sig_l ) else: sig_l = -40.0 if ( sig_r > 0.01 ): sig_r = 20.0 * math.log10( sig_r ) else: sig_r = - 40.0 self.d_thmLeft.setValue( sig_l ) self.d_thmRight.setValue( sig_r ) self.phs += M_PI / 100 if ( self.phs > M_PI ): self.phs = 0 def setMaster( self, v ): self.d_master = v class TuningThermo(QWidget): def __init__(self, parent): QWidget.__init__( self, parent ) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setOrientation( Qt.Horizontal ) self.d_thermo.setScalePosition( Qwt.QwtThermo.NoScale ) self.d_thermo.setScale( 0.0, 1.0 ) self.d_thermo.setFillBrush( Qt.green ) self.label = QLabel( "Tuning", self ) self.label.setAlignment( Qt.AlignCenter ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) FIXME self.layout.addWidget( self.d_thermo ) self.layout.addWidget( self.label ) self.setFixedWidth( 3 * self.label.sizeHint().width() ) def setValue( self, value ): self.d_thermo.setValue( value ) class TunerFrame( QWidget ): fieldChanged = pyqtSignal(float) def __init__(self, parent): QWidget.__init__(self, parent ) self.freqMin = 87.5 self.freqMax = 108 self.d_sliderFrequency = Qwt.QwtSlider( self ) self.d_sliderFrequency.setOrientation( Qt.Horizontal ) self.d_sliderFrequency.setScalePosition( Qwt.QwtSlider.TrailingScale ) self.d_sliderFrequency.setScale( self.freqMin, self.freqMax ) #self.d_sliderFrequency.setTotalSteps( math.round( ( self.freqMax - self.freqMin ) / 0.01 ) ) FIXME self.d_sliderFrequency.setTotalSteps( int(math.ceil( ( self.freqMax - self.freqMin ) / 0.01 ) ) ) self.d_sliderFrequency.setSingleSteps( 1 ) self.d_sliderFrequency.setPageSteps( 10 ) self.d_sliderFrequency.setScaleMaxMinor( 5 ) self.d_sliderFrequency.setScaleMaxMajor( 12 ) self.d_sliderFrequency.setHandleSize( QSize( 80, 20 ) ) self.d_sliderFrequency.setBorderWidth( 1 ) self.d_thermoTune = TuningThermo( self ) self.d_wheelFrequency = Qwt.QwtWheel( self ) self.d_wheelFrequency.setMass( 0.5 ) self.d_wheelFrequency.setRange( 87.5, 108 ) self.d_wheelFrequency.setSingleStep( 0.01 ) self.d_wheelFrequency.setPageStepCount( 10 ) self.d_wheelFrequency.setTotalAngle( 3600.0 ) self.d_wheelFrequency.setFixedHeight( 30 ) self.d_wheelFrequency.valueChanged['double'].connect(self.adjustFreq ) self.d_sliderFrequency.valueChanged['double'].connect(self.adjustFreq ) self.mainLayout = QVBoxLayout( self ) #self.mainLayout.setMargin( 10 ) self.mainLayout.setSpacing( 5 ) self.mainLayout.addWidget( self.d_sliderFrequency ) self.hLayout = QHBoxLayout() #self.hLayout.setMargin( 0 ) #self.hLayout.addWidget( self.d_thermoTune, 0 ) self.hLayout.addStretch( 5 ) self.hLayout.addWidget( self.d_wheelFrequency, 2 ) self.mainLayout.addLayout( self.hLayout ) def adjustFreq( self, frq ): factor = 13.0 / ( 108 - 87.5 ) x = ( frq - 87.5 ) * factor field = ( math.sin( x ) * math.cos( 4.0 * x ) )*( math.sin( x ) * math.cos( 4.0 * x ) ) self.d_thermoTune.setValue( field ) if ( self.d_sliderFrequency.value() != frq ): self.d_sliderFrequency.setValue( frq ) if ( self.d_wheelFrequency.value() != frq ): self.d_wheelFrequency.setValue( frq ) self.fieldChanged.emit( field ) def setFreq( self, frq ): self.d_wheelFrequency.setValue( frq ) class MainWindow(QWidget): def __init__(self): QWidget.__init__(self) self.frmTuner = TunerFrame( self ) #self.frmTuner.setFrameStyle( QFrame.Panel | QFrame.Raised ) self.frmAmp = AmpFrame( self ) self.frmAmp.setFrameStyle( QFrame.Panel | QFrame.Raised ) self.layout = QVBoxLayout( self ) #self.layout.setMargin( 0 ) self.layout.setSpacing( 0 ) self.layout.addWidget( self.frmTuner ) self.layout.addWidget( self.frmAmp ) self.frmTuner.fieldChanged['double'].connect(self.frmAmp.setMaster) self.frmTuner.setFreq( 90.0 ) self.setPalette( QPalette( QColor( 192, 192, 192 ) ) ) self.updateGradient() def resizeEvent(self, QResizeEvent ): # Qt 4.7.1: QGradient.StretchToDeviceMode is buggy on X11 self.updateGradient() def updateGradient(self): self.pal = QPalette() self.buttonColor = self.pal.color( QPalette.Button ) self.midLightColor = self.pal.color( QPalette.Midlight ) #self.gradient = QLinearGradient( rect().topLeft(), rect().topRight() ) FIXME self.gradient = QLinearGradient( ) self.gradient.setColorAt( 0.0, self.midLightColor ) self.gradient.setColorAt( 0.7, self.buttonColor ) self.gradient.setColorAt( 1.0, self.buttonColor ) self.pal.setBrush( QPalette.Window, self.gradient ) self.setPalette( self.pal ) a = QApplication(sys.argv) m = MainWindow() m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/scatterplot.py000077500000000000000000000066411377204562100205310ustar00rootroot00000000000000#!/usr/bin/python3 import sys import math #import Qwt from PyQt5 import Qwt import numpy as np from PyQt5.QtCore import Qt, QSize, qrand, QPointF from PyQt5.QtGui import QColor, QPixmap, QFont, QIcon, QPen, QPolygonF from PyQt5.QtWidgets import QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication def randomValue(): #a number between [ 0.0, 1.0 ] return ( qrand() % 100000 ) / 100000.0 class DistancePicker(Qwt.QwtPlotPicker): def __init__(self, canvas): Qwt.QwtPlotPicker.__init__(self, canvas) self.setTrackerMode( Qwt.QwtPicker.ActiveOnly ) self.setStateMachine( Qwt.QwtPickerDragLineMachine() ) self.setRubberBand( Qwt.QwtPlotPicker.PolygonRubberBand ) def trackerTextF(self, pos ): text = QwtText() points = self.selection(); if ( not points.isEmpty() ): #QString num #num.setNum( QLineF( pos, invTransform( points[0] ) ).length() ) num = "123" bg = QColor( Qt.white ) bg.setAlpha( 200 ) text.setBackgroundBrush( QBrush( bg ) ) text.setText( num ) return text class Plot( Qwt.QwtPlot ): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent) self.canvas().setStyleSheet( "border: 2px solid Black;" "border-radius: 15px;" "background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1," "stop: 0 LemonChiffon, stop: 1 PaleGoldenrod );" ) # attach curve self.d_curve = Qwt.QwtPlotCurve( "Scattered Points" ) self.d_curve.setPen( QColor( "Purple" ) ) # when using QwtPlotCurve.ImageBuffer simple dots can be # rendered in parallel on multicore systems. self.d_curve.setRenderThreadCount( 0 ) # 0: use QThread.idealThreadCount() self.d_curve.attach( self ) self.setSymbol( None ) # panning with the left mouse button Qwt.QwtPlotPanner( self.canvas() ) # zoom in/out with the wheel #magnifier = Qwt.QwtPlotMagnifier( self.canvas() ) FIXME #magnifier.setMouseButton( Qt.NoButton ) # distanve measurement with the right mouse button self.picker = DistancePicker( self.canvas() ) self.picker.setMousePattern( Qwt.QwtPlotPicker.MouseSelect1, Qt.RightButton ) self.picker.setRubberBandPen( QPen( Qt.blue ) ) def setSymbol( self, symbol ): self.d_curve.setSymbol( symbol ) if ( symbol == None): self.d_curve.setStyle( Qwt.QwtPlotCurve.Dots ) def setSamples(self, samples ): self.d_curve.setPaintAttribute( Qwt.QwtPlotCurve.ImageBuffer, samples.size() > 1000 ) self.d_curve.setSamples( samples ) class MainWindow(QMainWindow): def __init__(self, *args): QMainWindow.__init__(self, *args) self.d_plot = Plot( self ) self.d_plot.setTitle( "Scatter Plot" ) self.setCentralWidget( self.d_plot ) # a million points self.setSamples( 100000 ); def setSamples(self, numPoints ): samples = QPolygonF() for i in range(numPoints): x = randomValue() * 24.0 + 1.0; y = math.log( 10.0 * ( x - 1.0 ) + 1.0 ) * ( randomValue() * 0.5 + 0.9 ) samples += QPointF( x, y ) self.d_plot.setSamples( samples ) a = QApplication( sys.argv ) m = MainWindow() m.resize( 800, 600 ) m.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/simpleplot.py000077500000000000000000000015601377204562100203500ustar00rootroot00000000000000#!/usr/bin/python # python simpleplot.py # Tested for python3 Qt5 import sys #import Qwt from PyQt5 import Qwt import numpy as np from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QBrush, QPen from PyQt5.QtWidgets import QApplication a = QApplication(sys.argv) plot=Qwt.QwtPlot() plot.setTitle("Plot Demo") plot.setCanvasBackground(Qt.white) plot.insertLegend( Qwt.QwtLegend() ) grid = Qwt.QwtPlotGrid() grid.attach( plot ) curve = Qwt.QwtPlotCurve() curve.setTitle("Some Points") curve.setPen(Qt.blue,4) curve.setRenderHint( Qwt.QwtPlotItem.RenderAntialiased, True ); symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.Ellipse, QBrush( Qt.yellow ), QPen( Qt.red, 2 ), QSize( 8, 8 ) ); curve.setSymbol( symbol ) x=np.arange(0,10,0.1) y=np.sin(x) curve.setSamples(x,y) curve.attach(plot) plot.resize(600,400) plot.replot() plot.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/spectrogram.py000077500000000000000000000236741377204562100205200ustar00rootroot00000000000000#!/usr/bin/python import sys #import Qwt from PyQt5 import Qwt from PyQt5.QtCore import Qt, qIsNaN, qRound from PyQt5.QtGui import QColor, QPen, QBrush, QFontMetrics from PyQt5.QtWidgets import QApplication, QCheckBox, QToolBar, QToolButton, QLabel, QComboBox, QSlider, QSizePolicy, QMainWindow from PyQt5.QtPrintSupport import QPrintDialog, QPrinter class MyZoomer(Qwt.QwtPlotZoomer): def __init__(self, canvas): Qwt.QwtPlotZoomer.__init__(self, canvas ) self.setTrackerMode( Qwt.QwtPicker.AlwaysOn ) def trackerTextF( self, pos ): bg = QColor( Qt.white ) bg.setAlpha( 200 ) text = Qwt.QwtPlotZoomer.trackerTextF( pos ) text.setBackgroundBrush( QBrush( bg ) ) return text class SpectrogramData(Qwt.QwtRasterData): def __init__(self): Qwt.QwtRasterData.__init__(self) self.setInterval( Qt.XAxis, Qwt.QwtInterval( -1.5, 1.5 ) ) self.setInterval( Qt.YAxis, Qwt.QwtInterval( -1.5, 1.5 ) ) self.setInterval( Qt.ZAxis, Qwt.QwtInterval( 0.0, 10.0 ) ) def value( self, x, y ): c = 0.842 #c = 0.33 v1 = x * x + ( y - c ) * ( y + c ) v2 = x * ( y + c ) + x * ( y + c ) return 1.0 / ( v1 * v1 + v2 * v2 ) class LinearColorMapRGB(Qwt.QwtLinearColorMap): def __init__(self): Qwt.QwtLinearColorMap.__init__(self, Qt.darkCyan, Qt.red, Qwt.QwtColorMap.RGB ) self.addColorStop( 0.1, Qt.cyan ) self.addColorStop( 0.6, Qt.green ) self.addColorStop( 0.95, Qt.yellow ) class LinearColorMapIndexed(Qwt.QwtLinearColorMap): def __init__(self): Qwt.QwtLinearColorMap.__init__( self, Qt.darkCyan, Qt.red, Qwt.QwtColorMap.Indexed ) self.addColorStop( 0.1, Qt.cyan ) self.addColorStop( 0.6, Qt.green ) self.addColorStop( 0.95, Qt.yellow ) class HueColorMap(Qwt.QwtColorMap): def __init__(self): Qwt.QwtColorMap.__init__(self) self.d_hue1 = 0 self.d_hue2 = 359 self.d_saturation = 150 self.d_value = 200 self.d_rgbTable = [] self.updateTable() def rgb(self, interval, value ): if ( qIsNaN(value) ): return 0 width = interval.width() if ( width <= 0 ): return 0 if ( value <= interval.minValue() ): return self.d_rgbMin if ( value >= interval.maxValue() ): return self.d_rgbMax ratio = ( value - interval.minValue() ) / width hue = self.d_hue1 + qRound( ratio * ( self.d_hue2 - self.d_hue1 ) ) if ( hue >= 360 ): hue -= 360 if ( hue >= 360 ): hue = hue % 360 return self.d_rgbTable[hue] def colorIndex(self, a0, a1 ): # we don't support indexed colors return 0 def updateTable(self): for i in range(360): self.d_rgbTable.append(QColor.fromHsv( i, self.d_saturation, self.d_value ).rgb()) self.d_rgbMin = self.d_rgbTable[ self.d_hue1 % 360 ] self.d_rgbMax = self.d_rgbTable[ self.d_hue2 % 360 ] class AlphaColorMap(Qwt.QwtAlphaColorMap): def __init__(self): Qwt.QwtAlphaColorMap.__init__(self) #setColor( QColor("DarkSalmon") ) self.setColor( QColor("SteelBlue") ) class Plot( Qwt.QwtPlot ): def __init__(self, parent): Qwt.QwtPlot.__init__(self, parent ) self.RGBMap = 0 self.IndexMap = 1 self.HueMap = 2 self.AlphaMap = 3 self.d_alpha = 255 self.d_spectrogram = Qwt.QwtPlotSpectrogram() self.d_spectrogram.setRenderThreadCount( 0 ) # use system specific thread count self.d_spectrogram.setCachePolicy( Qwt.QwtPlotRasterItem.PaintCache ) contourLevels=[] for level in range(1,20,2): contourLevels.append(0.5*level) self.d_spectrogram.setContourLevels( contourLevels ) self.d_spectrogram.setData( SpectrogramData() ) self.d_spectrogram.attach( self ) zInterval = self.d_spectrogram.data().interval( Qt.ZAxis ) # A color bar on the right axis self.rightAxis = self.axisWidget( Qwt.QwtPlot.yRight ) self.rightAxis.setTitle( "Intensity" ) self.rightAxis.setColorBarEnabled( True ) self.setAxisScale( Qwt.QwtPlot.yRight, zInterval.minValue(), zInterval.maxValue() ) self.enableAxis( Qwt.QwtPlot.yRight ) self.plotLayout().setAlignCanvasToScales( True ) self.setColorMap( self.RGBMap ) # LeftButton for the zooming # MidButton for the panning # RightButton: zoom out by 1 # Ctrl+RighButton: zoom out to full size self.zoomer = MyZoomer( self.canvas() ) self.zoomer.setMousePattern( Qwt.QwtEventPattern.MouseSelect2, Qt.RightButton, Qt.ControlModifier ) self.zoomer.setMousePattern( Qwt.QwtEventPattern.MouseSelect3, Qt.RightButton ) self.panner = Qwt.QwtPlotPanner( self.canvas() ) self.panner.setAxisEnabled( Qwt.QwtPlot.yRight, False ) self.panner.setMouseButton( Qt.MidButton ) # Avoid jumping when labels with more/less digits # appear/disappear when scrolling vertically fm = QFontMetrics ( self.axisWidget( Qwt.QwtPlot.yLeft ).font() ) sd = self.axisScaleDraw( Qwt.QwtPlot.yLeft ) sd.setMinimumExtent( fm.width( "100.00" ) ) c = QColor( Qt.darkBlue ) self.zoomer.setRubberBandPen( c ) self.zoomer.setTrackerPen( c ) def showContour( self, on ): self.d_spectrogram.setDisplayMode( Qwt.QwtPlotSpectrogram.ContourMode, on ) self.replot() def showSpectrogram( self, on ): self.d_spectrogram.setDisplayMode( Qwt.QwtPlotSpectrogram.ImageMode, on ) if (on): self.d_spectrogram.setDefaultContourPen( QPen( Qt.black, 0 ) ) else: self.d_spectrogram.setDefaultContourPen( QPen( Qt.NoPen ) ) self.replot() def setColorMap( self, type ): self.axis = self.axisWidget( Qwt.QwtPlot.yRight ) zInterval = self.d_spectrogram.data().interval( Qt.ZAxis ) self.d_mapType = type alpha = self.d_alpha if ( type == self.HueMap ): self.d_spectrogram.setColorMap( HueColorMap() ) self.axis.setColorMap( zInterval, HueColorMap() ) elif ( type == self.AlphaMap): self.alpha = 255 self.d_spectrogram.setColorMap( AlphaColorMap() ) self.axis.setColorMap( zInterval, AlphaColorMap() ) elif ( type == self.IndexMap): self.d_spectrogram.setColorMap( LinearColorMapIndexed() ) self.axis.setColorMap( zInterval, LinearColorMapIndexed() ) elif ( type == self.RGBMap): self.d_spectrogram.setColorMap( LinearColorMapRGB() ) self.axis.setColorMap( zInterval, LinearColorMapRGB() ) self.d_spectrogram.setAlpha( alpha ) self.replot() def setAlpha( self, alpha ): # setting an alpha value doesn't make sense in combination # with a color map interpolating the alpha value self.d_alpha = alpha if ( self.d_mapType != self.AlphaMap ): self.d_spectrogram.setAlpha( alpha ) self.replot() def printPlot(self): # Creates an empty file XXXXX printer = QPrinter( QPrinter.HighResolution ) printer.setOrientation( QPrinter.Landscape ) printer.setDocName( "spectrogram.pdf" ) printer.setCreator( "Spectrogram example" ) dialog = QPrintDialog ( printer ) if ( dialog.exec_() ): renderer = Qwt.QwtPlotRenderer() if ( printer.colorMode() == QPrinter.GrayScale ): renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasBackground ) renderer.setDiscardFlag( Qwt.QwtPlotRenderer.DiscardCanvasFrame ) renderer.setLayoutFlag( Qwt.QwtPlotRenderer.FrameWithScales ) renderer.renderTo( self, printer ) class MainWindow( QMainWindow ): def __init__(self, *args): QMainWindow.__init__(self, *args ) self.d_plot = Plot( self ) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.btnPrint = QToolButton( self.toolBar ) self.btnPrint.setText( "Print" ) self.btnPrint.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) self.toolBar.addWidget( self.btnPrint ) self.btnPrint.clicked.connect(self.d_plot.printPlot ) self.toolBar.addSeparator() self.toolBar.addWidget( QLabel("Color Map " ) ) self.mapBox = QComboBox( self.toolBar ) self.mapBox.addItem( "RGB" ) self.mapBox.addItem( "Indexed Colors" ) self.mapBox.addItem( "Hue" ) self.mapBox.addItem( "Alpha" ) self.mapBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.toolBar.addWidget( self.mapBox ) self.mapBox.currentIndexChanged['int'].connect(self.d_plot.setColorMap ) self.toolBar.addWidget( QLabel( " Opacity " ) ) self.slider = QSlider( Qt.Horizontal ) self.slider.setRange( 0, 255 ) self.slider.setValue( 255 ) self.slider.valueChanged['int'].connect(self.d_plot.setAlpha ) self.toolBar.addWidget( self.slider ) self.toolBar.addWidget( QLabel(" " ) ) self.btnSpectrogram = QCheckBox( "Spectrogram", self.toolBar ) self.toolBar.addWidget( self.btnSpectrogram ) self.btnSpectrogram.toggled['bool'].connect(self.d_plot.showSpectrogram ) self.btnContour = QCheckBox( "Contour", self.toolBar ) self.toolBar.addWidget( self.btnContour ) self.btnContour.toggled['bool'].connect(self.d_plot.showContour ) self.addToolBar( self.toolBar ) self.btnSpectrogram.setChecked( True ) self.btnContour.setChecked( False ) if __name__ == '__main__': a = QApplication(sys.argv) a.setStyle( "Windows" ) mainWindow = MainWindow() mainWindow.resize( 600, 400 ) mainWindow.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/sysinfo.py000077500000000000000000000075561377204562100176650ustar00rootroot00000000000000#!/usr/bin/python import sys from PyQt5 import Qwt import math import numpy as np from PyQt5.QtCore import pyqtSignal, Qt, QSize, QBasicTimer from PyQt5.QtGui import QColor, QPixmap, QFont, QIcon, QPalette, QLinearGradient from PyQt5.QtWidgets import (QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QSizePolicy, QVBoxLayout, QFrame, QGroupBox, QVBoxLayout ) class ValueBar(QWidget): def __init__(self, orientation, text, parent, value = 0.0 ): QWidget.__init__(self, parent) self.d_label = QLabel( text, self ) self.d_label.setFont( QFont( "Helvetica", 10 ) ) self.d_thermo = Qwt.QwtThermo( self ) self.d_thermo.setOrientation( orientation ) self.d_thermo.setScale( 0.0, 100.0 ) self.d_thermo.setValue( value ) self.d_thermo.setFont( QFont( "Helvetica", 8 ) ) self.d_thermo.setPipeWidth( 6 ) self.d_thermo.setScaleMaxMajor( 6 ) self.d_thermo.setScaleMaxMinor( 5 ) self.d_thermo.setFillBrush( Qt.darkMagenta ) #if 0 colorMap = Qwt.QwtLinearColorMap( Qt.blue, Qt.red ) colorMap.addColorStop( 0.2, Qt.yellow ) colorMap.addColorStop( 0.3, Qt.cyan ) colorMap.addColorStop( 0.4, Qt.green ) colorMap.addColorStop( 0.5, Qt.magenta ) colorMap.setMode( Qwt.QwtLinearColorMap.FixedColors ) self.d_thermo.setColorMap( colorMap ) #endif""" self.layout = QVBoxLayout( self ) #self.layout.setCanvasMargin( 0 ) self.layout.setSpacing( 0 ) if ( orientation == Qt.Horizontal ): self.d_label.setAlignment( Qt.AlignCenter ) self.d_thermo.setScalePosition( Qwt.QwtThermo.LeadingScale ) self.layout.addWidget( self.d_label ) self.layout.addWidget( self.d_thermo ) else: self.d_label.setAlignment( Qt.AlignRight ) self.d_thermo.setScalePosition( Qwt.QwtThermo.TrailingScale ) self.layout.addWidget( self.d_thermo, 10, Qt.AlignHCenter ) self.layout.addWidget( self.d_label, 0 ) def setValue(self, value ): self.d_thermo.setValue( value ) class SysInfo(QFrame): def __init__(self, parent = None): QFrame.__init__(self, parent ) self.memBox = QGroupBox( "Memory Usage", self ) self.memBox.setFont( QFont( "Helvetica", 10 ) ) self.memLayout = QVBoxLayout( self.memBox ) #self.memLayout.setMargin( 15 ) self.memLayout.setSpacing( 5 ) o = Qt.Horizontal self.memLayout.addWidget( ValueBar( o, "Used", self.memBox, 57 ) ) self.memLayout.addWidget( ValueBar( o, "Shared", self.memBox, 17 ) ) self.memLayout.addWidget( ValueBar( o, "Cache", self.memBox, 30 ) ) self.memLayout.addWidget( ValueBar( o, "Buffers", self.memBox, 22 ) ) self.memLayout.addWidget( ValueBar( o, "Swap Used", self.memBox, 57 ) ) self.memLayout.addWidget( QWidget( self.memBox ), 10 ) # spacer self.cpuBox = QGroupBox( "Cpu Usage", self ) self.cpuBox.setFont( QFont( "Helvetica", 10 ) ) self.cpuLayout = QHBoxLayout( self.cpuBox ) self.cpuLayout.setContentsMargins( 15,15,15,15 ) self.cpuLayout.setSpacing( 5 ) o = Qt.Vertical self.cpuLayout.addWidget( ValueBar( o, "User", self.cpuBox, 57 ) ) self.cpuLayout.addWidget( ValueBar( o, "Total", self.cpuBox, 73 ) ) self.cpuLayout.addWidget( ValueBar( o, "System", self.cpuBox, 16 ) ) self.cpuLayout.addWidget( ValueBar( o, "Idle", self.cpuBox, 27 ) ) self.layout = QHBoxLayout( self ) self.layout.setContentsMargins( 10, 10, 10, 10 ) self.layout.addWidget( self.memBox, 10 ) self.layout.addWidget( self.cpuBox, 0 ) a = QApplication(sys.argv) info = SysInfo() info.resize( info.sizeHint().expandedTo( QSize( 600, 400 ) ) ) info.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/qt5examples/tvplot.py000077500000000000000000000131021377204562100175030ustar00rootroot00000000000000#!/usr/bin/python import sys from PyQt5 import Qwt from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QColor, QPixmap, QFont, QBrush, QPalette, QPen from PyQt5.QtWidgets import (QMainWindow, QWidget, QToolBar, QToolButton, QHBoxLayout, QLabel, QApplication, QComboBox, QSizePolicy) class Histogram(Qwt.QwtPlotHistogram): def __init__(self,title, symbolColor ): Qwt.QwtPlotHistogram.__init__(self,title) self.setStyle( Qwt.QwtPlotHistogram.Columns ) self.setColor( symbolColor ) def setValues(self, values ): numValues = len(values) #QVector samples( numValues ) samples = [] for i in range(numValues): interval = Qwt.QwtInterval( i , i + 1.0 ) interval.setBorderFlags( Qwt.QwtInterval.ExcludeMaximum ) samples.append(Qwt.QwtIntervalSample( values[i], interval )) self.setSamples( samples ) def setColor(self, color ): c = QColor(color) c.setAlpha( 180 ) self.setBrush( QBrush( c ) ) class TVPlot( Qwt.QwtPlot): def __init__(self, parent=None): Qwt.QwtPlot.__init__(self, parent ) self.setTitle( "Watching TV during a weekend" ) canvas = Qwt.QwtPlotCanvas() canvas.setPalette( QPalette(Qt.gray) ) canvas.setBorderRadius( 10 ) self.setCanvas( canvas ) self.plotLayout().setAlignCanvasToScales( True ) self.setAxisTitle( Qwt.QwtPlot.yLeft, "Number of People" ) self.setAxisTitle( Qwt.QwtPlot.xBottom, "Number of Hours" ) legend = Qwt.QwtLegend() legend.setDefaultItemMode( Qwt.QwtLegendData.Checkable ) self.insertLegend( legend, Qwt.QwtPlot.RightLegend ) self.populate() #connect( legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( showItem( const QVariant &, bool ) ) ); legend.checked['QVariant','bool','int'].connect(self.showItem ) self.replot() # creating the legend items self.items = self.itemList( Qwt.QwtPlotItem.Rtti_PlotHistogram ) for i in range(len(self.items)): if ( i == 0 ): #const QVariant itemInfo = self.itemToInfo( self.items[i] ) #QwtLegendLabel * legendLabel = legend.legendWidget( itemInfo ) if ( legendLabel ): legendLabel.setChecked( True ) self.items[i].setVisible( True ) else: self.items[i].setVisible( False ) self.setAutoReplot( True ) def populate(self): grid = Qwt.QwtPlotGrid() grid.enableX( False ) grid.enableY( True ) grid.enableXMin( False ) grid.enableYMin( False ) grid.setMajorPen( Qt.black, 0, Qt.DotLine ) grid.attach( self ) juneValues = [ 7.0, 19.0, 24.0, 32.0, 10.0, 5.0, 3.0 ] novemberValues = [ 4.0, 15.0, 22.0, 34.0, 13.0, 8.0, 4.0 ] histogramJune = Histogram( "Summer", Qt.red ) histogramJune.setValues( juneValues ) histogramJune.attach( self ) histogramNovember = Histogram( "Winter", Qt.blue ) histogramNovember.setValues( novemberValues ) histogramNovember.attach( self ) def exportPlot(self): print("Export Plot") #renderer = Qwt.QwtPlotRenderer() #renderer.exportTo( self, "tvplot.pdf" ) def setMode( self, mode): #QwtPlotItemList #print("Set mode %d"%mode) items = self.itemList( Qwt.QwtPlotItem.Rtti_PlotHistogram ) for i in range(len(items)): histogram = items[i] if ( mode < 3 ): histogram.setStyle(mode) histogram.setSymbol( None) pen = QPen( Qt.black, 0 ) if ( mode == Qwt.QwtPlotHistogram.Lines ): pen.setBrush( histogram.brush() ) histogram.setPen( pen ) else: histogram.setStyle( Qwt.QwtPlotHistogram.Columns ) symbol = Qwt.QwtColumnSymbol( Qwt.QwtColumnSymbol.Box ) symbol.setFrameStyle( Qwt.QwtColumnSymbol.Raised ) symbol.setLineWidth( 2 ) symbol.setPalette( QPalette( histogram.brush().color() ) ) histogram.setSymbol( symbol ) def showItem( self, plotItem, on ): plotItem.setVisible( on ) class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.d_plot = TVPlot(self) self.setCentralWidget( self.d_plot ) self.toolBar = QToolBar( self ) self.typeBox = QComboBox( self.toolBar ) self.typeBox.addItem( "Outline" ) self.typeBox.addItem( "Columns" ) self.typeBox.addItem( "Lines" ) self.typeBox.addItem( "Column Symbol" ) self.typeBox.setCurrentIndex( self.typeBox.count() - 1 ) self.typeBox.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) self.btnExport = QToolButton( self.toolBar ) self.btnExport.setText( "Export" ) self.btnExport.setToolButtonStyle( Qt.ToolButtonTextUnderIcon ) #connect( btnExport, SIGNAL( clicked() ), d_plot, SLOT( exportPlot() ) ) self.btnExport.clicked.connect(self.d_plot.exportPlot) self.toolBar.addWidget( self.typeBox ) self.toolBar.addWidget( self.btnExport ) self.addToolBar( self.toolBar ) self.d_plot.setMode( self.typeBox.currentIndex() ) self.typeBox.currentIndexChanged['int'].connect(self.d_plot.setMode) a = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.resize( 600, 400 ) mainWindow.show() sys.exit(a.exec_()) PyQt-Qwt-1.02.02/sip/000077500000000000000000000000001377204562100141245ustar00rootroot00000000000000PyQt-Qwt-1.02.02/sip/Qwt_Qt4.sip000066400000000000000000000050741377204562100161520ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ %Module(name=PyQt4.Qwt, keyword_arguments="Optional") %Import QtCore/QtCoremod.sip //typedef unsigned long size_t; %Import QtGui/QtGuimod.sip %If (Qt_5_0_0 -) %Import QtWidgets/QtWidgetsmod.sip %End %Include conversions.sip %Include qmap_convert.sip %Include qwt_legend.sip %Include qwt_legend_data.sip %Include qwt_plot.sip %Include qwt_plot_item.sip %Include qwt_plot_layout.sip %Include qwt_abstract_legend.sip %Include qwt_scale_map.sip %Include qwt_scale_engine.sip %Include qwt_scale_div.sip %Include qwt_scale_draw.sip %Include qwt_abstract_scale_draw.sip %Include qwt_interval.sip %Include qwt_scale_widget.sip %Include qwt_text.sip %Include qwt_text_label.sip %Include qwt_color_map.sip %Include qwt_text_engine.sip %Include qwt_picker.sip %Include qwt_plot_picker.sip %Include qwt_plot_zoomer.sip %Include qwt_event_pattern.sip %Include qwt_picker_machine.sip %Include qwt_plot_canvas.sip %Include qwt_plot_grid.sip %Include qwt_plot_curve.sip %Include qwt_plot_seriesitem.sip %Include qwt_series_store.sip %Include qwt_symbol.sip %Include qwt_curve_fitter.sip %Include qwt_samples.sip %Include qwt_series_data.sip %Include qwt_spline.sip %Include qwt_plot_marker.sip %Include qwt_panner.sip %Include qwt_plot_panner.sip %Include qwt_counter.sip %Include qwt_column_symbol.sip %Include qwt_plot_histogram.sip %Include qwt_plot_barchart.sip %Include qwt_plot_abstract_barchart.sip %Include qwt_plot_multi_barchart.sip %Include qwt_null_paintdevice.sip %Include qwt_graphic.sip %Include qwt_abstract_scale.sip %Include qwt_abstract_slider.sip %Include qwt_slider.sip %Include qwt_thermo.sip %Include qwt_wheel.sip %Include qwt_round_scale_draw.sip %Include qwt_knob.sip %Include qwt_plot_directpainter.sip %Include qwt_sampling_thread.sip %Include qwt_plot_dict.sip %Include qwt_plot_rasteritem.sip %Include qwt_plot_spectrogram.sip %Include qwt_raster_data.sip %Include qwt_plot_renderer.sip //%Include qwt_point_data.sip // Fails to compile %Include qwt_slider.sip %Include qwt_transform.sip %Include qwt_dial_needle.sip %Include qwt_dial.sip %Include qwt_round_scale_draw.sip %Include qwt_compass_rose.sip %Include qwt_compass.sip %Include qwt_point_polar.sip %Include qwt_analog_clock.sip PyQt-Qwt-1.02.02/sip/Qwt_Qt5.sip000066400000000000000000000050741377204562100161530ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ %Module(name=PyQt5.Qwt, keyword_arguments="Optional") %Import QtCore/QtCoremod.sip //typedef unsigned long size_t; %Import QtGui/QtGuimod.sip %If (Qt_5_0_0 -) %Import QtWidgets/QtWidgetsmod.sip %End %Include conversions.sip %Include qmap_convert.sip %Include qwt_legend.sip %Include qwt_legend_data.sip %Include qwt_plot.sip %Include qwt_plot_item.sip %Include qwt_plot_layout.sip %Include qwt_abstract_legend.sip %Include qwt_scale_map.sip %Include qwt_scale_engine.sip %Include qwt_scale_div.sip %Include qwt_scale_draw.sip %Include qwt_abstract_scale_draw.sip %Include qwt_interval.sip %Include qwt_scale_widget.sip %Include qwt_text.sip %Include qwt_text_label.sip %Include qwt_color_map.sip %Include qwt_text_engine.sip %Include qwt_picker.sip %Include qwt_plot_picker.sip %Include qwt_plot_zoomer.sip %Include qwt_event_pattern.sip %Include qwt_picker_machine.sip %Include qwt_plot_canvas.sip %Include qwt_plot_grid.sip %Include qwt_plot_curve.sip %Include qwt_plot_seriesitem.sip %Include qwt_series_store.sip %Include qwt_symbol.sip %Include qwt_curve_fitter.sip %Include qwt_samples.sip %Include qwt_series_data.sip %Include qwt_spline.sip %Include qwt_plot_marker.sip %Include qwt_panner.sip %Include qwt_plot_panner.sip %Include qwt_counter.sip %Include qwt_column_symbol.sip %Include qwt_plot_histogram.sip %Include qwt_plot_barchart.sip %Include qwt_plot_abstract_barchart.sip %Include qwt_plot_multi_barchart.sip %Include qwt_null_paintdevice.sip %Include qwt_graphic.sip %Include qwt_abstract_scale.sip %Include qwt_abstract_slider.sip %Include qwt_slider.sip %Include qwt_thermo.sip %Include qwt_wheel.sip %Include qwt_round_scale_draw.sip %Include qwt_knob.sip %Include qwt_plot_directpainter.sip %Include qwt_sampling_thread.sip %Include qwt_plot_dict.sip %Include qwt_plot_rasteritem.sip %Include qwt_plot_spectrogram.sip %Include qwt_raster_data.sip %Include qwt_plot_renderer.sip //%Include qwt_point_data.sip // Fails to compile %Include qwt_slider.sip %Include qwt_transform.sip %Include qwt_dial_needle.sip %Include qwt_dial.sip %Include qwt_round_scale_draw.sip %Include qwt_compass_rose.sip %Include qwt_compass.sip %Include qwt_point_polar.sip %Include qwt_analog_clock.sip PyQt-Qwt-1.02.02/sip/clean.sh000077500000000000000000000001201377204562100155360ustar00rootroot00000000000000#!/bin/bash rm -f sip* rm -f Makefile rm -f Qwt.exp rm -f Qwt.so rm -f qwt.sbf PyQt-Qwt-1.02.02/sip/conversions.sip000066400000000000000000000033561377204562100172200ustar00rootroot00000000000000/* Code borrowed from qgis */ %MappedType QVector< QVector > { %TypeHeaderCode #include %End %ConvertFromTypeCode // Create the list. PyObject *l; if ((l = PyList_New(sipCpp->size())) == NULL) return NULL; const sipMappedType* qvector_qreal = sipFindType("QVector"); // Set the list elements. for (int i = 0; i < sipCpp->size(); ++i) { QVector* t = new QVector(sipCpp->at(i)); PyObject *tobj; if ((tobj = sipConvertFromType(t, qvector_qreal, sipTransferObj)) == NULL) { Py_DECREF(l); delete t; return NULL; } PyList_SET_ITEM(l, i, tobj); } return l; %End %ConvertToTypeCode const sipMappedType* qvector_qreal = sipFindType("QVector"); // Check the type if that is all that is required. if (sipIsErr == NULL) { if (!PyList_Check(sipPy)) return 0; for (int i = 0; i < PyList_GET_SIZE(sipPy); ++i) if (!sipCanConvertToType(PyList_GET_ITEM(sipPy, i), qvector_qreal, SIP_NOT_NONE)) return 0; return 1; } QVector< QVector > *ql = new QVector< QVector >; for (int i = 0; i < PyList_GET_SIZE(sipPy); ++i) { int state; //qreal *t = reinterpret_cast(sipConvertToInstance(PyList_GET_ITEM(sipPy, i), sipClass_qreal, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr)); QVector * t = reinterpret_cast< QVector * >(sipConvertToType(PyList_GET_ITEM(sipPy, i), qvector_qreal, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr)); if (*sipIsErr) { sipReleaseType(t, qvector_qreal, state); delete ql; return 0; } ql->append(*t); sipReleaseType(t, qvector_qreal, state); } *sipCppPtr = ql; return sipGetState(sipTransferObj); %End }; PyQt-Qwt-1.02.02/sip/qmap_convert.sip000066400000000000000000000041141377204562100173370ustar00rootroot00000000000000// QMap is implemented as a Python dictionary. %MappedType QMap /TypeHint="Dict[double,QString]", TypeHintValue="{}"/ { %TypeHeaderCode #include %End %ConvertFromTypeCode // Create the dictionary. PyObject *d = PyDict_New(); if (!d) return NULL; // Set the dictionary elements. QMap::const_iterator i = sipCpp->constBegin(); while (i != sipCpp->constEnd()) { QString *t = new QString(i.value()); PyObject *kobj = PyFloat_FromDouble(i.key()); PyObject *tobj = sipConvertFromType(t, sipType_QString, sipTransferObj); if (kobj == NULL || tobj == NULL || PyDict_SetItem(d, kobj, tobj) < 0) { Py_DECREF(d); if (kobj) { Py_DECREF(kobj); } if (tobj) { Py_DECREF(tobj); } else { delete t; } return NULL; } Py_DECREF(kobj); Py_DECREF(tobj); ++i; } return d; %End %ConvertToTypeCode PyObject *kobj, *tobj; SIP_SSIZE_T i = 0; // Check the type if that is all that is required. if (sipIsErr == NULL) { if (!PyDict_Check(sipPy)) return 0; while (PyDict_Next(sipPy, &i, &kobj, &tobj)) if (!sipCanConvertToType(tobj, sipType_QString, SIP_NOT_NONE)) return 0; return 1; } QMap *qm = new QMap; while (PyDict_Next(sipPy, &i, &kobj, &tobj)) { int state; double k = PyFloat_AS_DOUBLE(kobj); QString *t = reinterpret_cast(sipConvertToType(tobj, sipType_QString, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr)); if (*sipIsErr) { sipReleaseType(t, sipType_QString, state); delete qm; return 0; } qm->insert(k, *t); sipReleaseType(t, sipType_QString, state); } *sipCppPtr = qm; return sipGetState(sipTransferObj); %End }; PyQt-Qwt-1.02.02/sip/qwt_abstract_legend.sip000066400000000000000000000025621377204562100206620ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtAbstractLegend : QFrame { %TypeHeaderCode #include %End public: explicit QwtAbstractLegend( QWidget *parent = NULL ); virtual ~QwtAbstractLegend(); /*! Render the legend into a given rectangle. \param painter Painter \param rect Bounding rectangle \param fillBackground When true, fill rect with the widget background \sa renderLegend() is used by QwtPlotRenderer */ virtual void renderLegend( QPainter *painter, const QRectF &rect, bool fillBackground ) const = 0; //! \return True, when no plot item is inserted virtual bool isEmpty() const = 0; virtual int scrollExtent( Qt::Orientation ) const; public slots: /*! \brief Update the entries for a plot item \param itemInfo Info about an item \param data List of legend entry attributes for the item */ virtual void updateLegend( const QVariant &itemInfo, const QList &data ) = 0; }; PyQt-Qwt-1.02.02/sip/qwt_abstract_scale.sip000066400000000000000000000043431377204562100205120ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtAbstractScale: QWidget { %TypeHeaderCode #include %End /* Q_OBJECT Q_PROPERTY( double lowerBound READ lowerBound WRITE setLowerBound ) Q_PROPERTY( double upperBound READ upperBound WRITE setUpperBound ) Q_PROPERTY( int scaleMaxMajor READ scaleMaxMajor WRITE setScaleMaxMajor ) Q_PROPERTY( int scaleMaxMinor READ scaleMaxMinor WRITE setScaleMaxMinor ) Q_PROPERTY( double scaleStepSize READ scaleStepSize WRITE setScaleStepSize ) */ public: QwtAbstractScale( QWidget *parent /TransferThis/ = NULL ); virtual ~QwtAbstractScale(); void setScale( double lowerBound, double upperBound ); void setScale( const QwtInterval & ); void setScale( const QwtScaleDiv & ); const QwtScaleDiv& scaleDiv() const; void setLowerBound( double value ); double lowerBound() const; void setUpperBound( double value ); double upperBound() const; void setScaleStepSize( double stepSize ); double scaleStepSize() const; void setScaleMaxMajor( int ticks ); int scaleMaxMinor() const; void setScaleMaxMinor( int ticks ); int scaleMaxMajor() const; void setScaleEngine( QwtScaleEngine * /Transfer/ ); //const QwtScaleEngine *scaleEngine() const; QwtScaleEngine *scaleEngine(); int transform( double ) const; double invTransform( int ) const; bool isInverted() const; double minimum() const; double maximum() const; const QwtScaleMap &scaleMap() const; protected: void rescale( double lowerBound, double upperBound, double stepSize ); void setAbstractScaleDraw( QwtAbstractScaleDraw * /Transfer/ ); //const QwtAbstractScaleDraw *abstractScaleDraw() const; QwtAbstractScaleDraw *abstractScaleDraw(); virtual void scaleChange(); /*private: void updateScaleDraw(); class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_abstract_scale_draw.sip000066400000000000000000000060351377204562100215270ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtAbstractScaleDraw { %TypeHeaderCode #include %End public: /*! Components of a scale \sa enableComponent(), hasComponent */ enum ScaleComponent { //! Backbone = the line where the ticks are located Backbone = 0x01, //! Ticks Ticks = 0x02, //! Labels Labels = 0x04 }; //! Scale components //typedef QFlags ScaleComponents; QwtAbstractScaleDraw(); virtual ~QwtAbstractScaleDraw(); void setScaleDiv( const QwtScaleDiv &s ); const QwtScaleDiv& scaleDiv() const; //void setTransformation( QwtTransform * ); //const QwtScaleMap &scaleMap() const; QwtScaleMap &scaleMap(); void enableComponent( ScaleComponent, bool enable = true ); bool hasComponent( ScaleComponent ) const; void setTickLength( QwtScaleDiv::TickType, double length ); double tickLength( QwtScaleDiv::TickType ) const; double maxTickLength() const; void setSpacing( double margin ); double spacing() const; void setPenWidth( int width ); int penWidth() const; virtual void draw( QPainter *, const QPalette & ) const; //virtual QwtText label( double ) const; /*! Calculate the extent The extent is the distance from the baseline to the outermost pixel of the scale draw in opposite to its orientation. It is at least minimumExtent() pixels. \param font Font used for drawing the tick labels \return Number of pixels \sa setMinimumExtent(), minimumExtent() */ virtual double extent( const QFont &font ) const = 0; void setMinimumExtent( double ); double minimumExtent() const; protected: /*! Draw a tick \param painter Painter \param value Value of the tick \param len Length of the tick \sa drawBackbone(), drawLabel() */ virtual void drawTick( QPainter *painter, double value, double len ) const = 0; /*! Draws the baseline of the scale \param painter Painter \sa drawTick(), drawLabel() */ virtual void drawBackbone( QPainter *painter ) const = 0; /*! Draws the label for a major scale tick \param painter Painter \param value Value \sa drawTick(), drawBackbone() */ virtual void drawLabel( QPainter *painter, double value ) const = 0; void invalidateCache(); //const QwtText &tickLabel( const QFont &, double value ) const; private: QwtAbstractScaleDraw( const QwtAbstractScaleDraw & ); /*QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & ); class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_abstract_slider.sip000066400000000000000000000052751377204562100207120ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtAbstractSlider: QwtAbstractScale { %TypeHeaderCode #include %End /* Q_OBJECT Q_PROPERTY( double value READ value WRITE setValue ) Q_PROPERTY( uint totalSteps READ totalSteps WRITE setTotalSteps ) Q_PROPERTY( uint singleSteps READ singleSteps WRITE setSingleSteps ) Q_PROPERTY( uint pageSteps READ pageSteps WRITE setPageSteps ) Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment ) Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) Q_PROPERTY( bool tracking READ isTracking WRITE setTracking ) Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) Q_PROPERTY( bool invertedControls READ invertedControls WRITE setInvertedControls )*/ public: explicit QwtAbstractSlider( QWidget *parent /TransferThis/ = NULL ); virtual ~QwtAbstractSlider(); void setValid( bool ); bool isValid() const; double value() const; void setWrapping( bool ); bool wrapping() const; void setTotalSteps( uint ); uint totalSteps() const; void setSingleSteps( uint ); uint singleSteps() const; void setPageSteps( uint ); uint pageSteps() const; void setStepAlignment( bool ); bool stepAlignment() const; void setTracking( bool ); bool isTracking() const; void setReadOnly( bool ); bool isReadOnly() const; void setInvertedControls( bool ); bool invertedControls() const; public Q_SLOTS: void setValue( double val ); Q_SIGNALS: void valueChanged( double value ); void sliderPressed(); void sliderReleased(); void sliderMoved( double value ); protected: virtual void mousePressEvent( QMouseEvent *); virtual void mouseReleaseEvent( QMouseEvent *); virtual void mouseMoveEvent( QMouseEvent *); virtual void keyPressEvent( QKeyEvent *); virtual void wheelEvent( QWheelEvent *); virtual bool isScrollPosition( const QPoint &pos ) const = 0; virtual double scrolledTo( const QPoint &pos ) const = 0; void incrementValue( int numSteps ); virtual void scaleChange(); protected: virtual void sliderChange(); double incrementedValue( double value, int stepCount ) const; private: double alignedValue( double ) const; double boundedValue( double ) const; /* class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_analog_clock.sip000066400000000000000000000040661377204562100201560ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2018 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ /*! \brief An analog clock \image html analogclock.png \par Example \code #include QwtAnalogClock *clock = new QwtAnalogClock(...); clock->scaleDraw()->setPenWidth(3); clock->setLineWidth(6); clock->setFrameShadow(QwtDial::Sunken); clock->setTime(); // update the clock every second QTimer *timer = new QTimer(clock); timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime())); timer->start(1000); \endcode \note The examples/dials example shows how to use QwtAnalogClock. */ class QwtAnalogClock: QwtDial { %TypeHeaderCode #include %End public: /*! Hand type \sa setHand(), hand() */ enum Hand { //! Needle displaying the seconds SecondHand, //! Needle displaying the minutes MinuteHand, //! Needle displaying the hours HourHand, //! Number of needles NHands }; explicit QwtAnalogClock( QWidget* parent /TransferThis/ = NULL ); virtual ~QwtAnalogClock(); void setHand( Hand, QwtDialNeedle * /Transfer/); //const QwtDialNeedle *hand( Hand ) const; QwtDialNeedle *hand( Hand ); public Q_SLOTS: void setCurrentTime(); void setTime( const QTime & ); protected: virtual void drawNeedle( QPainter *, const QPointF &, double radius, double direction, QPalette::ColorGroup ) const; virtual void drawHand( QPainter *, Hand, const QPointF &, double radius, double direction, QPalette::ColorGroup ) const; private: // use setHand instead void setNeedle( QwtDialNeedle * ); //QwtDialNeedle *d_hand[NHands]; }; PyQt-Qwt-1.02.02/sip/qwt_color_map.sip000066400000000000000000000056731377204562100175220ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtColorMap { %TypeHeaderCode #include %End public: enum Format { RGB, Indexed }; QwtColorMap( Format = QwtColorMap::RGB ); virtual ~QwtColorMap(); Format format() const; virtual QRgb rgb( const QwtInterval &interval, double value ) const = 0; virtual unsigned char colorIndex( const QwtInterval &interval, double value ) const = 0; QColor color( const QwtInterval &, double value ) const; virtual QVector colorTable( const QwtInterval & ) const; //private: // Format d_format; }; class QwtLinearColorMap: QwtColorMap { %TypeHeaderCode #include %End public: enum Mode { FixedColors, ScaledColors }; QwtLinearColorMap( Format = QwtColorMap::RGB ); QwtLinearColorMap( const QColor &from, const QColor &to, Format = QwtColorMap::RGB ); virtual ~QwtLinearColorMap(); void setMode( Mode ); Mode mode() const; void setColorInterval( const QColor &color1, const QColor &color2 ); void addColorStop( double value, const QColor& ); QVector colorStops() const; QColor color1() const; QColor color2() const; virtual QRgb rgb( const QwtInterval &, double value ) const; virtual unsigned char colorIndex( const QwtInterval &, double value ) const; class ColorStops; private: // Disabled copy constructor and operator= QwtLinearColorMap( const QwtLinearColorMap & ); //QwtLinearColorMap &operator=( const QwtLinearColorMap & ); //class PrivateData; //PrivateData *d_data; }; class QwtAlphaColorMap: QwtColorMap { %TypeHeaderCode #include %End public: QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) ); virtual ~QwtAlphaColorMap(); void setColor( const QColor & ); QColor color() const; virtual QRgb rgb( const QwtInterval &, double value ) const; private: QwtAlphaColorMap( const QwtAlphaColorMap & ); //QwtAlphaColorMap &operator=( const QwtAlphaColorMap & ); virtual unsigned char colorIndex( const QwtInterval &, double value ) const; //class PrivateData; //PrivateData *d_data; }; /*inline QColor QwtColorMap::color( const QwtInterval &interval, double value ) const { if ( d_format == RGB ) { return QColor::fromRgba( rgb( interval, value ) ); } else { const unsigned int index = colorIndex( interval, value ); return colorTable( interval )[index]; // slow } } inline QwtColorMap::Format QwtColorMap::format() const { return d_format; }*/ PyQt-Qwt-1.02.02/sip/qwt_column_symbol.sip000066400000000000000000000067431377204562100204300ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtColumnRect { %TypeHeaderCode #include %End public: //! Direction of the column enum Direction { //! From left to right LeftToRight, //! From right to left RightToLeft, //! From bottom to top BottomToTop, //! From top to bottom TopToBottom }; //! Build an rectangle with invalid intervals directed BottomToTop. /*QwtColumnRect(): direction( BottomToTop ) { }*/ //! \return A normalized QRect built from the intervals QRectF toRect() const; /*{ QRectF r( hInterval.minValue(), vInterval.minValue(), hInterval.maxValue() - hInterval.minValue(), vInterval.maxValue() - vInterval.minValue() ); r = r.normalized(); if ( hInterval.borderFlags() & QwtInterval::ExcludeMinimum ) r.adjust( 1, 0, 0, 0 ); if ( hInterval.borderFlags() & QwtInterval::ExcludeMaximum ) r.adjust( 0, 0, -1, 0 ); if ( vInterval.borderFlags() & QwtInterval::ExcludeMinimum ) r.adjust( 0, 1, 0, 0 ); if ( vInterval.borderFlags() & QwtInterval::ExcludeMaximum ) r.adjust( 0, 0, 0, -1 ); return r; }*/ //! \return Orientation Qt::Orientation orientation() const; /*{ if ( direction == LeftToRight || direction == RightToLeft ) return Qt::Horizontal; return Qt::Vertical; }*/ //! Interval for the horizontal coordinates QwtInterval hInterval; //! Interval for the vertical coordinates QwtInterval vInterval; //! Direction Direction direction; }; //! A drawing primitive for columns class QwtColumnSymbol { %TypeHeaderCode #include %End public: /*! Style \sa setStyle(), style() */ enum Style { //! No Style, the symbol draws nothing NoStyle = -1, /*! The column is painted with a frame depending on the frameStyle() and lineWidth() using the palette(). */ Box, /*! Styles >= QwtColumnSymbol::UserStyle are reserved for derived classes of QwtColumnSymbol that overload draw() with additional application specific symbol types. */ UserStyle = 1000 }; /*! Frame Style used in Box style(). \sa Style, setFrameStyle(), frameStyle(), setStyle(), setPalette() */ enum FrameStyle { //! No frame NoFrame, //! A plain frame style Plain, //! A raised frame style Raised }; public: QwtColumnSymbol( Style = NoStyle ); virtual ~QwtColumnSymbol(); void setFrameStyle( FrameStyle style ); FrameStyle frameStyle() const; void setLineWidth( int width ); int lineWidth() const; void setPalette( const QPalette & ); const QPalette &palette() const; void setStyle( Style ); Style style() const; virtual void draw( QPainter * /Transfer/, const QwtColumnRect & ) const; protected: void drawBox( QPainter * /Transfer/, const QwtColumnRect & ) const; }; PyQt-Qwt-1.02.02/sip/qwt_compass.sip000066400000000000000000000037501377204562100172060ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2018 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ //class QwtCompassRose; /*! \brief A special scale draw made for QwtCompass QwtCompassScaleDraw maps values to strings using a special map, that can be modified by the application The default map consists of the labels N, NE, E, SE, S, SW, W, NW. \sa QwtCompass */ class QwtCompassScaleDraw: QwtRoundScaleDraw { %TypeHeaderCode #include %End public: explicit QwtCompassScaleDraw(); explicit QwtCompassScaleDraw( const QMap &map ); void setLabelMap( const QMap &map ); QMap labelMap() const; virtual QwtText label( double value ) const; //private: // QMap d_labelMap; }; /*! \brief A Compass Widget QwtCompass is a widget to display and enter directions. It consists of a scale, an optional needle and rose. \image html dials1.png \note The examples/dials example shows how to use QwtCompass. */ class QwtCompass: QwtDial { %TypeHeaderCode #include %End public: explicit QwtCompass( QWidget* parent /TransferThis/ = NULL ); virtual ~QwtCompass(); void setRose( QwtCompassRose *rose /Transfer/); //const QwtCompassRose *rose() const; QwtCompassRose *rose(); protected: virtual void drawRose( QPainter *, const QPointF ¢er, double radius, double north, QPalette::ColorGroup ) const; virtual void drawScaleContents( QPainter *, const QPointF ¢er, double radius ) const; virtual void keyPressEvent( QKeyEvent * ); //private: // class PrivateData; // PrivateData *d_data; }; PyQt-Qwt-1.02.02/sip/qwt_compass_rose.sip000066400000000000000000000041631377204562100202350ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2018 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ //class QPainter; /*! \brief Abstract base class for a compass rose */ class QwtCompassRose { %TypeHeaderCode #include %End public: //! Destructor virtual ~QwtCompassRose(); //! Assign a palette virtual void setPalette( const QPalette &p ); //! \return Current palette const QPalette &palette() const; /*! Draw the rose \param painter Painter \param center Center point \param radius Radius of the rose \param north Position \param colorGroup Color group */ virtual void draw( QPainter *painter, const QPointF ¢er, double radius, double north, QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0; //private: // QPalette d_palette; }; /*! \brief A simple rose for QwtCompass */ class QwtSimpleCompassRose: QwtCompassRose { %TypeHeaderCode #include %End public: QwtSimpleCompassRose( int numThorns = 8, int numThornLevels = -1 ); virtual ~QwtSimpleCompassRose(); void setWidth( double w ); double width() const; void setNumThorns( int count ); int numThorns() const; void setNumThornLevels( int count ); int numThornLevels() const; void setShrinkFactor( double factor ); double shrinkFactor() const; virtual void draw( QPainter *, const QPointF ¢er, double radius, double north, QPalette::ColorGroup = QPalette::Active ) const; static void drawRose( QPainter *, const QPalette &, const QPointF ¢er, double radius, double origin, double width, int numThorns, int numThornLevels, double shrinkFactor ); /*private: class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_counter.sip000066400000000000000000000056031377204562100172170ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtCounter: QWidget { %TypeHeaderCode #include %End //Q_OBJECT /*Q_PROPERTY( double value READ value WRITE setValue ) Q_PROPERTY( double minimum READ minimum WRITE setMinimum ) Q_PROPERTY( double maximum READ maximum WRITE setMaximum ) Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep ) Q_PROPERTY( int numButtons READ numButtons WRITE setNumButtons ) Q_PROPERTY( int stepButton1 READ stepButton1 WRITE setStepButton1 ) Q_PROPERTY( int stepButton2 READ stepButton2 WRITE setStepButton2 ) Q_PROPERTY( int stepButton3 READ stepButton3 WRITE setStepButton3 ) Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )*/ public: //! Button index enum Button { //! Button intended for minor steps Button1, //! Button intended for medium steps Button2, //! Button intended for large steps Button3, //! Number of buttons ButtonCnt }; explicit QwtCounter( QWidget *parent = NULL ); virtual ~QwtCounter(); void setValid( bool ); bool isValid() const; void setWrapping( bool ); bool wrapping() const; bool isReadOnly() const; void setReadOnly( bool ); void setNumButtons( int n ); int numButtons() const; void setIncSteps( QwtCounter::Button btn, int nSteps ); int incSteps( QwtCounter::Button btn ) const; virtual QSize sizeHint() const; double singleStep() const; void setSingleStep( double s ); void setRange( double min, double max ); double minimum() const; void setMinimum( double min ); double maximum() const; void setMaximum( double max ); void setStepButton1( int nSteps ); int stepButton1() const; void setStepButton2( int nSteps ); int stepButton2() const; void setStepButton3( int nSteps ); int stepButton3() const; double value() const; public Q_SLOTS: void setValue( double ); Q_SIGNALS: void buttonReleased ( double value ); void valueChanged ( double value ); protected: virtual bool event( QEvent *); virtual void wheelEvent( QWheelEvent *); virtual void keyPressEvent( QKeyEvent *); /*private Q_SLOTS: void btnReleased(); void btnClicked(); void textChanged(); private: void incrementValue( int numSteps ); void initCounter(); void updateButtons(); void showNumber( double ); class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_curve_fitter.sip000066400000000000000000000072031377204562100202370ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtCurveFitter { %TypeHeaderCode #include %End public: virtual ~QwtCurveFitter(); /*! Find a curve which has the best fit to a series of data points \param polygon Series of data points \return Curve points */ virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0; protected: QwtCurveFitter(); private: QwtCurveFitter( const QwtCurveFitter & ); //QwtCurveFitter &operator=( const QwtCurveFitter & ); }; /*! \brief A curve fitter using cubic splines */ class QwtSplineCurveFitter: public QwtCurveFitter { %TypeHeaderCode #include %End public: /*! Spline type The default setting is Auto \sa setFitMode(), FitMode() */ enum FitMode { /*! Use the default spline algorithm for polygons with increasing x values ( p[i-1] < p[i] ), otherwise use a parametric spline algorithm. */ Auto, //! Use a default spline algorithm Spline, //! Use a parametric spline algorithm ParametricSpline }; QwtSplineCurveFitter(); virtual ~QwtSplineCurveFitter(); void setFitMode( FitMode ); FitMode fitMode() const; void setSpline( const QwtSpline& ); //const QwtSpline &spline() const; FIXME. QwtSpline &spline(); void setSplineSize( int size ); int splineSize() const; virtual QPolygonF fitCurve( const QPolygonF & ) const; private: QPolygonF fitSpline( const QPolygonF & ) const; QPolygonF fitParametric( const QPolygonF & ) const; //class PrivateData; //PrivateData *d_data; }; /*! \brief A curve fitter implementing Douglas and Peucker algorithm The purpose of the Douglas and Peucker algorithm is that given a 'curve' composed of line segments to find a curve not too dissimilar but that has fewer points. The algorithm defines 'too dissimilar' based on the maximum distance (tolerance) between the original curve and the smoothed curve. The runtime of the algorithm increases non linear ( worst case O( n*n ) ) and might be very slow for huge polygons. To avoid performance issues it might be useful to split the polygon ( setChunkSize() ) and to run the algorithm for these smaller parts. The disadvantage of having no interpolation at the borders is for most use cases irrelevant. The smoothed curve consists of a subset of the points that defined the original curve. In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces the number of points. By adjusting the tolerance parameter according to the axis scales QwtSplineCurveFitter can be used to implement different level of details to speed up painting of curves of many points. */ class QwtWeedingCurveFitter: public QwtCurveFitter { %TypeHeaderCode #include %End public: QwtWeedingCurveFitter( double tolerance = 1.0 ); virtual ~QwtWeedingCurveFitter(); void setTolerance( double ); double tolerance() const; void setChunkSize( uint ); uint chunkSize() const; virtual QPolygonF fitCurve( const QPolygonF & ) const; private: virtual QPolygonF simplify( const QPolygonF & ) const; //class Line; //class PrivateData; //PrivateData *d_data; }; PyQt-Qwt-1.02.02/sip/qwt_dial.sip000066400000000000000000000113661377204562100164540ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2018 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ /*! \brief QwtDial class provides a rounded range control. QwtDial is intended as base class for dial widgets like speedometers, compass widgets, clocks ... \image html dials2.png A dial contains a scale and a needle indicating the current value of the dial. Depending on Mode one of them is fixed and the other is rotating. If not isReadOnly() the dial can be rotated by dragging the mouse or using keyboard inputs (see QwtAbstractSlider::keyPressEvent()). A dial might be wrapping, what means a rotation below/above one limit continues on the other limit (f.e compass). The scale might cover any arc of the dial, its values are related to the origin() of the dial. Often dials have to be updated very often according to values from external devices. For these high refresh rates QwtDial caches as much as possible. For derived classes it might be necessary to clear these caches manually according to attribute changes using invalidateCache(). \sa QwtCompass, QwtAnalogClock, QwtDialNeedle \note The controls and dials examples shows different types of dials. \note QDial is more similar to QwtKnob than to QwtDial */ class QwtDial: QwtAbstractSlider { %TypeHeaderCode #include %End /* Q_ENUMS( Shadow Mode Direction ) Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth ) Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow ) Q_PROPERTY( Mode mode READ mode WRITE setMode ) Q_PROPERTY( double origin READ origin WRITE setOrigin ) Q_PROPERTY( double minScaleArc READ minScaleArc WRITE setMinScaleArc ) Q_PROPERTY( double maxScaleArc READ maxScaleArc WRITE setMaxScaleArc ) */ public: /*! \brief Frame shadow Unfortunately it is not possible to use QFrame::Shadow as a property of a widget that is not derived from QFrame. The following enum is made for the designer only. It is safe to use QFrame::Shadow instead. */ enum Shadow { //! QFrame::Plain Plain = QFrame::Plain, //! QFrame::Raised Raised = QFrame::Raised, //! QFrame::Sunken Sunken = QFrame::Sunken }; //! Mode controlling whether the needle or the scale is rotating enum Mode { //! The needle is rotating RotateNeedle, //! The needle is fixed, the scales are rotating RotateScale }; explicit QwtDial( QWidget *parent /TransferThis/ = NULL ); virtual ~QwtDial(); void setFrameShadow( Shadow ); Shadow frameShadow() const; void setLineWidth( int ); int lineWidth() const; void setMode( Mode ); Mode mode() const; void setScaleArc( double min, double max ); void setMinScaleArc( double min ); double minScaleArc() const; void setMaxScaleArc( double min ); double maxScaleArc() const; virtual void setOrigin( double ); double origin() const; void setNeedle( QwtDialNeedle * /Transfer/); //const QwtDialNeedle *needle() const; QwtDialNeedle *needle(); QRect boundingRect() const; QRect innerRect() const; virtual QRect scaleInnerRect() const; virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; void setScaleDraw( QwtRoundScaleDraw * /Transfer/); QwtRoundScaleDraw *scaleDraw(); //const QwtRoundScaleDraw *scaleDraw() const; protected: virtual void wheelEvent( QWheelEvent * ); virtual void paintEvent( QPaintEvent * ); virtual void changeEvent( QEvent * ); virtual void drawFrame( QPainter *p ); virtual void drawContents( QPainter * ) const; virtual void drawFocusIndicator( QPainter * ) const; void invalidateCache(); virtual void drawScale( QPainter *, const QPointF ¢er, double radius ) const; virtual void drawScaleContents( QPainter *painter, const QPointF ¢er, double radius ) const; virtual void drawNeedle( QPainter *, const QPointF &, double radius, double direction, QPalette::ColorGroup ) const; virtual double scrolledTo( const QPoint & ) const; virtual bool isScrollPosition( const QPoint & ) const; virtual void sliderChange(); virtual void scaleChange(); private: void setAngleRange( double angle, double span ); void drawNeedle( QPainter * ) const; //class PrivateData; //PrivateData *d_data; }; //#endif PyQt-Qwt-1.02.02/sip/qwt_dial_needle.sip000066400000000000000000000100601377204562100177560ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2018 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ /*! \brief Base class for needles that can be used in a QwtDial. QwtDialNeedle is a pointer that indicates a value by pointing to a specific direction. \sa QwtDial, QwtCompass */ class QwtDialNeedle { %TypeHeaderCode #include %End public: QwtDialNeedle(); virtual ~QwtDialNeedle(); virtual void setPalette( const QPalette & ); const QPalette &palette() const; virtual void draw( QPainter *painter, const QPointF ¢er, double length, double direction, QPalette::ColorGroup = QPalette::Active ) const; protected: /*! \brief Draw the needle The origin of the needle is at position (0.0, 0.0 ) pointing in direction 0.0 ( = east ). The painter is already initialized with translation and rotation. \param painter Painter \param length Length of the needle \param colorGroup Color group, used for painting \sa setPalette(), palette() */ virtual void drawNeedle( QPainter *painter, double length, QPalette::ColorGroup colorGroup ) const = 0; virtual void drawKnob( QPainter *, double width, const QBrush &, bool sunken ) const; //private: // QPalette d_palette; }; /*! \brief A needle for dial widgets The following colors are used: - QPalette::Mid\n Pointer - QPalette::Base\n Knob \sa QwtDial, QwtCompass */ class QwtDialSimpleNeedle: QwtDialNeedle { %TypeHeaderCode #include %End public: //! Style of the needle enum Style { //! Arrow Arrow, //! A straight line from the center Ray }; QwtDialSimpleNeedle( Style, bool hasKnob = true, const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray ); void setWidth( double width ); double width() const; protected: virtual void drawNeedle( QPainter *, double length, QPalette::ColorGroup ) const; /*private: Style d_style; bool d_hasKnob; double d_width;*/ }; /*! \brief A magnet needle for compass widgets A magnet needle points to two opposite directions indicating north and south. The following colors are used: - QPalette::Light\n Used for pointing south - QPalette::Dark\n Used for pointing north - QPalette::Base\n Knob (ThinStyle only) \sa QwtDial, QwtCompass */ class QwtCompassMagnetNeedle: QwtDialNeedle { %TypeHeaderCode #include %End public: //! Style of the needle enum Style { //! A needle with a triangular shape TriangleStyle, //! A thin needle ThinStyle }; QwtCompassMagnetNeedle( Style = TriangleStyle, const QColor &light = Qt::white, const QColor &dark = Qt::red ); protected: virtual void drawNeedle( QPainter *, double length, QPalette::ColorGroup ) const; //private: // Style d_style; }; /*! \brief An indicator for the wind direction QwtCompassWindArrow shows the direction where the wind comes from. - QPalette::Light\n Used for Style1, or the light half of Style2 - QPalette::Dark\n Used for the dark half of Style2 \sa QwtDial, QwtCompass */ class QwtCompassWindArrow: QwtDialNeedle { %TypeHeaderCode #include %End public: //! Style of the arrow enum Style { //! A needle pointing to the center Style1, //! A needle pointing to the center Style2 }; QwtCompassWindArrow( Style, const QColor &light = Qt::white, const QColor &dark = Qt::gray ); protected: virtual void drawNeedle( QPainter *, double length, QPalette::ColorGroup ) const; //private: // Style d_style; }; PyQt-Qwt-1.02.02/sip/qwt_event_pattern.sip000066400000000000000000000051201377204562100204100ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtEventPattern { %TypeHeaderCode #include %End public: enum MousePatternCode { MouseSelect1, MouseSelect2, MouseSelect3, MouseSelect4, MouseSelect5, MouseSelect6, MousePatternCount }; enum KeyPatternCode { KeySelect1, KeySelect2, KeyAbort, KeyLeft, KeyRight, KeyUp, KeyDown, KeyRedo, KeyUndo, KeyHome, KeyPatternCount }; //! A pattern for mouse events class MousePattern { %TypeHeaderCode #include %End public: //! Constructor Qt::MouseButton button; Qt::KeyboardModifiers modifiers; MousePattern( Qt::MouseButton btn = Qt::NoButton, Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ); }; //! A pattern for key events class KeyPattern { %TypeHeaderCode #include %End public: //! Constructor int key; Qt::KeyboardModifiers modifiers; KeyPattern( int keyCode = Qt::Key_unknown, Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ); }; QwtEventPattern(); virtual ~QwtEventPattern(); void initMousePattern( int numButtons ); void initKeyPattern(); void setMousePattern( MousePatternCode, Qt::MouseButton button, Qt::KeyboardModifiers = Qt::NoModifier ); void setKeyPattern( KeyPatternCode, int keyCode, Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ); void setMousePattern( const QVector & ); void setKeyPattern( const QVector & ); //FIXME const QVector &mousePattern() const; //FIXME const QVector &keyPattern() const; QVector &mousePattern(); QVector &keyPattern(); bool mouseMatch( MousePatternCode, const QMouseEvent *) const; bool keyMatch( KeyPatternCode, const QKeyEvent *) const; protected: virtual bool mouseMatch( const QwtEventPattern::MousePattern &, const QMouseEvent *) const; virtual bool keyMatch( const QwtEventPattern::KeyPattern &, const QKeyEvent *) const; }; PyQt-Qwt-1.02.02/sip/qwt_graphic.sip000066400000000000000000000050021377204562100171460ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtGraphic: QwtNullPaintDevice { %TypeHeaderCode #include %End public: enum RenderHint { RenderPensUnscaled = 0x1 }; typedef QFlags RenderHints; QwtGraphic(); QwtGraphic( const QwtGraphic & ); virtual ~QwtGraphic(); void reset(); bool isNull() const; bool isEmpty() const; void render( QPainter * ) const; void render( QPainter *, const QSizeF &, Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; void render( QPainter *, const QRectF &, Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; void render( QPainter *, const QPointF &, Qt::Alignment = Qt::AlignTop | Qt::AlignLeft ) const; QPixmap toPixmap() const; QPixmap toPixmap( const QSize &, Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; QImage toImage() const; QImage toImage( const QSize &, Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; QRectF scaledBoundingRect( double sx, double sy ) const; QRectF boundingRect() const; QRectF controlPointRect() const; //const QVector< QwtPainterCommand > &commands() const; FIXME //void setCommands( QVector< QwtPainterCommand > & ); FIXME void setDefaultSize( const QSizeF & ); QSizeF defaultSize() const; void setRenderHint( QwtGraphic::RenderHint, bool on = true ); bool testRenderHint( QwtGraphic::RenderHint ) const; protected: virtual QSize sizeMetrics() const; virtual void drawPath( const QPainterPath & ); virtual void drawPixmap( const QRectF &, const QPixmap &, const QRectF & ); virtual void drawImage( const QRectF &, const QImage &, const QRectF &, Qt::ImageConversionFlags ); virtual void updateState( const QPaintEngineState &state ); private: QwtGraphic& operator=( const QwtGraphic & ); /* void updateBoundingRect( const QRectF & ); void updateControlPointRect( const QRectF & ); class PathInfo; class PrivateData; PrivateData *d_data;*/ }; //Q_DECLARE_OPERATORS_FOR_FLAGS( QwtGraphic::RenderHints ) //Q_DECLARE_METATYPE( QwtGraphic ) PyQt-Qwt-1.02.02/sip/qwt_interval.sip000066400000000000000000000042141377204562100173610ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtInterval { %TypeHeaderCode #include %End public: enum BorderFlag { IncludeBorders = 0x00, ExcludeMinimum = 0x01, ExcludeMaximum = 0x02, ExcludeBorders = 0x03 //ExcludeMinimum | ExcludeMaximum }; //! Border flags typedef QFlags BorderFlags; QwtInterval(); QwtInterval( double minValue, double maxValue, BorderFlags = IncludeBorders ); void setInterval( double minValue, double maxValue, BorderFlags = IncludeBorders ); QwtInterval normalized() const; QwtInterval inverted() const; QwtInterval limited( double minValue, double maxValue ) const; bool operator==( const QwtInterval & ) const; bool operator!=( const QwtInterval & ) const; void setBorderFlags( QwtInterval::BorderFlags ); QwtInterval::BorderFlags borderFlags() const; double minValue() const; double maxValue() const; double width() const; void setMinValue( double ); void setMaxValue( double ); bool contains( double value ) const; bool intersects( const QwtInterval & ) const; QwtInterval intersect( const QwtInterval & ) const; QwtInterval unite( const QwtInterval & ) const; QwtInterval operator|( const QwtInterval & ) const; QwtInterval operator&( const QwtInterval & ) const; QwtInterval &operator|=( const QwtInterval & ); QwtInterval &operator&=( const QwtInterval & ); QwtInterval extend( double value ) const; QwtInterval operator|( double ) const; QwtInterval &operator|=( double ); bool isValid() const; bool isNull() const; void invalidate(); QwtInterval symmetrize( double value ) const; /*private: double d_minValue; double d_maxValue; BorderFlags d_borderFlags;*/ }; PyQt-Qwt-1.02.02/sip/qwt_knob.sip000066400000000000000000000052531377204562100164720ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtKnob: QwtAbstractSlider { %TypeHeaderCode #include %End /* Q_OBJECT Q_ENUMS ( KnobStyle MarkerStyle ) Q_PROPERTY( KnobStyle knobStyle READ knobStyle WRITE setKnobStyle ) Q_PROPERTY( int knobWidth READ knobWidth WRITE setKnobWidth ) Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment ) Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle ) Q_PROPERTY( int numTurns READ numTurns WRITE setNumTurns ) Q_PROPERTY( MarkerStyle markerStyle READ markerStyle WRITE setMarkerStyle ) Q_PROPERTY( int markerSize READ markerSize WRITE setMarkerSize ) Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth )*/ public: enum KnobStyle { Flat, Raised, Sunken, Styled }; enum MarkerStyle { NoMarker = -1, Tick, Triangle, Dot, Nub, Notch }; explicit QwtKnob( QWidget* parent /TransferThis/ = NULL ); virtual ~QwtKnob(); void setAlignment( Qt::Alignment ); Qt::Alignment alignment() const; void setKnobWidth( int ); int knobWidth() const; void setNumTurns( int ); int numTurns() const; void setTotalAngle ( double angle ); double totalAngle() const; void setKnobStyle( KnobStyle ); KnobStyle knobStyle() const; void setBorderWidth( int bw ); int borderWidth() const; void setMarkerStyle( MarkerStyle ); MarkerStyle markerStyle() const; void setMarkerSize( int ); int markerSize() const; virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; void setScaleDraw( QwtRoundScaleDraw * /Transfer/); //const QwtRoundScaleDraw *scaleDraw() const; QwtRoundScaleDraw *scaleDraw(); QRect knobRect() const; protected: virtual void paintEvent( QPaintEvent *); virtual void changeEvent( QEvent *); virtual void drawKnob( QPainter * /Transfer/, const QRectF & ) const; virtual void drawFocusIndicator( QPainter * /Transfer/) const; virtual void drawMarker( QPainter * /Transfer/, const QRectF &, double arc ) const; virtual double scrolledTo( const QPoint & ) const; virtual bool isScrollPosition( const QPoint & ) const; /*private: class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_legend.sip000066400000000000000000000056641377204562100170050ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtLegend : QwtAbstractLegend { %TypeHeaderCode #include %End public: explicit QwtLegend( QWidget *parent /TransferThis/ = NULL ); virtual ~QwtLegend(); void setMaxColumns( uint numColums ); uint maxColumns() const; void setDefaultItemMode( QwtLegendData::Mode ); QwtLegendData::Mode defaultItemMode() const; QWidget *contentsWidget(); //const QWidget *contentsWidget() const; QWidget *legendWidget( const QVariant & ) const; QList legendWidgets( const QVariant & ) const; QVariant itemInfo( const QWidget * ) const; virtual bool eventFilter( QObject *, QEvent * ); virtual QSize sizeHint() const; virtual int heightForWidth( int w ) const; QScrollBar *horizontalScrollBar() const; QScrollBar *verticalScrollBar() const; virtual void renderLegend( QPainter *, const QRectF &, bool fillBackground ) const; virtual void renderItem( QPainter *, const QWidget *, const QRectF &, bool fillBackground ) const; virtual bool isEmpty() const; virtual int scrollExtent( Qt::Orientation ) const; signals: /*! A signal which is emitted when the user has clicked on a legend label, which is in QwtLegendData::Clickable mode. \param itemInfo Info for the item item of the selected legend item \param index Index of the legend label in the list of widgets that are associated with the plot item \note clicks are disabled as default \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() */ void clicked( const QVariant &itemInfo, int index ); /*! A signal which is emitted when the user has clicked on a legend label, which is in QwtLegendData::Checkable mode \param itemInfo Info for the item of the selected legend label \param index Index of the legend label in the list of widgets that are associated with the plot item \param on True when the legend label is checked \note clicks are disabled as default \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() */ void checked( const QVariant &itemInfo, bool on, int index ); public slots: virtual void updateLegend( const QVariant &, const QList & ); protected slots: void itemClicked(); void itemChecked( bool ); protected: virtual QWidget *createWidget( const QwtLegendData & ) const; virtual void updateWidget( QWidget *widget, const QwtLegendData &data ); }; PyQt-Qwt-1.02.02/sip/qwt_legend_data.sip000066400000000000000000000027651377204562100177750ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtLegendData { %TypeHeaderCode #include %End public: //! Mode defining how a legend entry interacts enum Mode { //! The legend item is not interactive, like a label ReadOnly, //! The legend item is clickable, like a push button Clickable, //! The legend item is checkable, like a checkable button Checkable }; //! Identifier how to interprete a QVariant enum Role { // The value is a Mode ModeRole, // The value is a title TitleRole, // The value is an icon IconRole, // Values < UserRole are reserved for internal use UserRole = 32 }; QwtLegendData(); ~QwtLegendData(); void setValues( const QMap & ); const QMap &values() const; void setValue( int role, const QVariant & ); QVariant value( int role ) const; bool hasRole( int role ) const; bool isValid() const; QwtGraphic icon() const; QwtText title() const; Mode mode() const; //private: // QMap d_map; }; PyQt-Qwt-1.02.02/sip/qwt_null_paintdevice.sip000066400000000000000000000040451377204562100210640ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtNullPaintDevice: QPaintDevice { %TypeHeaderCode #include %End public: enum Mode { NormalMode, PolygonPathMode, PathMode }; QwtNullPaintDevice(); virtual ~QwtNullPaintDevice(); void setMode( Mode ); Mode mode() const; virtual QPaintEngine *paintEngine() const; virtual int metric( PaintDeviceMetric metric ) const; virtual void drawRects(const QRect *, int ); virtual void drawRects(const QRectF *, int ); virtual void drawLines(const QLine *, int ); virtual void drawLines(const QLineF *, int ); virtual void drawEllipse(const QRectF &); virtual void drawEllipse(const QRect &); virtual void drawPath(const QPainterPath &); virtual void drawPoints(const QPointF *, int ); virtual void drawPoints(const QPoint *, int ); virtual void drawPolygon( const QPointF *, int , QPaintEngine::PolygonDrawMode ); virtual void drawPolygon( const QPoint *, int , QPaintEngine::PolygonDrawMode ); virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &); virtual void drawTextItem(const QPointF &, const QTextItem &); virtual void drawTiledPixmap(const QRectF &, const QPixmap &, const QPointF &s); virtual void drawImage(const QRectF &, const QImage &, const QRectF &, Qt::ImageConversionFlags ); virtual void updateState( const QPaintEngineState &state ); protected: //! \return Size needed to implement metric() virtual QSize sizeMetrics() const = 0; /*private: class PaintEngine; PaintEngine *d_engine; class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_panner.sip000066400000000000000000000042041377204562100170170ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPanner: QWidget { %TypeHeaderCode #include %End //Q_OBJECT public: QwtPanner( QWidget* parent /TransferThis/); virtual ~QwtPanner(); void setEnabled( bool ); bool isEnabled() const; void setMouseButton( Qt::MouseButton, Qt::KeyboardModifiers = Qt::NoModifier ); void getMouseButton( Qt::MouseButton &button, Qt::KeyboardModifiers & ) const; void setAbortKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); void getAbortKey( int &key, Qt::KeyboardModifiers & ) const; void setCursor( const QCursor & ); const QCursor cursor() const; void setOrientations( Qt::Orientations ); Qt::Orientations orientations() const; bool isOrientationEnabled( Qt::Orientation ) const; virtual bool eventFilter( QObject *, QEvent * ); Q_SIGNALS: /*! Signal emitted, when panning is done \param dx Offset in horizontal direction \param dy Offset in vertical direction */ void panned( int dx, int dy ); /*! Signal emitted, while the widget moved, but panning is not finished. \param dx Offset in horizontal direction \param dy Offset in vertical direction */ void moved( int dx, int dy ); protected: virtual void widgetMousePressEvent( QMouseEvent * ); virtual void widgetMouseReleaseEvent( QMouseEvent * ); virtual void widgetMouseMoveEvent( QMouseEvent * ); virtual void widgetKeyPressEvent( QKeyEvent * ); virtual void widgetKeyReleaseEvent( QKeyEvent * ); virtual void paintEvent( QPaintEvent * ); virtual QBitmap contentsMask() const; virtual QPixmap grab() const; /*private: #ifndef QT_NO_CURSOR void showCursor( bool ); #endif class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_picker.sip000066400000000000000000000153631377204562100170210ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPicker: QObject, QwtEventPattern { %TypeHeaderCode #include %End /* Q_OBJECT Q_ENUMS( RubberBand DisplayMode ResizeMode ) Q_PROPERTY( bool isEnabled READ isEnabled WRITE setEnabled ) Q_PROPERTY( ResizeMode resizeMode READ resizeMode WRITE setResizeMode ) Q_PROPERTY( DisplayMode trackerMode READ trackerMode WRITE setTrackerMode ) Q_PROPERTY( QPen trackerPen READ trackerPen WRITE setTrackerPen ) Q_PROPERTY( QFont trackerFont READ trackerFont WRITE setTrackerFont ) Q_PROPERTY( RubberBand rubberBand READ rubberBand WRITE setRubberBand ) Q_PROPERTY( QPen rubberBandPen READ rubberBandPen WRITE setRubberBandPen ) */ public: /*! Rubber band style The default value is QwtPicker::NoRubberBand. \sa setRubberBand(), rubberBand() */ enum RubberBand { //! No rubberband. NoRubberBand = 0, //! A horizontal line ( only for QwtPickerMachine::PointSelection ) HLineRubberBand, //! A vertical line ( only for QwtPickerMachine::PointSelection ) VLineRubberBand, //! A crosshair ( only for QwtPickerMachine::PointSelection ) CrossRubberBand, //! A rectangle ( only for QwtPickerMachine::RectSelection ) RectRubberBand, //! An ellipse ( only for QwtPickerMachine::RectSelection ) EllipseRubberBand, //! A polygon ( only for QwtPickerMachine::PolygonSelection ) PolygonRubberBand, /*! Values >= UserRubberBand can be used to define additional rubber bands. */ UserRubberBand = 100 }; /*! \brief Display mode \sa setTrackerMode(), trackerMode(), isActive() */ enum DisplayMode { //! Display never AlwaysOff, //! Display always AlwaysOn, //! Display only when the selection is active ActiveOnly }; /*! Controls what to do with the selected points of an active selection when the observed widget is resized. The default value is QwtPicker::Stretch. \sa setResizeMode() */ enum ResizeMode { //! All points are scaled according to the new size, Stretch, //! All points remain unchanged. KeepSize }; explicit QwtPicker( QWidget *parent /TransferThis/); explicit QwtPicker( RubberBand rubberBand, DisplayMode trackerMode, QWidget * /Transfer/); virtual ~QwtPicker(); void setStateMachine( QwtPickerMachine * /Transfer/); //const QwtPickerMachine *stateMachine() const; FIXME QwtPickerMachine *stateMachine(); void setRubberBand( RubberBand ); RubberBand rubberBand() const; void setTrackerMode( DisplayMode ); DisplayMode trackerMode() const; void setResizeMode( ResizeMode ); ResizeMode resizeMode() const; void setRubberBandPen( const QPen & ); QPen rubberBandPen() const; void setTrackerPen( const QPen & ); QPen trackerPen() const; void setTrackerFont( const QFont & ); QFont trackerFont() const; bool isEnabled() const; bool isActive() const; virtual bool eventFilter( QObject *, QEvent *); QWidget *parentWidget(); //const QWidget *parentWidget() const; FIXME virtual QPainterPath pickArea() const; virtual void drawRubberBand( QPainter * ) const; virtual void drawTracker( QPainter * ) const; virtual QRegion rubberBandMask() const; //virtual QwtText trackerText( const QPoint &pos ) const; FIXME QPoint trackerPosition() const; virtual QRect trackerRect( const QFont & ) const; QPolygon selection() const; public Q_SLOTS: void setEnabled( bool ); Q_SIGNALS: /*! A signal indicating, when the picker has been activated. Together with setEnabled() it can be used to implement selections with more than one picker. \param on True, when the picker has been activated */ void activated( bool on ); /*! A signal emitting the selected points, at the end of a selection. \param polygon Selected points */ void selected( const QPolygon &polygon ); /*! A signal emitted when a point has been appended to the selection \param pos Position of the appended point. \sa append(). moved() */ void appended( const QPoint &pos ); /*! A signal emitted whenever the last appended point of the selection has been moved. \param pos Position of the moved last point of the selection. \sa move(), appended() */ void moved( const QPoint &pos ); /*! A signal emitted whenever the last appended point of the selection has been removed. \param pos Position of the point, that has been removed \sa remove(), appended() */ void removed( const QPoint &pos ); /*! A signal emitted when the active selection has been changed. This might happen when the observed widget is resized. \param selection Changed selection \sa stretchSelection() */ void changed( const QPolygon &selection ); protected: virtual QPolygon adjustedPoints( const QPolygon & ) const; virtual void transition( const QEvent *); virtual void begin(); virtual void append( const QPoint & ); virtual void move( const QPoint & ); virtual void remove(); virtual bool end( bool ok = true ); virtual bool accept( QPolygon & ) const; virtual void reset(); virtual void widgetMousePressEvent( QMouseEvent *); virtual void widgetMouseReleaseEvent( QMouseEvent *); virtual void widgetMouseDoubleClickEvent( QMouseEvent *); virtual void widgetMouseMoveEvent( QMouseEvent *); virtual void widgetWheelEvent( QWheelEvent *); virtual void widgetKeyPressEvent( QKeyEvent *); virtual void widgetKeyReleaseEvent( QKeyEvent *); virtual void widgetEnterEvent( QEvent *); virtual void widgetLeaveEvent( QEvent *); virtual void stretchSelection( const QSize &oldSize, const QSize &newSize ); virtual void updateDisplay(); //const QwtWidgetOverlay *rubberBandOverlay() const;FIXME //const QwtWidgetOverlay *trackerOverlay() const; FIXME const QPolygon &pickedPoints() const; private: void init( QWidget *, RubberBand rubberBand, DisplayMode trackerMode ); void setMouseTracking( bool ); //class PrivateData; //PrivateData *d_data; }; PyQt-Qwt-1.02.02/sip/qwt_picker_machine.sip000066400000000000000000000126531377204562100205040ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPickerMachine { %TypeHeaderCode #include %End public: enum SelectionType { NoSelection = -1, PointSelection, RectSelection, PolygonSelection }; //! Commands - the output of a state machine enum Command { Begin, Append, Move, Remove, End }; QwtPickerMachine( SelectionType type ); virtual ~QwtPickerMachine(); //! Transition virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/) = 0; void reset(); int state() const; void setState( int ); SelectionType selectionType() const; private: QwtPickerMachine& operator=(const QwtPickerMachine&); //SelectionType d_selectionType; //int d_state; }; /*! \brief A state machine for indicating mouse movements QwtPickerTrackerMachine supports displaying information corresponding to mouse movements, but is not intended for selecting anything. Begin/End are related to Enter/Leave events. */ class QwtPickerTrackerMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerTrackerMachine(); virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for point selections Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 selects a point. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ class QwtPickerClickPointMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerClickPointMachine(); virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for point selections Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 starts the selection, releasing QwtEventPattern::MouseSelect1 or a second press of QwtEventPattern::KeySelect1 terminates it. */ class QwtPickerDragPointMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerDragPointMachine(); virtual QList transition(const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for rectangle selections Pressing QwtEventPattern::MouseSelect1 starts the selection, releasing it selects the first point. Pressing it again selects the second point and terminates the selection. Pressing QwtEventPattern::KeySelect1 also starts the selection, a second press selects the first point. A third one selects the second point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ class QwtPickerClickRectMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerClickRectMachine(); virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for rectangle selections Pressing QwtEventPattern::MouseSelect1 selects the first point, releasing it the second point. Pressing QwtEventPattern::KeySelect1 also selects the first point, a second press selects the second point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ class QwtPickerDragRectMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerDragRectMachine(); virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for line selections Pressing QwtEventPattern::MouseSelect1 selects the first point, releasing it the second point. Pressing QwtEventPattern::KeySelect1 also selects the first point, a second press selects the second point and terminates the selection. A common use case of QwtPickerDragLineMachine are pickers for distance measurements. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ class QwtPickerDragLineMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerDragLineMachine(); virtual QList transition(const QwtEventPattern &, const QEvent * /Transfer/); }; /*! \brief A state machine for polygon selections Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 starts the selection and selects the first point, or appends a point. Pressing QwtEventPattern::MouseSelect2 or QwtEventPattern::KeySelect2 appends the last point and terminates the selection. \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode */ class QwtPickerPolygonMachine: QwtPickerMachine { %TypeHeaderCode #include %End public: QwtPickerPolygonMachine(); virtual QList transition( const QwtEventPattern &, const QEvent * /Transfer/); }; PyQt-Qwt-1.02.02/sip/qwt_plot.sip000066400000000000000000000142221377204562100165130ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlot: QFrame , QwtPlotDict { %TypeHeaderCode #include %End public: //! \brief Axis index enum Axis { //! Y axis left of the canvas yLeft, //! Y axis right of the canvas yRight, //! X axis below the canvas xBottom, //! X axis above the canvas xTop, //! Number of axes axisCnt }; /*! Position of the legend, relative to the canvas. \sa insertLegend() */ enum LegendPosition { //! The legend will be left from the QwtPlot::yLeft axis. LeftLegend, //! The legend will be right from the QwtPlot::yRight axis. RightLegend, //! The legend will be below the footer BottomLegend, //! The legend will be above the title TopLegend }; explicit QwtPlot( QWidget * /TransferThis/ = NULL ); explicit QwtPlot( const QwtText &title, QWidget * /TransferThis/ = NULL ); virtual ~QwtPlot(); void applyProperties( const QString & ); QString grabProperties() const; void setAutoReplot( bool = true ); bool autoReplot() const; // Layout void setPlotLayout( QwtPlotLayout * ); QwtPlotLayout *plotLayout(); //const QwtPlotLayout *plotLayout() const; // Title void setTitle( const QString & ); void setTitle( const QwtText &t ); QwtText title() const; QwtTextLabel *titleLabel(); //const QwtTextLabel *titleLabel() const; // Footer void setFooter( const QString & ); void setFooter( const QwtText &t ); QwtText footer() const; QwtTextLabel *footerLabel(); //const QwtTextLabel *footerLabel() const; // Canvas void setCanvas( QWidget * /Transfer/); QWidget *canvas(); //const QWidget *canvas() const; void setCanvasBackground( const QBrush & ); QBrush canvasBackground() const; virtual QwtScaleMap canvasMap( int axisId ) const; double invTransform( int axisId, int pos ) const; double transform( int axisId, double value ) const; // Axes QwtScaleEngine *axisScaleEngine( int axisId ); //const QwtScaleEngine *axisScaleEngine( int axisId ) const; void setAxisScaleEngine( int axisId, QwtScaleEngine * /Transfer/); void setAxisAutoScale( int axisId, bool on = true ); bool axisAutoScale( int axisId ) const; void enableAxis( int axisId, bool tf = true ); bool axisEnabled( int axisId ) const; void setAxisFont( int axisId, const QFont &f ); QFont axisFont( int axisId ) const; void setAxisScale( int axisId, double min, double max, double step = 0 ); void setAxisScaleDiv( int axisId, const QwtScaleDiv & ); void setAxisScaleDraw( int axisId, QwtScaleDraw * /Transfer/); double axisStepSize( int axisId ) const; QwtInterval axisInterval( int axisId ) const; const QwtScaleDiv &axisScaleDiv( int axisId ) const; //const QwtScaleDraw *axisScaleDraw( int axisId ) const; QwtScaleDraw *axisScaleDraw( int axisId ); //const QwtScaleWidget *axisWidget( int axisId ) const; QwtScaleWidget *axisWidget( int axisId ); void setAxisLabelAlignment( int axisId, Qt::Alignment ); void setAxisLabelRotation( int axisId, double rotation ); void setAxisTitle( int axisId, const QString & ); void setAxisTitle( int axisId, const QwtText & ); QwtText axisTitle( int axisId ) const; void setAxisMaxMinor( int axisId, int maxMinor ); int axisMaxMinor( int axisId ) const; void setAxisMaxMajor( int axisId, int maxMajor ); int axisMaxMajor( int axisId ) const; // Legend void insertLegend( QwtAbstractLegend * /Transfer/, LegendPosition = QwtPlot::RightLegend, double ratio = -1.0 ); QwtAbstractLegend *legend(); //const QwtAbstractLegend *legend() const; void updateLegend(); void updateLegend( const QwtPlotItem *); // Misc virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; virtual void updateLayout(); virtual void drawCanvas( QPainter * ); void updateAxes(); void updateCanvasMargins(); /*virtual void getCanvasMarginsHint( const QwtScaleMap maps[], const QRectF &canvasRect, double &left, double &top, double &right, double &bottom) const;*/ virtual bool event( QEvent * ); virtual bool eventFilter( QObject *, QEvent *); /*virtual void drawItems( QPainter *, const QRectF &, const QwtScaleMap maps[axisCnt] ) const;*/ virtual QVariant itemToInfo( QwtPlotItem *) const; virtual QwtPlotItem *infoToItem( const QVariant & ) const; signals: /*! A signal indicating, that an item has been attached/detached \param plotItem Plot item \param on Attached/Detached */ void itemAttached( QwtPlotItem *plotItem, bool on ); /*! A signal with the attributes how to update the legend entries for a plot item. \param itemInfo Info about a plot item, build from itemToInfo() \param data Attributes of the entries ( usually <= 1 ) for the plot item. \sa itemToInfo(), infoToItem(), QwtAbstractLegend::updateLegend() */ void legendDataChanged( const QVariant &itemInfo, const QList &data ); public slots: virtual void replot(); void autoRefresh(); protected: static bool axisValid( int axisId ); virtual void resizeEvent( QResizeEvent *e ); private slots: void updateLegendItems( const QVariant &itemInfo, const QList &data ); /*private: friend class QwtPlotItem; void attachItem( QwtPlotItem *, bool ); void initAxesData(); void deleteAxesData(); void updateScaleDiv(); void initPlot( const QwtText &title ); class AxisData; AxisData *d_axisData[axisCnt]; class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_abstract_barchart.sip000066400000000000000000000027671377204562100222570ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotAbstractBarChart: QwtPlotSeriesItem { %TypeHeaderCode #include %End public: enum LayoutPolicy { AutoAdjustSamples, ScaleSamplesToAxes, ScaleSampleToCanvas, FixedSampleSize }; explicit QwtPlotAbstractBarChart( const QwtText &title ); virtual ~QwtPlotAbstractBarChart(); void setLayoutPolicy( QwtPlotAbstractBarChart::LayoutPolicy ); QwtPlotAbstractBarChart::LayoutPolicy layoutPolicy() const; void setLayoutHint( double ); double layoutHint() const; void setSpacing( int ); int spacing() const; void setMargin( int ); int margin() const; void setBaseline( double ); double baseline() const; virtual void getCanvasMarginHint( const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, double &left, double &top, double &right, double &bottom) const; protected: double sampleWidth( const QwtScaleMap &map, double canvasSize, double dataSize, double value ) const; /*private: class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_barchart.sip000066400000000000000000000050671377204562100203700ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotBarChart: QwtPlotAbstractBarChart, QwtSeriesStoreQPointF { %TypeHeaderCode #include typedef QwtSeriesStore QwtSeriesStoreQPointF; %End public: /*! \brief Legend modes. The default setting is QwtPlotBarChart::LegendChartTitle. \sa setLegendMode(), legendMode() */ enum LegendMode { /*! One entry on the legend showing the default symbol and the title() of the chart \sa QwtPlotItem::title() */ LegendChartTitle, /*! One entry for each value showing the individual symbol of the corresponding bar and the bar title. \sa specialSymbol(), barTitle() */ LegendBarTitles }; explicit QwtPlotBarChart( const QString &title = QString::null ); explicit QwtPlotBarChart( const QwtText &title ); virtual ~QwtPlotBarChart(); virtual int rtti() const; void setSamples( const QVector & ); void setSamples( const QVector & ); void setSamples( QwtSeriesDataQPointF *series ); void setSymbol( QwtColumnSymbol * /Transfer/); const QwtColumnSymbol *symbol() const; void setLegendMode( QwtPlotBarChart::LegendMode ); QwtPlotBarChart::LegendMode legendMode() const; virtual void drawSeries( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual QRectF boundingRect() const; virtual QwtColumnSymbol *specialSymbol( int sampleIndex, const QPointF& ) const; virtual QwtText barTitle( int sampleIndex ) const; protected: virtual void drawSample( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, const QwtInterval &boundingInterval, int index, const QPointF& sample ) const; virtual void drawBar( QPainter *, int sampleIndex, const QPointF& point, const QwtColumnRect & ) const; QList legendData() const; QwtGraphic legendIcon( int index, const QSizeF & ) const; /*private: void init(); class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_canvas.sip000066400000000000000000000045431377204562100200530ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ //class QwtPlot; //class QPixmap; %ModuleHeaderCode // fix to allow compilation with sip that for some reason // doesn't add this include to the file where the code from // ConvertToSubClassCode goes. #include %End class QwtPlotCanvas : QFrame { %TypeHeaderCode #include %End %ConvertToSubClassCode if ( qobject_cast( sipCpp ) ) sipType = sipType_QwtPlotCanvas; else sipType = NULL; %End // Q_OBJECT // Q_PROPERTY( double borderRadius READ borderRadius WRITE setBorderRadius ) public: /*! \brief Paint attributes The default setting enables BackingStore and Opaque. \sa setPaintAttribute(), testPaintAttribute() */ enum PaintAttribute { BackingStore = 1, Opaque = 2, HackStyledBackground = 4, ImmediatePaint = 8 }; //! Paint attributes //typedef QFlags PaintAttributes; enum FocusIndicator { NoFocusIndicator, CanvasFocusIndicator, ItemFocusIndicator }; explicit QwtPlotCanvas( QwtPlot * = NULL ); virtual ~QwtPlotCanvas(); QwtPlot *plot(); //const QwtPlot *plot() const; void setFocusIndicator( FocusIndicator ); FocusIndicator focusIndicator() const; void setBorderRadius( double ); double borderRadius() const; void setPaintAttribute( PaintAttribute, bool on = true ); bool testPaintAttribute( PaintAttribute ) const; const QPixmap *backingStore() const; void invalidateBackingStore(); virtual bool event( QEvent * ); //Q_INVOKABLE QPainterPath borderPath( const QRect & ) const; public slots: void replot(); protected: virtual void paintEvent( QPaintEvent * ); virtual void resizeEvent( QResizeEvent * ); virtual void drawFocusIndicator( QPainter * ); virtual void drawBorder( QPainter * ); void updateStyleSheetInfo(); private: void drawCanvas( QPainter *, bool withBackground ); }; PyQt-Qwt-1.02.02/sip/qwt_plot_curve.sip000066400000000000000000000203451377204562100177220ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotCurve: QwtPlotSeriesItem, QwtSeriesStoreQPointF { %TypeHeaderCode #include typedef QwtSeriesStore QwtSeriesStoreQPointF; %End public: /*! Curve styles. \sa setStyle(), style() */ enum CurveStyle { /*! Don't draw a curve. Note: This doesn't affect the symbols. */ NoCurve = -1, /*! Connect the points with straight lines. The lines might be interpolated depending on the 'Fitted' attribute. Curve fitting can be configured using setCurveFitter(). */ Lines, /*! Draw vertical or horizontal sticks ( depending on the orientation() ) from a baseline which is defined by setBaseline(). */ Sticks, /*! Connect the points with a step function. The step function is drawn from the left to the right or vice versa, depending on the QwtPlotCurve::Inverted attribute. */ Steps, /*! Draw dots at the locations of the data points. Note: This is different from a dotted line (see setPen()), and faster as a curve in QwtPlotCurve::NoStyle style and a symbol painting a point. */ Dots, /*! Styles >= QwtPlotCurve::UserCurve are reserved for derived classes of QwtPlotCurve that overload drawCurve() with additional application specific curve types. */ UserCurve = 100 }; /*! Attribute for drawing the curve \sa setCurveAttribute(), testCurveAttribute(), curveFitter() */ enum CurveAttribute { /*! For QwtPlotCurve::Steps only. Draws a step function from the right to the left. */ Inverted = 0x01, /*! Only in combination with QwtPlotCurve::Lines A QwtCurveFitter tries to interpolate/smooth the curve, before it is painted. \note Curve fitting requires temporary memory for calculating coefficients and additional points. If painting in QwtPlotCurve::Fitted mode is slow it might be better to fit the points, before they are passed to QwtPlotCurve. */ Fitted = 0x02 }; //! Curve attributes //typedef QFlags CurveAttributes; /*! Attributes how to represent the curve on the legend \sa setLegendAttribute(), testLegendAttribute(), QwtPlotItem::legendData(), legendIcon() */ enum LegendAttribute { /*! QwtPlotCurve tries to find a color representing the curve and paints a rectangle with it. */ LegendNoAttribute = 0x00, /*! If the style() is not QwtPlotCurve::NoCurve a line is painted with the curve pen(). */ LegendShowLine = 0x01, /*! If the curve has a valid symbol it is painted. */ LegendShowSymbol = 0x02, /*! If the curve has a brush a rectangle filled with the curve brush() is painted. */ LegendShowBrush = 0x04 }; //! Legend attributes //typedef QFlags LegendAttributes; /*! Attributes to modify the drawing algorithm. The default setting enables ClipPolygons | FilterPoints \sa setPaintAttribute(), testPaintAttribute() */ enum PaintAttribute { /*! Clip polygons before painting them. In situations, where points are far outside the visible area (f.e when zooming deep) this might be a substantial improvement for the painting performance */ ClipPolygons = 0x01, /*! Tries to reduce the data that has to be painted, by sorting out duplicates, or paintings outside the visible area. Might have a notable impact on curves with many close points. Only a couple of very basic filtering algorithms are implemented. */ FilterPoints = 0x02, /*! Minimize memory usage that is temporarily needed for the translated points, before they get painted. This might slow down the performance of painting */ MinimizeMemory = 0x04, /*! Render the points to a temporary image and paint the image. This is a very special optimization for Dots style, when having a huge amount of points. With a reasonable number of points QPainter::drawPoints() will be faster. */ ImageBuffer = 0x08 }; //! Paint attributes //typedef QFlags PaintAttributes; explicit QwtPlotCurve( const QString &title = QString::null); explicit QwtPlotCurve( const QwtText &title ); virtual ~QwtPlotCurve(); virtual int rtti() const; void setPaintAttribute( PaintAttribute, bool on = true ); bool testPaintAttribute( PaintAttribute ) const; void setLegendAttribute( LegendAttribute, bool on = true ); bool testLegendAttribute( LegendAttribute ) const; //#ifndef QWT_NO_COMPAT void setRawSamples( const double *xData, const double *yData, int size ); void setSamples( const double *xData, const double *yData, int size ); void setSamples( const QVector &xData, const QVector &yData ); void setSamples( const QPolygonF & ); void setSamples( const QVector & ); void setSamples( QwtSeriesDataQPointF * ); int closestPoint( const QPoint &pos, double *dist = NULL ) const; double minXValue() const; double maxXValue() const; double minYValue() const; double maxYValue() const; void setCurveAttribute( CurveAttribute, bool on = true ); bool testCurveAttribute( CurveAttribute ) const; void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); void setPen( const QPen & ); const QPen &pen() const; void setBrush( const QBrush & ); const QBrush &brush() const; void setBaseline( double ); double baseline() const; void setStyle( CurveStyle style ); CurveStyle style() const; void setSymbol( QwtSymbol * /Transfer/); const QwtSymbol *symbol() const; void setCurveFitter( QwtCurveFitter * /Transfer/); QwtCurveFitter *curveFitter() const; virtual void drawSeries( QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; protected: void init(); virtual void drawCurve( QPainter *p, int style, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void drawSymbols( QPainter *p, const QwtSymbol &, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void drawLines( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void drawSticks( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void drawDots( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void drawSteps( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual void fillCurve( QPainter *, const QwtScaleMap &, const QwtScaleMap &, const QRectF &canvasRect, QPolygonF & ) const; void closePolyline( QPainter *, const QwtScaleMap &, const QwtScaleMap &, QPolygonF & ) const; /*private: class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_dict.sip000066400000000000000000000020461377204562100175170ustar00rootroot00000000000000 /* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ typedef QList QwtPlotItemList; //typedef QList::ConstIterator QwtPlotItemIterator; class QwtPlotDict { %TypeHeaderCode #include %End public: explicit QwtPlotDict(); virtual ~QwtPlotDict(); void setAutoDelete( bool ); bool autoDelete() const; const QwtPlotItemList& itemList() const; QwtPlotItemList itemList( int rtti ) const; void detachItems( int rtti = QwtPlotItem::Rtti_PlotItem, bool autoDelete = true ); protected: void insertItem( QwtPlotItem * /Transfer/); void removeItem( QwtPlotItem * /Transfer/); /*private: class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_directpainter.sip000066400000000000000000000024131377204562100214270ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotDirectPainter: QObject { %TypeHeaderCode #include %End public: enum Attribute { AtomicPainter = 0x01, FullRepaint = 0x02, CopyBackingStore = 0x04 }; typedef QFlags Attributes; QwtPlotDirectPainter( QObject *parent /TransferThis/ = NULL ); virtual ~QwtPlotDirectPainter(); void setAttribute( Attribute, bool on ); bool testAttribute( Attribute ) const; void setClipping( bool ); bool hasClipping() const; void setClipRegion( const QRegion & ); QRegion clipRegion() const; void drawSeries( QwtPlotSeriesItem * /Transfer/, int from, int to ); void reset(); virtual bool eventFilter( QObject *, QEvent * ); /*private: class PrivateData; PrivateData *d_data;*/ }; //Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotDirectPainter::Attributes ) PyQt-Qwt-1.02.02/sip/qwt_plot_grid.sip000066400000000000000000000035121377204562100175200ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotGrid: QwtPlotItem { %TypeHeaderCode #include %End public: explicit QwtPlotGrid(); virtual ~QwtPlotGrid(); virtual int rtti() const; void enableX( bool tf ); bool xEnabled() const; void enableY( bool tf ); bool yEnabled() const; void enableXMin( bool tf ); bool xMinEnabled() const; void enableYMin( bool tf ); bool yMinEnabled() const; void setXDiv( const QwtScaleDiv &sx ); const QwtScaleDiv &xScaleDiv() const; void setYDiv( const QwtScaleDiv &sy ); const QwtScaleDiv &yScaleDiv() const; void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); void setPen( const QPen & ); void setMajorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); void setMajorPen( const QPen & ); const QPen& majorPen() const; void setMinorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); void setMinorPen( const QPen &p ); const QPen& minorPen() const; virtual void draw( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &rect ) const; virtual void updateScaleDiv( const QwtScaleDiv &xMap, const QwtScaleDiv &yMap ); /*private: void drawLines( QPainter *painter, const QRectF &, Qt::Orientation orientation, const QwtScaleMap &, const QList & ) const; class PrivateData; PrivateData *d_data;*/ }; PyQt-Qwt-1.02.02/sip/qwt_plot_histogram.sip000066400000000000000000000047011377204562100205710ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotHistogram: QwtPlotSeriesItem , QwtSeriesStoreQwtIntervalSample { %TypeHeaderCode #include typedef QwtSeriesStore QwtSeriesStoreQwtIntervalSample; %End public: enum HistogramStyle { Outline, Columns, Lines, UserStyle = 100 }; explicit QwtPlotHistogram( const QString &title = QString::null ); //explicit QwtPlotHistogram( const QwtText &title ); virtual ~QwtPlotHistogram(); virtual int rtti() const; void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); void setPen( const QPen & ); const QPen &pen() const; void setBrush( const QBrush & ); const QBrush &brush() const; void setSamples( const QVector & ); void setSamples( QwtSeriesDataQwtIntervalSample * ); void setBaseline( double reference ); double baseline() const; void setStyle( HistogramStyle style ); HistogramStyle style() const; void setSymbol( const QwtColumnSymbol * /Transfer/); const QwtColumnSymbol *symbol() const; virtual void drawSeries( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to ) const; virtual QRectF boundingRect() const; //virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; protected: virtual QwtColumnRect columnRect( const QwtIntervalSample &, const QwtScaleMap &, const QwtScaleMap & ) const; virtual void drawColumn( QPainter *, const QwtColumnRect &, const QwtIntervalSample & ) const; void drawColumns( QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to ) const; void drawOutline( QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to ) const; void drawLines( QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to ) const; private: void init(); void flushPolygon( QPainter *, double baseLine, QPolygonF & ) const; }; PyQt-Qwt-1.02.02/sip/qwt_plot_item.sip000066400000000000000000000147051377204562100175370ustar00rootroot00000000000000/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotItem { %TypeHeaderCode #include %End public: /*! \brief Runtime type information RttiValues is used to cast plot items, without having to enable runtime type information of the compiler. */ enum RttiValues { //! Unspecific value, that can be used, when it doesn't matter Rtti_PlotItem = 0, //! For QwtPlotGrid Rtti_PlotGrid, //! For QwtPlotScaleItem Rtti_PlotScale, //! For QwtPlotLegendItem Rtti_PlotLegend, //! For QwtPlotMarker Rtti_PlotMarker, //! For QwtPlotCurve Rtti_PlotCurve, //! For QwtPlotSpectroCurve Rtti_PlotSpectroCurve, //! For QwtPlotIntervalCurve Rtti_PlotIntervalCurve, //! For QwtPlotHistogram Rtti_PlotHistogram, //! For QwtPlotSpectrogram Rtti_PlotSpectrogram, //! For QwtPlotSvgItem Rtti_PlotSVG, //! For QwtPlotTradingCurve Rtti_PlotTradingCurve, //! For QwtPlotBarChart Rtti_PlotBarChart, //! For QwtPlotMultiBarChart Rtti_PlotMultiBarChart, //! For QwtPlotShapeItem Rtti_PlotShape, //! For QwtPlotTextLabel Rtti_PlotTextLabel, //! For QwtPlotZoneItem Rtti_PlotZone, /*! Values >= Rtti_PlotUserItem are reserved for plot items not implemented in the Qwt library. */ Rtti_PlotUserItem = 1000 }; /*! \brief Plot Item Attributes Various aspects of a plot widget depend on the attributes of the attached plot items. If and how a single plot item participates in these updates depends on its attributes. \sa setItemAttribute(), testItemAttribute(), ItemInterest */ enum ItemAttribute { //! The item is represented on the legend. Legend = 0x01, /*! The boundingRect() of the item is included in the autoscaling calculation as long as its width or height is >= 0.0. */ AutoScale = 0x02, /*! The item needs extra space to display something outside its bounding rectangle. \sa getCanvasMarginHint() */ Margins = 0x04 }; //! Plot Item Attributes typedef QFlags ItemAttributes; /*! \brief Plot Item Interests Plot items might depend on the situation of the corresponding plot widget. By enabling an interest the plot item will be notified, when the corresponding attribute of the plot widgets has changed. \sa setItemAttribute(), testItemAttribute(), ItemInterest */ enum ItemInterest { /*! The item is interested in updates of the scales \sa updateScaleDiv() */ ScaleInterest = 0x01, /*! The item is interested in updates of the legend ( of other items ) This flag is intended for items, that want to implement a legend for displaying entries of other plot item. \note If the plot item wants to be represented on a legend enable QwtPlotItem::Legend instead. \sa updateLegend() */ LegendInterest = 0x02 }; //! Plot Item Interests typedef QFlags ItemInterests; //! Render hints enum RenderHint { //! Enable antialiasing RenderAntialiased = 0x1 }; //! Render hints typedef QFlags RenderHints; explicit QwtPlotItem( const QwtText &title = QwtText() ); virtual ~QwtPlotItem(); void attach( QwtPlot *plot /TransferThis/); void detach(); QwtPlot *plot() const; void setTitle( const QString &title ); void setTitle( const QwtText &title ); const QwtText &title() const; virtual int rtti() const; void setItemAttribute( ItemAttribute, bool on = true ); bool testItemAttribute( ItemAttribute ) const; void setItemInterest( ItemInterest, bool on = true ); bool testItemInterest( ItemInterest ) const; void setRenderHint( RenderHint, bool on = true ); bool testRenderHint( RenderHint ) const; void setRenderThreadCount( uint numThreads ); uint renderThreadCount() const; void setLegendIconSize( const QSize & ); QSize legendIconSize() const; double z() const; void setZ( double z ); void show(); void hide(); virtual void setVisible( bool ); bool isVisible () const; void setAxes( int xAxis, int yAxis ); void setXAxis( int axis ); int xAxis() const; void setYAxis( int axis ); int yAxis() const; virtual void itemChanged(); virtual void legendChanged(); /*! \brief Draw the item \param painter Painter \param xMap Maps x-values into pixel coordinates. \param yMap Maps y-values into pixel coordinates. \param canvasRect Contents rect of the canvas in painter coordinates */ virtual void draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect ) const = 0; virtual QRectF boundingRect() const; virtual void getCanvasMarginHint( const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasSize, double &left, double &top, double &right, double &bottom) const; virtual void updateScaleDiv( const QwtScaleDiv&, const QwtScaleDiv& ); virtual void updateLegend( const QwtPlotItem *, const QList & ); QRectF scaleRect( const QwtScaleMap &, const QwtScaleMap & ) const; QRectF paintRect( const QwtScaleMap &, const QwtScaleMap & ) const; virtual QList legendData() const; /* virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; protected: QwtGraphic defaultIcon( const QBrush &, const QSizeF & ) const; */ private: // Disabled copy constructor and operator= QwtPlotItem( const QwtPlotItem & ); QwtPlotItem &operator=( const QwtPlotItem & ); }; PyQt-Qwt-1.02.02/sip/qwt_plot_layout.sip000066400000000000000000000054451377204562100201170ustar00rootroot00000000000000/* * python-qwt. Python wrapper for the Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * Copyright (C) 2015 Gudjon I. Gudjonsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ class QwtPlotLayout { %TypeHeaderCode #include %End public: /*! Options to configure the plot layout engine \sa activate(), QwtPlotRenderer */ enum Option { //! Unused AlignScales = 0x01, /*! Ignore the dimension of the scrollbars. There are no scrollbars, when the plot is not rendered to widgets. */ IgnoreScrollbars = 0x02, //! Ignore all frames. IgnoreFrames = 0x04, //! Ignore the legend. IgnoreLegend = 0x08, //! Ignore the title. IgnoreTitle = 0x10, //! Ignore the footer. IgnoreFooter = 0x20 }; //! Layout options //typedef QFlags