├── README.md ├── .gitattributes ├── main.cpp ├── serial_plot_template_project.pro ├── .gitignore ├── mainwindow.h ├── win_qextserialport.h ├── qextserialbase.cpp ├── qextserialbase.h ├── mainwindow.ui ├── mainwindow.cpp ├── serial_plot_template_project.pro.user ├── win_qextserialport.cpp └── qcustomplot.h /README.md: -------------------------------------------------------------------------------- 1 | # Qt-Serial-PID-Host 2 | Qt写的上位机,用来在线调试PID参数,使用串口通信 3 | 绘图使用qcustomplot, 串口通信使用qextserial。 4 | ![image](http://github.com/xuafei/Qt-Serial-PID-Host/raw/master/pic.png) 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication a(argc, argv); 8 | QTextCodec *codec = QTextCodec::codecForName("UTF-8"); 9 | QTextCodec::setCodecForCStrings(codec); 10 | MainWindow w; 11 | w.setFixedSize(720, 450); //固定窗口大小 12 | w.setWindowFlags(Qt::WindowCloseButtonHint); //主窗口只有关闭按钮 13 | w.show(); 14 | 15 | return a.exec(); 16 | } 17 | -------------------------------------------------------------------------------- /serial_plot_template_project.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-07-14T19:13:39 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport 10 | 11 | TARGET = serial_plot_template_project 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += main.cpp\ 16 | mainwindow.cpp \ 17 | qcustomplot.cpp \ 18 | qextserialbase.cpp \ 19 | win_qextserialport.cpp 20 | 21 | HEADERS += mainwindow.h \ 22 | qcustomplot.h \ 23 | qextserialbase.h \ 24 | win_qextserialport.h 25 | 26 | FORMS += mainwindow.ui 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "win_qextserialport.h" 6 | #include "qcustomplot.h" 7 | #include 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWindow(QWidget *parent = 0); 19 | ~MainWindow(); 20 | 21 | private slots: 22 | void on_button_open_clicked(); 23 | void on_button_filter_clicked(); 24 | void readMyCom(); 25 | void on_button_close_clicked(); 26 | void on_hSlider_pid_a_valueChanged(int value); 27 | void on_hSlider_pid_b_valueChanged(int value); 28 | void on_hSlider_pid_c_valueChanged(int value); 29 | 30 | void on_button_switch_clicked(); 31 | 32 | private: 33 | Ui::MainWindow *ui; 34 | Win_QextSerialPort *myCom = NULL; 35 | bool isMyComOpen; 36 | bool isStart; 37 | QVector *t; 38 | QVector *x1, *x2, *pwm; 39 | 40 | void setupPlot(QCustomPlot *customPlot); 41 | void plotUpdate(QCustomPlot *customPlot, double _x1, double _x2, double _pwm); 42 | void select_serial_port(); 43 | void send_parameter(float val, unsigned char head2); 44 | void read_saved_pid_parameter(); 45 | void save_pid_parameter(); 46 | void closeEvent(QCloseEvent *event); 47 | }; 48 | 49 | #endif // MAINWINDOW_H 50 | -------------------------------------------------------------------------------- /win_qextserialport.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIN_QEXTSERIALPORT_H_ 2 | #define _WIN_QEXTSERIALPORT_H_ 3 | 4 | #include "qextserialbase.h" 5 | #include 6 | #include 7 | 8 | 9 | /*if all warning messages are turned off, flag portability warnings to be turned off as well*/ 10 | #ifdef _TTY_NOWARN_ 11 | #define _TTY_NOWARN_PORT_ 12 | #endif 13 | 14 | class QReadWriteLock; 15 | class Win_QextSerialThread; 16 | 17 | 18 | /*! 19 | \author Stefan Sander 20 | \author Michal Policht 21 | 22 | A cross-platform serial port class. 23 | This class encapsulates the Windows portion of QextSerialPort. The user will be notified of 24 | errors and possible portability conflicts at run-time by default - this behavior can be turned 25 | off by defining _TTY_NOWARN_ (to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off 26 | portability warnings) in the project. Note that defining _TTY_NOWARN_ also defines 27 | _TTY_NOWARN_PORT_. 28 | 29 | \note 30 | On Windows NT/2000/XP this class uses Win32 serial port functions by default. The user may 31 | select POSIX behavior under NT, 2000, or XP ONLY by defining _TTY_POSIX_ in the project. I can 32 | make no guarantees as to the quality of POSIX support under NT/2000 however. 33 | 34 | \todo remove copy constructor and assign operator. 35 | */ 36 | class Win_QextSerialPort: public QextSerialBase 37 | { 38 | Q_OBJECT 39 | friend class Win_QextSerialThread; 40 | 41 | private: 42 | /*! 43 | * This method is a part of constructor. 44 | */ 45 | void init(); 46 | 47 | protected: 48 | HANDLE Win_Handle; 49 | HANDLE threadStartEvent; 50 | HANDLE threadTerminateEvent; 51 | OVERLAPPED overlap; 52 | OVERLAPPED overlapWrite; 53 | COMMCONFIG Win_CommConfig; 54 | COMMTIMEOUTS Win_CommTimeouts; 55 | QReadWriteLock * bytesToWriteLock; ///< @todo maybe move to QextSerialBase. 56 | qint64 _bytesToWrite; ///< @todo maybe move to QextSerialBase (and implement in POSIX). 57 | Win_QextSerialThread * overlapThread; ///< @todo maybe move to QextSerialBase (and implement in POSIX). 58 | 59 | void monitorCommEvent(); 60 | void terminateCommWait(); 61 | virtual qint64 readData(char *data, qint64 maxSize); 62 | virtual qint64 writeData(const char *data, qint64 maxSize); 63 | 64 | public: 65 | Win_QextSerialPort(); 66 | Win_QextSerialPort(Win_QextSerialPort const& s); 67 | Win_QextSerialPort(const QString & name, QextSerialBase::QueryMode mode = QextSerialBase::Polling); 68 | Win_QextSerialPort(const PortSettings& settings, QextSerialBase::QueryMode mode = QextSerialBase::Polling); 69 | Win_QextSerialPort(const QString & name, const PortSettings& settings, QextSerialBase::QueryMode mode = QextSerialBase::Polling); 70 | Win_QextSerialPort& operator=(const Win_QextSerialPort& s); 71 | virtual ~Win_QextSerialPort(); 72 | virtual bool open(OpenMode mode); 73 | virtual void close(); 74 | virtual void flush(); 75 | virtual qint64 size() const; 76 | virtual void ungetChar(char c); 77 | virtual void setFlowControl(FlowType); 78 | virtual void setParity(ParityType); 79 | virtual void setDataBits(DataBitsType); 80 | virtual void setStopBits(StopBitsType); 81 | virtual void setBaudRate(BaudRateType); 82 | virtual void setDtr(bool set=true); 83 | virtual void setRts(bool set=true); 84 | virtual ulong lineStatus(void); 85 | virtual qint64 bytesAvailable(); 86 | virtual void translateError(ulong); 87 | virtual void setTimeout(long); 88 | 89 | /*! 90 | * Return number of bytes waiting in the buffer. Currently this shows number 91 | * of bytes queued within write() and before the TX_EMPTY event occured. TX_EMPTY 92 | * event is created whenever last character in the system buffer was sent. 93 | * 94 | * \return number of bytes queued within write(), before the first TX_EMPTY 95 | * event occur. 96 | * 97 | * \warning this function may not give you expected results since TX_EMPTY may occur 98 | * while writing data to the buffer. Eventually some TX_EMPTY events may not be 99 | * catched. 100 | * 101 | * \note this function always returns 0 in polling mode. 102 | * 103 | * \see flush(). 104 | */ 105 | virtual qint64 bytesToWrite() const; 106 | 107 | virtual bool waitForReadyRead(int msecs); ///< @todo implement. 108 | }; 109 | 110 | /*! 111 | * This thread monitors communication events. 112 | */ 113 | class Win_QextSerialThread: public QThread 114 | { 115 | Win_QextSerialPort * qesp; 116 | bool terminate; 117 | 118 | public: 119 | /*! 120 | * Constructor. 121 | * 122 | * \param qesp valid serial port object. 123 | */ 124 | Win_QextSerialThread(Win_QextSerialPort * qesp); 125 | 126 | /*! 127 | * Stop the thread. 128 | */ 129 | void stop(); 130 | 131 | protected: 132 | //overriden 133 | virtual void run(); 134 | 135 | }; 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /qextserialbase.cpp: -------------------------------------------------------------------------------- 1 | #include "qextserialbase.h" 2 | 3 | /*! 4 | \fn QextSerialBase::QextSerialBase() 5 | Default constructor. 6 | */ 7 | QextSerialBase::QextSerialBase() 8 | : QIODevice() 9 | { 10 | 11 | #ifdef _TTY_WIN_ 12 | setPortName("COM1"); 13 | 14 | #elif defined(_TTY_IRIX_) 15 | setPortName("/dev/ttyf1"); 16 | 17 | #elif defined(_TTY_HPUX_) 18 | setPortName("/dev/tty1p0"); 19 | 20 | #elif defined(_TTY_SUN_) 21 | setPortName("/dev/ttya"); 22 | 23 | #elif defined(_TTY_DIGITAL_) 24 | setPortName("/dev/tty01"); 25 | 26 | #elif defined(_TTY_FREEBSD_) 27 | setPortName("/dev/ttyd1"); 28 | 29 | #else 30 | setPortName("/dev/ttyS0"); 31 | #endif 32 | 33 | construct(); 34 | } 35 | 36 | /*! 37 | \fn QextSerialBase::QextSerialBase(const QString & name) 38 | Construct a port and assign it to the device specified by the name parameter. 39 | */ 40 | QextSerialBase::QextSerialBase(const QString & name) 41 | : QIODevice() 42 | { 43 | setPortName(name); 44 | construct(); 45 | } 46 | 47 | /*! 48 | \fn QextSerialBase::~QextSerialBase() 49 | Standard destructor. 50 | */ 51 | QextSerialBase::~QextSerialBase() 52 | { 53 | delete mutex; 54 | } 55 | 56 | /*! 57 | \fn void QextSerialBase::construct() 58 | Common constructor function for setting up default port settings. 59 | (115200 Baud, 8N1, Hardware flow control where supported, otherwise no flow control, and 0 ms timeout). 60 | */ 61 | void QextSerialBase::construct() 62 | { 63 | Settings.BaudRate=BAUD115200; 64 | Settings.DataBits=DATA_8; 65 | Settings.Parity=PAR_NONE; 66 | Settings.StopBits=STOP_1; 67 | Settings.FlowControl=FLOW_HARDWARE; 68 | Settings.Timeout_Millisec=500; 69 | mutex = new QMutex( QMutex::Recursive ); 70 | setOpenMode(QIODevice::NotOpen); 71 | } 72 | 73 | void QextSerialBase::setQueryMode(QueryMode mechanism) 74 | { 75 | _queryMode = mechanism; 76 | } 77 | 78 | /*! 79 | \fn void QextSerialBase::setPortName(const QString & name) 80 | Sets the name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0". 81 | */ 82 | void QextSerialBase::setPortName(const QString & name) 83 | { 84 | port = name; 85 | } 86 | 87 | /*! 88 | \fn QString QextSerialBase::portName() const 89 | Returns the name set by setPortName(). 90 | */ 91 | QString QextSerialBase::portName() const 92 | { 93 | return port; 94 | } 95 | 96 | /*! 97 | \fn BaudRateType QextSerialBase::baudRate(void) const 98 | Returns the baud rate of the serial port. For a list of possible return values see 99 | the definition of the enum BaudRateType. 100 | */ 101 | BaudRateType QextSerialBase::baudRate(void) const 102 | { 103 | return Settings.BaudRate; 104 | } 105 | 106 | /*! 107 | \fn DataBitsType QextSerialBase::dataBits() const 108 | Returns the number of data bits used by the port. For a list of possible values returned by 109 | this function, see the definition of the enum DataBitsType. 110 | */ 111 | DataBitsType QextSerialBase::dataBits() const 112 | { 113 | return Settings.DataBits; 114 | } 115 | 116 | /*! 117 | \fn ParityType QextSerialBase::parity() const 118 | Returns the type of parity used by the port. For a list of possible values returned by 119 | this function, see the definition of the enum ParityType. 120 | */ 121 | ParityType QextSerialBase::parity() const 122 | { 123 | return Settings.Parity; 124 | } 125 | 126 | /*! 127 | \fn StopBitsType QextSerialBase::stopBits() const 128 | Returns the number of stop bits used by the port. For a list of possible return values, see 129 | the definition of the enum StopBitsType. 130 | */ 131 | StopBitsType QextSerialBase::stopBits() const 132 | { 133 | return Settings.StopBits; 134 | } 135 | 136 | /*! 137 | \fn FlowType QextSerialBase::flowControl() const 138 | Returns the type of flow control used by the port. For a list of possible values returned 139 | by this function, see the definition of the enum FlowType. 140 | */ 141 | FlowType QextSerialBase::flowControl() const 142 | { 143 | return Settings.FlowControl; 144 | } 145 | 146 | /*! 147 | \fn bool QextSerialBase::isSequential() const 148 | Returns true if device is sequential, otherwise returns false. Serial port is sequential device 149 | so this function always returns true. Check QIODevice::isSequential() documentation for more 150 | information. 151 | */ 152 | bool QextSerialBase::isSequential() const 153 | { 154 | return true; 155 | } 156 | 157 | /*! 158 | \fn bool QextSerialBase::atEnd() const 159 | This function will return true if the input buffer is empty (or on error), and false otherwise. 160 | Call QextSerialBase::lastError() for error information. 161 | */ 162 | bool QextSerialBase::atEnd() const 163 | { 164 | if (size()) { 165 | return true; 166 | } 167 | return false; 168 | } 169 | 170 | /*! 171 | \fn qint64 QextSerialBase::readLine(char * data, qint64 maxSize) 172 | This function will read a line of buffered input from the port, stopping when either maxSize bytes 173 | have been read, the port has no more data available, or a newline is encountered. 174 | The value returned is the length of the string that was read. 175 | */ 176 | qint64 QextSerialBase::readLine(char * data, qint64 maxSize) 177 | { 178 | qint64 numBytes = bytesAvailable(); 179 | char* pData = data; 180 | 181 | if (maxSize < 2) //maxSize must be larger than 1 182 | return -1; 183 | 184 | /*read a byte at a time for MIN(bytesAvail, maxSize - 1) iterations, or until a newline*/ 185 | while (pData<(data+numBytes) && --maxSize) { 186 | readData(pData, 1); 187 | if (*pData++ == '\n') { 188 | break; 189 | } 190 | } 191 | *pData='\0'; 192 | 193 | /*return size of data read*/ 194 | return (pData-data); 195 | } 196 | 197 | /*! 198 | \fn ulong QextSerialBase::lastError() const 199 | Returns the code for the last error encountered by the port, or E_NO_ERROR if the last port 200 | operation was successful. Possible error codes are: 201 | 202 | \verbatim 203 | Error Explanation 204 | --------------------------- ------------------------------------------------------------- 205 | E_NO_ERROR No Error has occured 206 | E_INVALID_FD Invalid file descriptor (port was not opened correctly) 207 | E_NO_MEMORY Unable to allocate memory tables (POSIX) 208 | E_CAUGHT_NON_BLOCKED_SIGNAL Caught a non-blocked signal (POSIX) 209 | E_PORT_TIMEOUT Operation timed out (POSIX) 210 | E_INVALID_DEVICE The file opened by the port is not a character device (POSIX) 211 | E_BREAK_CONDITION The port detected a break condition 212 | E_FRAMING_ERROR The port detected a framing error 213 | (usually caused by incorrect baud rate settings) 214 | E_IO_ERROR There was an I/O error while communicating with the port 215 | E_BUFFER_OVERRUN Character buffer overrun 216 | E_RECEIVE_OVERFLOW Receive buffer overflow 217 | E_RECEIVE_PARITY_ERROR The port detected a parity error in the received data 218 | E_TRANSMIT_OVERFLOW Transmit buffer overflow 219 | E_READ_FAILED General read operation failure 220 | E_WRITE_FAILED General write operation failure 221 | \endverbatim 222 | */ 223 | ulong QextSerialBase::lastError() const 224 | { 225 | return lastErr; 226 | } 227 | -------------------------------------------------------------------------------- /qextserialbase.h: -------------------------------------------------------------------------------- 1 | #ifndef _QEXTSERIALBASE_H_ 2 | #define _QEXTSERIALBASE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /*if all warning messages are turned off, flag portability warnings to be turned off as well*/ 10 | #ifdef _TTY_NOWARN_ 11 | #define _TTY_NOWARN_PORT_ 12 | #endif 13 | 14 | /*macros for thread support*/ 15 | #define LOCK_MUTEX() mutex->lock() 16 | #define UNLOCK_MUTEX() mutex->unlock() 17 | 18 | /*macros for warning and debug messages*/ 19 | #ifdef _TTY_NOWARN_PORT_ 20 | #define TTY_PORTABILITY_WARNING(s) 21 | #else 22 | #define TTY_PORTABILITY_WARNING(s) qWarning(s) 23 | #endif /*_TTY_NOWARN_PORT_*/ 24 | #ifdef _TTY_NOWARN_ 25 | #define TTY_WARNING(s) 26 | #else 27 | #define TTY_WARNING(s) qWarning(s) 28 | #endif /*_TTY_NOWARN_*/ 29 | 30 | 31 | /*line status constants*/ 32 | #define LS_CTS 0x01 33 | #define LS_DSR 0x02 34 | #define LS_DCD 0x04 35 | #define LS_RI 0x08 36 | #define LS_RTS 0x10 37 | #define LS_DTR 0x20 38 | #define LS_ST 0x40 39 | #define LS_SR 0x80 40 | 41 | /*error constants*/ 42 | #define E_NO_ERROR 0 43 | #define E_INVALID_FD 1 44 | #define E_NO_MEMORY 2 45 | #define E_CAUGHT_NON_BLOCKED_SIGNAL 3 46 | #define E_PORT_TIMEOUT 4 47 | #define E_INVALID_DEVICE 5 48 | #define E_BREAK_CONDITION 6 49 | #define E_FRAMING_ERROR 7 50 | #define E_IO_ERROR 8 51 | #define E_BUFFER_OVERRUN 9 52 | #define E_RECEIVE_OVERFLOW 10 53 | #define E_RECEIVE_PARITY_ERROR 11 54 | #define E_TRANSMIT_OVERFLOW 12 55 | #define E_READ_FAILED 13 56 | #define E_WRITE_FAILED 14 57 | 58 | /*! 59 | * Enums for port settings. 60 | */ 61 | enum NamingConvention 62 | { 63 | WIN_NAMES, 64 | IRIX_NAMES, 65 | HPUX_NAMES, 66 | SUN_NAMES, 67 | DIGITAL_NAMES, 68 | FREEBSD_NAMES, 69 | LINUX_NAMES 70 | }; 71 | 72 | enum BaudRateType 73 | { 74 | BAUD50, //POSIX ONLY 75 | BAUD75, //POSIX ONLY 76 | BAUD110, 77 | BAUD134, //POSIX ONLY 78 | BAUD150, //POSIX ONLY 79 | BAUD200, //POSIX ONLY 80 | BAUD300, 81 | BAUD600, 82 | BAUD1200, 83 | BAUD1800, //POSIX ONLY 84 | BAUD2400, 85 | BAUD4800, 86 | BAUD9600, 87 | BAUD14400, //WINDOWS ONLY 88 | BAUD19200, 89 | BAUD38400, 90 | BAUD56000, //WINDOWS ONLY 91 | BAUD57600, 92 | BAUD76800, //POSIX ONLY 93 | BAUD115200, 94 | BAUD128000, //WINDOWS ONLY 95 | BAUD256000 //WINDOWS ONLY 96 | }; 97 | 98 | enum DataBitsType 99 | { 100 | DATA_5, 101 | DATA_6, 102 | DATA_7, 103 | DATA_8 104 | }; 105 | 106 | enum ParityType 107 | { 108 | PAR_NONE, 109 | PAR_ODD, 110 | PAR_EVEN, 111 | PAR_MARK, //WINDOWS ONLY 112 | PAR_SPACE 113 | }; 114 | 115 | enum StopBitsType 116 | { 117 | STOP_1, 118 | STOP_1_5, //WINDOWS ONLY 119 | STOP_2 120 | }; 121 | 122 | enum FlowType 123 | { 124 | FLOW_OFF, 125 | FLOW_HARDWARE, 126 | FLOW_XONXOFF 127 | }; 128 | 129 | /** 130 | * structure to contain port settings 131 | */ 132 | struct PortSettings 133 | { 134 | BaudRateType BaudRate; 135 | DataBitsType DataBits; 136 | ParityType Parity; 137 | StopBitsType StopBits; 138 | FlowType FlowControl; 139 | long Timeout_Millisec; 140 | }; 141 | 142 | /*! 143 | * \author Stefan Sander 144 | * \author Michal Policht 145 | * 146 | * A common base class for Win_QextSerialBase, Posix_QextSerialBase and QextSerialPort. 147 | */ 148 | class QextSerialBase : public QIODevice 149 | { 150 | Q_OBJECT 151 | 152 | public: 153 | enum QueryMode { 154 | Polling, 155 | EventDriven 156 | }; 157 | 158 | protected: 159 | QMutex* mutex; 160 | QString port; 161 | PortSettings Settings; 162 | ulong lastErr; 163 | QextSerialBase::QueryMode _queryMode; 164 | 165 | virtual qint64 readData(char * data, qint64 maxSize)=0; 166 | virtual qint64 writeData(const char * data, qint64 maxSize)=0; 167 | 168 | public: 169 | QextSerialBase(); 170 | QextSerialBase(const QString & name); 171 | virtual ~QextSerialBase(); 172 | virtual void construct(); 173 | virtual void setPortName(const QString & name); 174 | virtual QString portName() const; 175 | 176 | /**! 177 | * Get query mode. 178 | * \return query mode. 179 | */ 180 | inline QextSerialBase::QueryMode queryMode() const { return _queryMode; }; 181 | 182 | /*! 183 | * Set desired serial communication handling style. You may choose from polling 184 | * or event driven approach. This function does nothing when port is open; to 185 | * apply changes port must be reopened. 186 | * 187 | * In event driven approach read() and write() functions are acting 188 | * asynchronously. They return immediately and the operation is performed in 189 | * the background, so they doesn't freeze the calling thread. 190 | * To determine when operation is finished, QextSerialPort runs separate thread 191 | * and monitors serial port events. Whenever the event occurs, adequate signal 192 | * is emitted. 193 | * 194 | * When polling is set, read() and write() are acting synchronously. Signals are 195 | * not working in this mode and some functions may not be available. The advantage 196 | * of polling is that it generates less overhead due to lack of signals emissions 197 | * and it doesn't start separate thread to monitor events. 198 | * 199 | * Generally event driven approach is more capable and friendly, although some 200 | * applications may need as low overhead as possible and then polling comes. 201 | * 202 | * \param mode query mode. 203 | */ 204 | virtual void setQueryMode(QueryMode mode); 205 | 206 | // virtual void setBlockingRead(bool block) = 0; ///< @todo implement. 207 | 208 | virtual void setBaudRate(BaudRateType)=0; 209 | virtual BaudRateType baudRate() const; 210 | virtual void setDataBits(DataBitsType)=0; 211 | virtual DataBitsType dataBits() const; 212 | virtual void setParity(ParityType)=0; 213 | virtual ParityType parity() const; 214 | virtual void setStopBits(StopBitsType)=0; 215 | virtual StopBitsType stopBits() const; 216 | virtual void setFlowControl(FlowType)=0; 217 | virtual FlowType flowControl() const; 218 | virtual void setTimeout(long)=0; 219 | 220 | virtual bool open(OpenMode mode)=0; 221 | virtual bool isSequential() const; 222 | virtual void close()=0; 223 | virtual void flush()=0; 224 | 225 | virtual qint64 size() const=0; 226 | virtual qint64 bytesAvailable()=0; 227 | virtual bool atEnd() const; 228 | 229 | virtual void ungetChar(char c)=0; 230 | virtual qint64 readLine(char * data, qint64 maxSize); 231 | 232 | virtual ulong lastError() const; 233 | virtual void translateError(ulong error)=0; 234 | 235 | virtual void setDtr(bool set=true)=0; 236 | virtual void setRts(bool set=true)=0; 237 | virtual ulong lineStatus()=0; 238 | 239 | signals: 240 | /** 241 | * This signal is emitted whenever port settings are updated. 242 | * \param valid \p true if settings are valid, \p false otherwise. 243 | * 244 | * @todo implement. 245 | */ 246 | // void validSettings(bool valid); 247 | 248 | /*! 249 | * This signal is emitted whenever dsr line has changed its state. You may 250 | * use this signal to check if device is connected. 251 | * \param status \p true when DSR signal is on, \p false otherwise. 252 | * 253 | * \see lineStatus(). 254 | */ 255 | void dsrChanged(bool status); 256 | }; 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 720 10 | 460 11 | 12 | 13 | 14 | Host海坊主 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 720 23 | 320 24 | 25 | 26 | 27 | horizontalLayoutWidget 28 | 29 | 30 | 31 | 32 | 0 33 | 320 34 | 721 35 | 131 36 | 37 | 38 | 39 | 40 | 10 41 | 42 | 43 | 10 44 | 45 | 46 | 47 | 48 | 10 49 | 50 | 51 | 52 | 53 | 54 | 55 | 打开串口 56 | 57 | 58 | 59 | 60 | 61 | 62 | 关闭串口 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 检测 79 | 80 | 81 | 82 | 83 | 84 | 85 | 开始/停止 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | PID->A 103 | 104 | 105 | 106 | 107 | 108 | 109 | 0 110 | 111 | 112 | 113 | 114 | 115 | 116 | 99 117 | 118 | 119 | Qt::Horizontal 120 | 121 | 122 | 123 | 124 | 125 | 126 | 0 127 | 128 | 129 | 130 | 131 | 132 | 133 | 100 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | PID->B 145 | 146 | 147 | 148 | 149 | 150 | 151 | 0 152 | 153 | 154 | 155 | 156 | 157 | 158 | 99 159 | 160 | 161 | Qt::Horizontal 162 | 163 | 164 | 165 | 166 | 167 | 168 | 0 169 | 170 | 171 | 172 | 173 | 174 | 175 | 100 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | PID->C 187 | 188 | 189 | 190 | 191 | 192 | 193 | 0 194 | 195 | 196 | 197 | 198 | 199 | 200 | 99 201 | 202 | 203 | Qt::Horizontal 204 | 205 | 206 | 207 | 208 | 209 | 210 | 0 211 | 212 | 213 | 214 | 215 | 216 | 217 | 100 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 0 232 | 0 233 | 720 234 | 23 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | QCustomPlot 243 | QWidget 244 |
qcustomplot.h
245 | 1 246 |
247 |
248 | 249 | 250 |
251 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include 4 | #include 5 | 6 | MainWindow::MainWindow(QWidget *parent) : 7 | QMainWindow(parent), 8 | ui(new Ui::MainWindow) 9 | { 10 | ui->setupUi(this); 11 | setupPlot(ui->customPlot); 12 | 13 | isMyComOpen = false; 14 | isStart = false; 15 | ui->button_close->setEnabled(false); 16 | 17 | read_saved_pid_parameter(); 18 | select_serial_port(); 19 | } 20 | 21 | //检测可用串口 22 | void MainWindow::select_serial_port() 23 | { 24 | QString portName; 25 | ui->comboBox->removeItem(0); 26 | ui->comboBox->removeItem(1); 27 | myCom = new Win_QextSerialPort("COM1",QextSerialBase::EventDriven); 28 | for(int i=0; i<12; i++){ 29 | portName = QString("COM%0").arg(i+1); 30 | myCom->setPortName(portName); 31 | if(myCom->open(QIODevice::ReadWrite) == true){ 32 | ui->comboBox->addItem(portName); 33 | myCom->close(); 34 | } 35 | } 36 | delete myCom; 37 | if(ui->comboBox->count() > 0){ 38 | ui->button_open->setEnabled(true); 39 | } 40 | } 41 | 42 | MainWindow::~MainWindow() 43 | { 44 | delete ui; 45 | } 46 | 47 | //绘图初始化 48 | void MainWindow::setupPlot(QCustomPlot *customPlot) 49 | { 50 | t = new QVector; 51 | x1 = new QVector; 52 | x2 = new QVector; 53 | pwm = new QVector; 54 | 55 | customPlot->legend->setVisible(true); 56 | customPlot->legend->setFont(QFont("Helvetica",9)); 57 | 58 | customPlot->addGraph(); 59 | customPlot->graph(0)->setName("x1"); 60 | customPlot->graph(0)->setData(*t, *x1); 61 | customPlot->graph(0)->setPen(QPen(Qt::blue)); 62 | 63 | customPlot->addGraph(); 64 | customPlot->graph(1)->setName("x2"); 65 | customPlot->graph(1)->setData(*t, *x2); 66 | customPlot->graph(1)->setPen(QPen(Qt::red)); 67 | 68 | customPlot->addGraph(); 69 | customPlot->graph(2)->setName("pwm"); 70 | customPlot->graph(2)->setData(*t, *pwm); 71 | customPlot->graph(2)->setPen(QPen(Qt::green)); 72 | 73 | customPlot->xAxis->setLabel("time/s"); 74 | customPlot->xAxis->setAutoTickCount(9); 75 | customPlot->yAxis->setLabel("angle/(m/s)"); 76 | customPlot->yAxis->setAutoTickCount(9); 77 | customPlot->xAxis2->setVisible(true); 78 | customPlot->xAxis2->setTickLabels(false); 79 | customPlot->yAxis2->setVisible(true); 80 | customPlot->yAxis2->setTickLabels(false); 81 | connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange))); 82 | connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange))); 83 | customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables); 84 | customPlot->replot(); 85 | } 86 | 87 | //绘图更新 88 | void MainWindow::plotUpdate(QCustomPlot *customPlot, double _x1, double _x2, double _pwm) 89 | { 90 | static int num = 0; 91 | static int counter = 0; 92 | double time = (counter++)*0.01; 93 | t->append(time); 94 | x1->append(_x1); 95 | x2->append(_x2); 96 | pwm->append(_pwm); 97 | if(counter >= 300){ 98 | t->remove(0); 99 | x1->remove(0); 100 | x2->remove(0); 101 | pwm->remove(0); 102 | } 103 | //customPlot->graph(0)->rescaleAxes(false); 104 | customPlot->yAxis->setRange(-180, 180); 105 | customPlot->xAxis->setRange(time-3, time+1); 106 | customPlot->graph(0)->setData(*t, *x1); 107 | customPlot->graph(1)->setData(*t, *x2); 108 | customPlot->graph(2)->setData(*t, *pwm); 109 | num++; 110 | if(num == 10){ 111 | num = 0; 112 | customPlot->replot(); 113 | } 114 | } 115 | 116 | //打开串口 117 | void MainWindow::on_button_open_clicked() 118 | { 119 | QString portName = ui->comboBox->currentText(); 120 | 121 | myCom = new Win_QextSerialPort(portName,QextSerialBase::EventDriven); 122 | if(myCom ->open(QIODevice::ReadWrite) == false){ 123 | QMessageBox::information(NULL, "星海坊主", "打开串口失败!"); 124 | return; 125 | } 126 | myCom->setBaudRate(BAUD115200); 127 | myCom->setDataBits(DATA_8); 128 | myCom->setParity(PAR_NONE); 129 | myCom->setStopBits(STOP_1); 130 | myCom->setFlowControl(FLOW_OFF); 131 | myCom->setTimeout(1000); 132 | connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom())); 133 | isMyComOpen = true; 134 | 135 | ui->button_close->setEnabled(true); 136 | ui->button_open->setEnabled(false); 137 | } 138 | 139 | //检测按钮回调 140 | void MainWindow::on_button_filter_clicked() 141 | { 142 | select_serial_port(); 143 | } 144 | 145 | #define BUFFER_HEAD1 0X55 146 | #define BUFFER_HEAD2 0X66 147 | #define BUFFER_SIZE 14 148 | //读串口 149 | void MainWindow::readMyCom() 150 | { 151 | static unsigned char buffer[BUFFER_SIZE] = {0}; 152 | static unsigned char counter = 0; 153 | char ch; 154 | double _x1, _x2, _pwm; 155 | while(myCom->bytesAvailable()){ 156 | myCom->getChar(&ch); 157 | buffer[counter] = ch; 158 | if(buffer[0] != BUFFER_HEAD1 && counter == 0){ 159 | return; 160 | } 161 | counter++; 162 | if(counter == 2 && buffer[1] != BUFFER_HEAD2){ 163 | counter = 0; 164 | return; 165 | } 166 | if(counter == BUFFER_SIZE){ 167 | counter = 0; 168 | _x1 = (double)((buffer[2]<<24)|(buffer[3]<<16)|(buffer[4]<<8)|buffer[5])/1000.0f-180; 169 | _x2 = (double)((buffer[6]<<24)|(buffer[7]<<16)|(buffer[8]<<8)|buffer[9])/1000.0f-180; 170 | _pwm = (double)((buffer[10]<<24)|(buffer[11]<<16)|(buffer[12]<<8)|buffer[13])/1000.0f-100; 171 | plotUpdate(ui->customPlot, _x1, _x2, _pwm); 172 | } 173 | } 174 | } 175 | 176 | //关闭串口 177 | void MainWindow::on_button_close_clicked() 178 | { 179 | isMyComOpen = false; 180 | if(myCom->isOpen()){ 181 | myCom->close(); 182 | } 183 | delete myCom; 184 | ui->button_close->setEnabled(false); 185 | ui->button_open->setEnabled(true); 186 | } 187 | 188 | #define HEAD1 0XAA 189 | #define HEAD2_A 0X11 190 | #define HEAD2_B 0X22 191 | #define HEAD2_C 0X33 192 | #define HEAD2_SWITCH_START 0XBB 193 | #define HEAD2_SWITCH_STOP 0XCC 194 | //发送一个参数 195 | void MainWindow::send_parameter(float val, unsigned char head2) 196 | { 197 | char buffer[7] = {0}; 198 | buffer[0] = HEAD1; 199 | buffer[1] = head2; 200 | unsigned int int_val = (unsigned int)(val*1000+0.5f); 201 | buffer[2] = int_val>>24; 202 | buffer[3] = int_val>>16; 203 | buffer[4] = int_val>>8; 204 | buffer[5] = int_val; 205 | buffer[6] = buffer[2]^buffer[3]^buffer[4]^buffer[5]; 206 | if(isMyComOpen){ 207 | myCom->write(buffer, 7); 208 | } 209 | } 210 | 211 | //滑动条PID->A回调 212 | void MainWindow::on_hSlider_pid_a_valueChanged(int value) 213 | { 214 | int min = ui->lineEdit_min_a->text().toInt(); 215 | int max = ui->lineEdit_max_a->text().toInt(); 216 | float a = value/100.0f*(max-min)+min; 217 | QString a_str = QString("%1").arg(a); 218 | ui->lineEdit_pid_a->setText(a_str); 219 | send_parameter(a, HEAD2_A); 220 | } 221 | 222 | //滑动条PID->B回调 223 | void MainWindow::on_hSlider_pid_b_valueChanged(int value) 224 | { 225 | int min = ui->lineEdit_min_b->text().toInt(); 226 | int max = ui->lineEdit_max_b->text().toInt(); 227 | float b = value/100.0f*(max-min)+min; 228 | QString b_str = QString("%1").arg(b); 229 | ui->lineEdit_pid_b->setText(b_str); 230 | send_parameter(b, HEAD2_B); 231 | } 232 | 233 | //滑动条PID->C回调 234 | void MainWindow::on_hSlider_pid_c_valueChanged(int value) 235 | { 236 | int min = ui->lineEdit_min_c->text().toInt(); 237 | int max = ui->lineEdit_max_c->text().toInt(); 238 | float c = value/100.0f*(max-min)+min; 239 | QString c_str = QString("%1").arg(c); 240 | ui->lineEdit_pid_c->setText(c_str); 241 | send_parameter(c, HEAD2_C); 242 | } 243 | 244 | #include 245 | //读取PID参数 246 | void MainWindow::read_saved_pid_parameter() 247 | { 248 | FILE *fp; 249 | fp = fopen("./pid.txt", "r"); 250 | if(fp == NULL){ 251 | QMessageBox::information(NULL, "星海坊主", "pid.txt打开失败!"); 252 | return; 253 | } 254 | QString str; 255 | float a; 256 | int pos_a, max_a, min_a; 257 | float b; 258 | int pos_b, max_b, min_b; 259 | float c; 260 | int pos_c, max_c, min_c; 261 | 262 | fscanf(fp, "%f %d %d %d\n", &a, &pos_a, &max_a, &min_a); 263 | fscanf(fp, "%f %d %d %d\n", &b, &pos_b, &max_b, &min_b); 264 | fscanf(fp, "%f %d %d %d\n", &c, &pos_c, &max_c, &min_c); 265 | 266 | str = QString("%1").arg(max_a); 267 | ui->lineEdit_max_a->setText(str); 268 | str = QString("%1").arg(min_a); 269 | ui->lineEdit_min_a->setText(str); 270 | str = QString("%1").arg(a); 271 | ui->lineEdit_pid_a->setText(str); 272 | ui->hSlider_pid_a->setValue(pos_a); 273 | 274 | str = QString("%1").arg(max_b); 275 | ui->lineEdit_max_b->setText(str); 276 | str = QString("%1").arg(min_b); 277 | ui->lineEdit_min_b->setText(str); 278 | str = QString("%1").arg(b); 279 | ui->lineEdit_pid_b->setText(str); 280 | ui->hSlider_pid_b->setValue(pos_b); 281 | 282 | str = QString("%1").arg(max_c); 283 | ui->lineEdit_max_c->setText(str); 284 | str = QString("%1").arg(min_c); 285 | ui->lineEdit_min_c->setText(str); 286 | str = QString("%1").arg(c); 287 | ui->lineEdit_pid_c->setText(str); 288 | ui->hSlider_pid_c->setValue(pos_c); 289 | 290 | fclose(fp); 291 | } 292 | 293 | //保存PID参数 294 | void MainWindow::save_pid_parameter() 295 | { 296 | FILE *fp; 297 | fp = fopen("./pid.txt", "w"); 298 | if(fp == NULL){ 299 | QMessageBox::information(NULL, "星海坊主", "pid.txt打开失败!"); 300 | return; 301 | } 302 | float a; 303 | int pos_a, max_a, min_a; 304 | float b; 305 | int pos_b, max_b, min_b; 306 | float c; 307 | int pos_c, max_c, min_c; 308 | 309 | a = ui->lineEdit_pid_a->text().toFloat(); 310 | b = ui->lineEdit_pid_b->text().toFloat(); 311 | c = ui->lineEdit_pid_c->text().toFloat(); 312 | 313 | pos_a = ui->hSlider_pid_a->value(); 314 | pos_b = ui->hSlider_pid_b->value(); 315 | pos_c = ui->hSlider_pid_c->value(); 316 | 317 | max_a = ui->lineEdit_max_a->text().toInt(); 318 | max_b = ui->lineEdit_max_b->text().toInt(); 319 | max_c = ui->lineEdit_max_c->text().toInt(); 320 | 321 | min_a = ui->lineEdit_min_a->text().toInt(); 322 | min_b = ui->lineEdit_min_b->text().toInt(); 323 | min_c = ui->lineEdit_min_c->text().toInt(); 324 | 325 | fprintf(fp, "%f %d %d %d\n", a, pos_a, max_a, min_a); 326 | fprintf(fp, "%f %d %d %d\n", b, pos_b, max_b, min_b); 327 | fprintf(fp, "%f %d %d %d\n", c, pos_c, max_c, min_c); 328 | fclose(fp); 329 | } 330 | 331 | //串口关闭事件,保存PID参数 332 | void MainWindow::closeEvent(QCloseEvent *event) 333 | { 334 | save_pid_parameter(); 335 | } 336 | 337 | void MainWindow::on_button_switch_clicked() 338 | { 339 | if(isStart){ 340 | isStart = false; 341 | send_parameter(0, HEAD2_SWITCH_STOP); 342 | } 343 | else{ 344 | isStart = true; 345 | send_parameter(0, HEAD2_SWITCH_START); 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /serial_plot_template_project.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {b47d198b-5b7a-4253-9031-91541c82953e} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 2 43 | true 44 | 2 45 | 8 46 | true 47 | 1 48 | true 49 | true 50 | true 51 | false 52 | 53 | 54 | 55 | ProjectExplorer.Project.PluginSettings 56 | 57 | 58 | 59 | ProjectExplorer.Project.Target.0 60 | 61 | desktop 62 | desktop 63 | {88555dea-ba22-48ec-9d99-e30611874589} 64 | 1 65 | 0 66 | 0 67 | 68 | D:/QtSpace/build-serial_plot_template_project-desktop-Debug 69 | 70 | 71 | true 72 | qmake 73 | 74 | QtProjectManager.QMakeBuildStep 75 | false 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | false 89 | 90 | 91 | 92 | 2 93 | 构建 94 | 95 | ProjectExplorer.BuildSteps.Build 96 | 97 | 98 | 99 | true 100 | Make 101 | 102 | Qt4ProjectManager.MakeStep 103 | 104 | true 105 | clean 106 | 107 | 108 | 1 109 | 清理 110 | 111 | ProjectExplorer.BuildSteps.Clean 112 | 113 | 2 114 | false 115 | 116 | Debug 117 | 118 | Qt4ProjectManager.Qt4BuildConfiguration 119 | 2 120 | true 121 | 122 | 123 | D:/QtSpace/build-serial_plot_template_project-desktop-Release 124 | 125 | 126 | true 127 | qmake 128 | 129 | QtProjectManager.QMakeBuildStep 130 | false 131 | true 132 | 133 | false 134 | false 135 | false 136 | 137 | 138 | true 139 | Make 140 | 141 | Qt4ProjectManager.MakeStep 142 | 143 | false 144 | 145 | 146 | 147 | 2 148 | 构建 149 | 150 | ProjectExplorer.BuildSteps.Build 151 | 152 | 153 | 154 | true 155 | Make 156 | 157 | Qt4ProjectManager.MakeStep 158 | 159 | true 160 | clean 161 | 162 | 163 | 1 164 | 清理 165 | 166 | ProjectExplorer.BuildSteps.Clean 167 | 168 | 2 169 | false 170 | 171 | Release 172 | 173 | Qt4ProjectManager.Qt4BuildConfiguration 174 | 0 175 | true 176 | 177 | 2 178 | 179 | 180 | 0 181 | 部署 182 | 183 | ProjectExplorer.BuildSteps.Deploy 184 | 185 | 1 186 | 在本地部署 187 | 188 | ProjectExplorer.DefaultDeployConfiguration 189 | 190 | 1 191 | 192 | 193 | 194 | false 195 | false 196 | false 197 | false 198 | true 199 | 0.01 200 | 10 201 | true 202 | 1 203 | 25 204 | 205 | 1 206 | true 207 | false 208 | true 209 | valgrind 210 | 211 | 0 212 | 1 213 | 2 214 | 3 215 | 4 216 | 5 217 | 6 218 | 7 219 | 8 220 | 9 221 | 10 222 | 11 223 | 12 224 | 13 225 | 14 226 | 227 | 2 228 | 229 | serial_plot_template_project 230 | 231 | Qt4ProjectManager.Qt4RunConfiguration:D:/QtSpace/serial_plot_template_project/serial_plot_template_project.pro 232 | 233 | serial_plot_template_project.pro 234 | false 235 | false 236 | 237 | 3768 238 | false 239 | true 240 | false 241 | false 242 | true 243 | 244 | 1 245 | 246 | 247 | 248 | ProjectExplorer.Project.TargetCount 249 | 1 250 | 251 | 252 | ProjectExplorer.Project.Updater.FileVersion 253 | 18 254 | 255 | 256 | Version 257 | 18 258 | 259 | 260 | -------------------------------------------------------------------------------- /win_qextserialport.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | //#include 4 | //#include 5 | #include 6 | #include "win_qextserialport.h" 7 | 8 | 9 | /*! 10 | \fn Win_QextSerialPort::Win_QextSerialPort() 11 | Default constructor. Note that the name of the device used by a Win_QextSerialPort constructed 12 | with this constructor will be determined by #defined constants, or lack thereof - the default 13 | behavior is the same as _TTY_LINUX_. Possible naming conventions and their associated constants 14 | are: 15 | 16 | \verbatim 17 | 18 | Constant Used By Naming Convention 19 | ---------- ------------- ------------------------ 20 | _TTY_WIN_ Windows COM1, COM2 21 | _TTY_IRIX_ SGI/IRIX /dev/ttyf1, /dev/ttyf2 22 | _TTY_HPUX_ HP-UX /dev/tty1p0, /dev/tty2p0 23 | _TTY_SUN_ SunOS/Solaris /dev/ttya, /dev/ttyb 24 | _TTY_DIGITAL_ Digital UNIX /dev/tty01, /dev/tty02 25 | _TTY_FREEBSD_ FreeBSD /dev/ttyd0, /dev/ttyd1 26 | _TTY_LINUX_ Linux /dev/ttyS0, /dev/ttyS1 27 | Linux /dev/ttyS0, /dev/ttyS1 28 | \endverbatim 29 | 30 | This constructor associates the object with the first port on the system, e.g. COM1 for Windows 31 | platforms. See the other constructor if you need a port other than the first. 32 | */ 33 | Win_QextSerialPort::Win_QextSerialPort(): 34 | QextSerialBase() 35 | { 36 | Win_Handle=INVALID_HANDLE_VALUE; 37 | init(); 38 | } 39 | 40 | /*!Win_QextSerialPort::Win_QextSerialPort(const Win_QextSerialPort&) 41 | Copy constructor. 42 | */ 43 | Win_QextSerialPort::Win_QextSerialPort(const Win_QextSerialPort& s): 44 | QextSerialBase(s.port) 45 | { 46 | Win_Handle=INVALID_HANDLE_VALUE; 47 | _queryMode = s._queryMode; 48 | _bytesToWrite = s._bytesToWrite; 49 | bytesToWriteLock = new QReadWriteLock; 50 | overlapThread = new Win_QextSerialThread(this); 51 | memcpy(& overlap, & s.overlap, sizeof(OVERLAPPED)); 52 | memcpy(& overlapWrite, & s.overlapWrite, sizeof(OVERLAPPED)); 53 | setOpenMode(s.openMode()); 54 | lastErr=s.lastErr; 55 | port = s.port; 56 | Settings.FlowControl=s.Settings.FlowControl; 57 | Settings.Parity=s.Settings.Parity; 58 | Settings.DataBits=s.Settings.DataBits; 59 | Settings.StopBits=s.Settings.StopBits; 60 | Settings.BaudRate=s.Settings.BaudRate; 61 | Win_Handle=s.Win_Handle; 62 | memcpy(&Win_CommConfig, &s.Win_CommConfig, sizeof(COMMCONFIG)); 63 | memcpy(&Win_CommTimeouts, &s.Win_CommTimeouts, sizeof(COMMTIMEOUTS)); 64 | if (s.overlapThread->isRunning()) 65 | overlapThread->start(); 66 | } 67 | 68 | /*! 69 | \fn Win_QextSerialPort::Win_QextSerialPort(const QString & name) 70 | Constructs a serial port attached to the port specified by devName. 71 | devName is the name of the device, which is windowsystem-specific, 72 | e.g."COM2" or "/dev/ttyS0". 73 | */ 74 | Win_QextSerialPort::Win_QextSerialPort(const QString & name, QextSerialBase::QueryMode mode): 75 | QextSerialBase(name) 76 | { 77 | Win_Handle=INVALID_HANDLE_VALUE; 78 | setQueryMode(mode); 79 | init(); 80 | } 81 | 82 | /*! 83 | \fn Win_QextSerialPort::Win_QextSerialPort(const PortSettings& settings) 84 | Constructs a port with default name and specified settings. 85 | */ 86 | Win_QextSerialPort::Win_QextSerialPort(const PortSettings& settings, QextSerialBase::QueryMode mode) { 87 | Win_Handle=INVALID_HANDLE_VALUE; 88 | setBaudRate(settings.BaudRate); 89 | setDataBits(settings.DataBits); 90 | setStopBits(settings.StopBits); 91 | setParity(settings.Parity); 92 | setFlowControl(settings.FlowControl); 93 | setTimeout(settings.Timeout_Millisec); 94 | setQueryMode(mode); 95 | init(); 96 | } 97 | 98 | /*! 99 | \fn Win_QextSerialPort::Win_QextSerialPort(const QString & name, const PortSettings& settings) 100 | Constructs a port with specified name and settings. 101 | */ 102 | Win_QextSerialPort::Win_QextSerialPort(const QString & name, const PortSettings& settings, QextSerialBase::QueryMode mode) { 103 | Win_Handle=INVALID_HANDLE_VALUE; 104 | setPortName(name); 105 | setBaudRate(settings.BaudRate); 106 | setDataBits(settings.DataBits); 107 | setStopBits(settings.StopBits); 108 | setParity(settings.Parity); 109 | setFlowControl(settings.FlowControl); 110 | setTimeout(settings.Timeout_Millisec); 111 | setQueryMode(mode); 112 | init(); 113 | } 114 | 115 | void Win_QextSerialPort::init() 116 | { 117 | _bytesToWrite = 0; 118 | overlap.Internal = 0; 119 | overlap.InternalHigh = 0; 120 | overlap.Offset = 0; 121 | overlap.OffsetHigh = 0; 122 | overlap.hEvent = CreateEvent(NULL, true, false, NULL); 123 | overlapThread = new Win_QextSerialThread(this); 124 | bytesToWriteLock = new QReadWriteLock; 125 | } 126 | 127 | /*! 128 | \fn Win_QextSerialPort::~Win_QextSerialPort() 129 | Standard destructor. 130 | */ 131 | Win_QextSerialPort::~Win_QextSerialPort() { 132 | if (isOpen()) { 133 | close(); 134 | } 135 | CloseHandle(overlap.hEvent); 136 | delete overlapThread; 137 | delete bytesToWriteLock; 138 | } 139 | 140 | /*! 141 | \fn Win_QextSerialPort& Win_QextSerialPort::operator=(const Win_QextSerialPort& s) 142 | overrides the = operator 143 | */ 144 | Win_QextSerialPort& Win_QextSerialPort::operator=(const Win_QextSerialPort& s) { 145 | setOpenMode(s.openMode()); 146 | _queryMode = s._queryMode; 147 | _bytesToWrite = s._bytesToWrite; 148 | bytesToWriteLock = new QReadWriteLock; 149 | overlapThread = new Win_QextSerialThread(this); 150 | memcpy(& overlap, & s.overlap, sizeof(OVERLAPPED)); 151 | memcpy(& overlapWrite, & s.overlapWrite, sizeof(OVERLAPPED)); 152 | lastErr=s.lastErr; 153 | port = s.port; 154 | Settings.FlowControl=s.Settings.FlowControl; 155 | Settings.Parity=s.Settings.Parity; 156 | Settings.DataBits=s.Settings.DataBits; 157 | Settings.StopBits=s.Settings.StopBits; 158 | Settings.BaudRate=s.Settings.BaudRate; 159 | Win_Handle=s.Win_Handle; 160 | memcpy(&Win_CommConfig, &s.Win_CommConfig, sizeof(COMMCONFIG)); 161 | memcpy(&Win_CommTimeouts, &s.Win_CommTimeouts, sizeof(COMMTIMEOUTS)); 162 | if (s.overlapThread->isRunning()) 163 | overlapThread->start(); 164 | return *this; 165 | } 166 | 167 | 168 | /*! 169 | \fn bool Win_QextSerialPort::open(OpenMode mode) 170 | Opens a serial port. Note that this function does not specify which device to open. If you need 171 | to open a device by name, see Win_QextSerialPort::open(const char*). This function has no effect 172 | if the port associated with the class is already open. The port is also configured to the current 173 | settings, as stored in the Settings structure. 174 | */ 175 | bool Win_QextSerialPort::open(OpenMode mode) { 176 | unsigned long confSize = sizeof(COMMCONFIG); 177 | Win_CommConfig.dwSize = confSize; 178 | DWORD dwFlagsAndAttributes = 0; 179 | if (queryMode() == QextSerialBase::EventDriven) 180 | dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED; 181 | 182 | LOCK_MUTEX(); 183 | if (mode == QIODevice::NotOpen) 184 | return isOpen(); 185 | if (!isOpen()) { 186 | /*open the port*/ 187 | Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE, 188 | FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); 189 | if (Win_Handle!=INVALID_HANDLE_VALUE) { 190 | /*configure port settings*/ 191 | GetCommConfig(Win_Handle, &Win_CommConfig, &confSize); 192 | GetCommState(Win_Handle, &(Win_CommConfig.dcb)); 193 | 194 | /*set up parameters*/ 195 | Win_CommConfig.dcb.fBinary=TRUE; 196 | Win_CommConfig.dcb.fInX=FALSE; 197 | Win_CommConfig.dcb.fOutX=FALSE; 198 | Win_CommConfig.dcb.fAbortOnError=FALSE; 199 | Win_CommConfig.dcb.fNull=FALSE; 200 | setBaudRate(Settings.BaudRate); 201 | setDataBits(Settings.DataBits); 202 | setStopBits(Settings.StopBits); 203 | setParity(Settings.Parity); 204 | setFlowControl(Settings.FlowControl); 205 | setTimeout(Settings.Timeout_Millisec); 206 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 207 | 208 | //init event driven approach 209 | if (queryMode() == QextSerialBase::EventDriven) { 210 | Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD; 211 | Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0; 212 | Win_CommTimeouts.ReadTotalTimeoutConstant = 0; 213 | Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0; 214 | Win_CommTimeouts.WriteTotalTimeoutConstant = 0; 215 | SetCommTimeouts(Win_Handle, &Win_CommTimeouts); 216 | if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) { 217 | qWarning("Failed to set Comm Mask. Error code: %ld", GetLastError()); 218 | UNLOCK_MUTEX(); 219 | return false; 220 | } 221 | overlapThread->start(); 222 | } 223 | QIODevice::open(mode); 224 | } 225 | } else { 226 | UNLOCK_MUTEX(); 227 | return false; 228 | } 229 | UNLOCK_MUTEX(); 230 | return isOpen(); 231 | } 232 | 233 | /*! 234 | \fn void Win_QextSerialPort::close() 235 | Closes a serial port. This function has no effect if the serial port associated with the class 236 | is not currently open. 237 | */ 238 | void Win_QextSerialPort::close() 239 | { 240 | LOCK_MUTEX(); 241 | 242 | if (isOpen()) { 243 | flush(); 244 | if (overlapThread->isRunning()) { 245 | overlapThread->stop(); 246 | if (QThread::currentThread() != overlapThread) 247 | overlapThread->wait(); 248 | } 249 | if (CloseHandle(Win_Handle)) 250 | Win_Handle = INVALID_HANDLE_VALUE; 251 | _bytesToWrite = 0; 252 | QIODevice::close(); 253 | } 254 | 255 | UNLOCK_MUTEX(); 256 | } 257 | 258 | /*! 259 | \fn void Win_QextSerialPort::flush() 260 | Flushes all pending I/O to the serial port. This function has no effect if the serial port 261 | associated with the class is not currently open. 262 | */ 263 | void Win_QextSerialPort::flush() { 264 | LOCK_MUTEX(); 265 | if (isOpen()) { 266 | FlushFileBuffers(Win_Handle); 267 | } 268 | UNLOCK_MUTEX(); 269 | } 270 | 271 | /*! 272 | \fn qint64 Win_QextSerialPort::size() const 273 | This function will return the number of bytes waiting in the receive queue of the serial port. 274 | It is included primarily to provide a complete QIODevice interface, and will not record errors 275 | in the lastErr member (because it is const). This function is also not thread-safe - in 276 | multithreading situations, use Win_QextSerialPort::bytesAvailable() instead. 277 | */ 278 | qint64 Win_QextSerialPort::size() const { 279 | int availBytes; 280 | COMSTAT Win_ComStat; 281 | DWORD Win_ErrorMask=0; 282 | ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat); 283 | availBytes = Win_ComStat.cbInQue; 284 | return (qint64)availBytes; 285 | } 286 | 287 | /*! 288 | \fn qint64 Win_QextSerialPort::bytesAvailable() 289 | Returns the number of bytes waiting in the port's receive queue. This function will return 0 if 290 | the port is not currently open, or -1 on error. Error information can be retrieved by calling 291 | Win_QextSerialPort::getLastError(). 292 | */ 293 | qint64 Win_QextSerialPort::bytesAvailable() { 294 | LOCK_MUTEX(); 295 | if (isOpen()) { 296 | DWORD Errors; 297 | COMSTAT Status; 298 | bool success=ClearCommError(Win_Handle, &Errors, &Status); 299 | translateError(Errors); 300 | if (success) { 301 | lastErr=E_NO_ERROR; 302 | UNLOCK_MUTEX(); 303 | return Status.cbInQue + QIODevice::bytesAvailable(); 304 | } 305 | UNLOCK_MUTEX(); 306 | return (unsigned int)-1; 307 | } 308 | UNLOCK_MUTEX(); 309 | return 0; 310 | } 311 | 312 | /*! 313 | \fn void Win_QextSerialPort::translateError(ulong error) 314 | Translates a system-specific error code to a QextSerialPort error code. Used internally. 315 | */ 316 | void Win_QextSerialPort::translateError(ulong error) { 317 | if (error&CE_BREAK) { 318 | lastErr=E_BREAK_CONDITION; 319 | } 320 | else if (error&CE_FRAME) { 321 | lastErr=E_FRAMING_ERROR; 322 | } 323 | else if (error&CE_IOE) { 324 | lastErr=E_IO_ERROR; 325 | } 326 | else if (error&CE_MODE) { 327 | lastErr=E_INVALID_FD; 328 | } 329 | else if (error&CE_OVERRUN) { 330 | lastErr=E_BUFFER_OVERRUN; 331 | } 332 | else if (error&CE_RXPARITY) { 333 | lastErr=E_RECEIVE_PARITY_ERROR; 334 | } 335 | else if (error&CE_RXOVER) { 336 | lastErr=E_RECEIVE_OVERFLOW; 337 | } 338 | else if (error&CE_TXFULL) { 339 | lastErr=E_TRANSMIT_OVERFLOW; 340 | } 341 | } 342 | 343 | /*! 344 | \fn qint64 Win_QextSerialPort::readData(char *data, qint64 maxSize) 345 | Reads a block of data from the serial port. This function will read at most maxlen bytes from 346 | the serial port and place them in the buffer pointed to by data. Return value is the number of 347 | bytes actually read, or -1 on error. 348 | 349 | \warning before calling this function ensure that serial port associated with this class 350 | is currently open (use isOpen() function to check if port is open). 351 | */ 352 | qint64 Win_QextSerialPort::readData(char *data, qint64 maxSize) 353 | { 354 | DWORD retVal; 355 | 356 | LOCK_MUTEX(); 357 | 358 | retVal = 0; 359 | if (queryMode() == QextSerialBase::EventDriven) { 360 | OVERLAPPED overlapRead; 361 | overlapRead.Internal = 0; 362 | overlapRead.InternalHigh = 0; 363 | overlapRead.Offset = 0; 364 | overlapRead.OffsetHigh = 0; 365 | overlapRead.hEvent = CreateEvent(NULL, true, false, NULL); 366 | if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, & overlapRead)) { 367 | if (GetLastError() == ERROR_IO_PENDING) 368 | GetOverlappedResult(Win_Handle, & overlapRead, & retVal, true); 369 | else { 370 | lastErr = E_READ_FAILED; 371 | retVal = (DWORD)-1; 372 | } 373 | } 374 | CloseHandle(overlapRead.hEvent); 375 | } else if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) { 376 | lastErr = E_READ_FAILED; 377 | retVal = (DWORD)-1; 378 | } 379 | 380 | UNLOCK_MUTEX(); 381 | 382 | return (qint64)retVal; 383 | } 384 | 385 | /*! 386 | \fn qint64 Win_QextSerialPort::writeData(const char *data, qint64 maxSize) 387 | Writes a block of data to the serial port. This function will write len bytes 388 | from the buffer pointed to by data to the serial port. Return value is the number 389 | of bytes actually written, or -1 on error. 390 | 391 | \warning before calling this function ensure that serial port associated with this class 392 | is currently open (use isOpen() function to check if port is open). 393 | */ 394 | qint64 Win_QextSerialPort::writeData(const char *data, qint64 maxSize) 395 | { 396 | DWORD retVal; 397 | 398 | LOCK_MUTEX(); 399 | 400 | retVal = 0; 401 | if (queryMode() == QextSerialBase::EventDriven) { 402 | bytesToWriteLock->lockForWrite(); 403 | _bytesToWrite += maxSize; 404 | bytesToWriteLock->unlock(); 405 | overlapWrite.Internal = 0; 406 | overlapWrite.InternalHigh = 0; 407 | overlapWrite.Offset = 0; 408 | overlapWrite.OffsetHigh = 0; 409 | overlapWrite.hEvent = CreateEvent(NULL, true, false, NULL); 410 | if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, & overlapWrite)) { 411 | lastErr = E_WRITE_FAILED; 412 | retVal = (DWORD)-1; 413 | } else 414 | retVal = maxSize; 415 | } else if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) { 416 | lastErr = E_WRITE_FAILED; 417 | retVal = (DWORD)-1; 418 | } 419 | 420 | UNLOCK_MUTEX(); 421 | 422 | return (qint64)retVal; 423 | } 424 | 425 | /*! 426 | \fn void Win_QextSerialPort::ungetChar(char c) 427 | This function is included to implement the full QIODevice interface, and currently has no 428 | purpose within this class. This function is meaningless on an unbuffered device and currently 429 | only prints a warning message to that effect. 430 | */ 431 | void Win_QextSerialPort::ungetChar(char c) { 432 | 433 | /*meaningless on unbuffered sequential device - return error and print a warning*/ 434 | TTY_WARNING("Win_QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless"); 435 | } 436 | 437 | /*! 438 | \fn void Win_QextSerialPort::setFlowControl(FlowType flow) 439 | Sets the flow control used by the port. Possible values of flow are: 440 | \verbatim 441 | FLOW_OFF No flow control 442 | FLOW_HARDWARE Hardware (RTS/CTS) flow control 443 | FLOW_XONXOFF Software (XON/XOFF) flow control 444 | \endverbatim 445 | */ 446 | void Win_QextSerialPort::setFlowControl(FlowType flow) { 447 | LOCK_MUTEX(); 448 | if (Settings.FlowControl!=flow) { 449 | Settings.FlowControl=flow; 450 | } 451 | if (isOpen()) { 452 | switch(flow) { 453 | 454 | /*no flow control*/ 455 | case FLOW_OFF: 456 | Win_CommConfig.dcb.fOutxCtsFlow=FALSE; 457 | Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE; 458 | Win_CommConfig.dcb.fInX=FALSE; 459 | Win_CommConfig.dcb.fOutX=FALSE; 460 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 461 | break; 462 | 463 | /*software (XON/XOFF) flow control*/ 464 | case FLOW_XONXOFF: 465 | Win_CommConfig.dcb.fOutxCtsFlow=FALSE; 466 | Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE; 467 | Win_CommConfig.dcb.fInX=TRUE; 468 | Win_CommConfig.dcb.fOutX=TRUE; 469 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 470 | break; 471 | 472 | case FLOW_HARDWARE: 473 | Win_CommConfig.dcb.fOutxCtsFlow=TRUE; 474 | Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE; 475 | Win_CommConfig.dcb.fInX=FALSE; 476 | Win_CommConfig.dcb.fOutX=FALSE; 477 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 478 | break; 479 | } 480 | } 481 | UNLOCK_MUTEX(); 482 | } 483 | 484 | /*! 485 | \fn void Win_QextSerialPort::setParity(ParityType parity) 486 | Sets the parity associated with the serial port. The possible values of parity are: 487 | \verbatim 488 | PAR_SPACE Space Parity 489 | PAR_MARK Mark Parity 490 | PAR_NONE No Parity 491 | PAR_EVEN Even Parity 492 | PAR_ODD Odd Parity 493 | \endverbatim 494 | */ 495 | void Win_QextSerialPort::setParity(ParityType parity) { 496 | LOCK_MUTEX(); 497 | if (Settings.Parity!=parity) { 498 | Settings.Parity=parity; 499 | } 500 | if (isOpen()) { 501 | Win_CommConfig.dcb.Parity=(unsigned char)parity; 502 | switch (parity) { 503 | 504 | /*space parity*/ 505 | case PAR_SPACE: 506 | if (Settings.DataBits==DATA_8) { 507 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems."); 508 | } 509 | Win_CommConfig.dcb.fParity=TRUE; 510 | break; 511 | 512 | /*mark parity - WINDOWS ONLY*/ 513 | case PAR_MARK: 514 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: Mark parity is not supported by POSIX systems"); 515 | Win_CommConfig.dcb.fParity=TRUE; 516 | break; 517 | 518 | /*no parity*/ 519 | case PAR_NONE: 520 | Win_CommConfig.dcb.fParity=FALSE; 521 | break; 522 | 523 | /*even parity*/ 524 | case PAR_EVEN: 525 | Win_CommConfig.dcb.fParity=TRUE; 526 | break; 527 | 528 | /*odd parity*/ 529 | case PAR_ODD: 530 | Win_CommConfig.dcb.fParity=TRUE; 531 | break; 532 | } 533 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 534 | } 535 | UNLOCK_MUTEX(); 536 | } 537 | 538 | /*! 539 | \fn void Win_QextSerialPort::setDataBits(DataBitsType dataBits) 540 | Sets the number of data bits used by the serial port. Possible values of dataBits are: 541 | \verbatim 542 | DATA_5 5 data bits 543 | DATA_6 6 data bits 544 | DATA_7 7 data bits 545 | DATA_8 8 data bits 546 | \endverbatim 547 | 548 | \note 549 | This function is subject to the following restrictions: 550 | \par 551 | 5 data bits cannot be used with 2 stop bits. 552 | \par 553 | 1.5 stop bits can only be used with 5 data bits. 554 | \par 555 | 8 data bits cannot be used with space parity on POSIX systems. 556 | 557 | */ 558 | void Win_QextSerialPort::setDataBits(DataBitsType dataBits) { 559 | LOCK_MUTEX(); 560 | if (Settings.DataBits!=dataBits) { 561 | if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) || 562 | (Settings.StopBits==STOP_1_5 && dataBits!=DATA_5)) { 563 | } 564 | else { 565 | Settings.DataBits=dataBits; 566 | } 567 | } 568 | if (isOpen()) { 569 | switch(dataBits) { 570 | 571 | /*5 data bits*/ 572 | case DATA_5: 573 | if (Settings.StopBits==STOP_2) { 574 | TTY_WARNING("Win_QextSerialPort: 5 Data bits cannot be used with 2 stop bits."); 575 | } 576 | else { 577 | Win_CommConfig.dcb.ByteSize=5; 578 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 579 | } 580 | break; 581 | 582 | /*6 data bits*/ 583 | case DATA_6: 584 | if (Settings.StopBits==STOP_1_5) { 585 | TTY_WARNING("Win_QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits."); 586 | } 587 | else { 588 | Win_CommConfig.dcb.ByteSize=6; 589 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 590 | } 591 | break; 592 | 593 | /*7 data bits*/ 594 | case DATA_7: 595 | if (Settings.StopBits==STOP_1_5) { 596 | TTY_WARNING("Win_QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits."); 597 | } 598 | else { 599 | Win_CommConfig.dcb.ByteSize=7; 600 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 601 | } 602 | break; 603 | 604 | /*8 data bits*/ 605 | case DATA_8: 606 | if (Settings.StopBits==STOP_1_5) { 607 | TTY_WARNING("Win_QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits."); 608 | } 609 | else { 610 | Win_CommConfig.dcb.ByteSize=8; 611 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 612 | } 613 | break; 614 | } 615 | } 616 | UNLOCK_MUTEX(); 617 | } 618 | 619 | /*! 620 | \fn void Win_QextSerialPort::setStopBits(StopBitsType stopBits) 621 | Sets the number of stop bits used by the serial port. Possible values of stopBits are: 622 | \verbatim 623 | STOP_1 1 stop bit 624 | STOP_1_5 1.5 stop bits 625 | STOP_2 2 stop bits 626 | \endverbatim 627 | 628 | \note 629 | This function is subject to the following restrictions: 630 | \par 631 | 2 stop bits cannot be used with 5 data bits. 632 | \par 633 | 1.5 stop bits cannot be used with 6 or more data bits. 634 | \par 635 | POSIX does not support 1.5 stop bits. 636 | */ 637 | void Win_QextSerialPort::setStopBits(StopBitsType stopBits) { 638 | LOCK_MUTEX(); 639 | if (Settings.StopBits!=stopBits) { 640 | if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) || 641 | (stopBits==STOP_1_5 && Settings.DataBits!=DATA_5)) { 642 | } 643 | else { 644 | Settings.StopBits=stopBits; 645 | } 646 | } 647 | if (isOpen()) { 648 | switch (stopBits) { 649 | 650 | /*one stop bit*/ 651 | case STOP_1: 652 | Win_CommConfig.dcb.StopBits=ONESTOPBIT; 653 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 654 | break; 655 | 656 | /*1.5 stop bits*/ 657 | case STOP_1_5: 658 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX."); 659 | if (Settings.DataBits!=DATA_5) { 660 | TTY_WARNING("Win_QextSerialPort: 1.5 stop bits can only be used with 5 data bits"); 661 | } 662 | else { 663 | Win_CommConfig.dcb.StopBits=ONE5STOPBITS; 664 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 665 | } 666 | break; 667 | 668 | /*two stop bits*/ 669 | case STOP_2: 670 | if (Settings.DataBits==DATA_5) { 671 | TTY_WARNING("Win_QextSerialPort: 2 stop bits cannot be used with 5 data bits"); 672 | } 673 | else { 674 | Win_CommConfig.dcb.StopBits=TWOSTOPBITS; 675 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 676 | } 677 | break; 678 | } 679 | } 680 | UNLOCK_MUTEX(); 681 | } 682 | 683 | /*! 684 | \fn void Win_QextSerialPort::setBaudRate(BaudRateType baudRate) 685 | Sets the baud rate of the serial port. Note that not all rates are applicable on 686 | all platforms. The following table shows translations of the various baud rate 687 | constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * 688 | are speeds that are usable on both Windows and POSIX. 689 | \verbatim 690 | 691 | RATE Windows Speed POSIX Speed 692 | ----------- ------------- ----------- 693 | BAUD50 110 50 694 | BAUD75 110 75 695 | *BAUD110 110 110 696 | BAUD134 110 134.5 697 | BAUD150 110 150 698 | BAUD200 110 200 699 | *BAUD300 300 300 700 | *BAUD600 600 600 701 | *BAUD1200 1200 1200 702 | BAUD1800 1200 1800 703 | *BAUD2400 2400 2400 704 | *BAUD4800 4800 4800 705 | *BAUD9600 9600 9600 706 | BAUD14400 14400 9600 707 | *BAUD19200 19200 19200 708 | *BAUD38400 38400 38400 709 | BAUD56000 56000 38400 710 | *BAUD57600 57600 57600 711 | BAUD76800 57600 76800 712 | *BAUD115200 115200 115200 713 | BAUD128000 128000 115200 714 | BAUD256000 256000 115200 715 | \endverbatim 716 | */ 717 | void Win_QextSerialPort::setBaudRate(BaudRateType baudRate) { 718 | LOCK_MUTEX(); 719 | if (Settings.BaudRate!=baudRate) { 720 | switch (baudRate) { 721 | case BAUD50: 722 | case BAUD75: 723 | case BAUD134: 724 | case BAUD150: 725 | case BAUD200: 726 | Settings.BaudRate=BAUD110; 727 | break; 728 | 729 | case BAUD1800: 730 | Settings.BaudRate=BAUD1200; 731 | break; 732 | 733 | case BAUD76800: 734 | Settings.BaudRate=BAUD57600; 735 | break; 736 | 737 | default: 738 | Settings.BaudRate=baudRate; 739 | break; 740 | } 741 | } 742 | if (isOpen()) { 743 | switch (baudRate) { 744 | 745 | /*50 baud*/ 746 | case BAUD50: 747 | TTY_WARNING("Win_QextSerialPort: Windows does not support 50 baud operation. Switching to 110 baud."); 748 | Win_CommConfig.dcb.BaudRate=CBR_110; 749 | break; 750 | 751 | /*75 baud*/ 752 | case BAUD75: 753 | TTY_WARNING("Win_QextSerialPort: Windows does not support 75 baud operation. Switching to 110 baud."); 754 | Win_CommConfig.dcb.BaudRate=CBR_110; 755 | break; 756 | 757 | /*110 baud*/ 758 | case BAUD110: 759 | Win_CommConfig.dcb.BaudRate=CBR_110; 760 | break; 761 | 762 | /*134.5 baud*/ 763 | case BAUD134: 764 | TTY_WARNING("Win_QextSerialPort: Windows does not support 134.5 baud operation. Switching to 110 baud."); 765 | Win_CommConfig.dcb.BaudRate=CBR_110; 766 | break; 767 | 768 | /*150 baud*/ 769 | case BAUD150: 770 | TTY_WARNING("Win_QextSerialPort: Windows does not support 150 baud operation. Switching to 110 baud."); 771 | Win_CommConfig.dcb.BaudRate=CBR_110; 772 | break; 773 | 774 | /*200 baud*/ 775 | case BAUD200: 776 | TTY_WARNING("Win_QextSerialPort: Windows does not support 200 baud operation. Switching to 110 baud."); 777 | Win_CommConfig.dcb.BaudRate=CBR_110; 778 | break; 779 | 780 | /*300 baud*/ 781 | case BAUD300: 782 | Win_CommConfig.dcb.BaudRate=CBR_300; 783 | break; 784 | 785 | /*600 baud*/ 786 | case BAUD600: 787 | Win_CommConfig.dcb.BaudRate=CBR_600; 788 | break; 789 | 790 | /*1200 baud*/ 791 | case BAUD1200: 792 | Win_CommConfig.dcb.BaudRate=CBR_1200; 793 | break; 794 | 795 | /*1800 baud*/ 796 | case BAUD1800: 797 | TTY_WARNING("Win_QextSerialPort: Windows does not support 1800 baud operation. Switching to 1200 baud."); 798 | Win_CommConfig.dcb.BaudRate=CBR_1200; 799 | break; 800 | 801 | /*2400 baud*/ 802 | case BAUD2400: 803 | Win_CommConfig.dcb.BaudRate=CBR_2400; 804 | break; 805 | 806 | /*4800 baud*/ 807 | case BAUD4800: 808 | Win_CommConfig.dcb.BaudRate=CBR_4800; 809 | break; 810 | 811 | /*9600 baud*/ 812 | case BAUD9600: 813 | Win_CommConfig.dcb.BaudRate=CBR_9600; 814 | break; 815 | 816 | /*14400 baud*/ 817 | case BAUD14400: 818 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 14400 baud operation."); 819 | Win_CommConfig.dcb.BaudRate=CBR_14400; 820 | break; 821 | 822 | /*19200 baud*/ 823 | case BAUD19200: 824 | Win_CommConfig.dcb.BaudRate=CBR_19200; 825 | break; 826 | 827 | /*38400 baud*/ 828 | case BAUD38400: 829 | Win_CommConfig.dcb.BaudRate=CBR_38400; 830 | break; 831 | 832 | /*56000 baud*/ 833 | case BAUD56000: 834 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 56000 baud operation."); 835 | Win_CommConfig.dcb.BaudRate=CBR_56000; 836 | break; 837 | 838 | /*57600 baud*/ 839 | case BAUD57600: 840 | Win_CommConfig.dcb.BaudRate=CBR_57600; 841 | break; 842 | 843 | /*76800 baud*/ 844 | case BAUD76800: 845 | TTY_WARNING("Win_QextSerialPort: Windows does not support 76800 baud operation. Switching to 57600 baud."); 846 | Win_CommConfig.dcb.BaudRate=CBR_57600; 847 | break; 848 | 849 | /*115200 baud*/ 850 | case BAUD115200: 851 | Win_CommConfig.dcb.BaudRate=CBR_115200; 852 | break; 853 | 854 | /*128000 baud*/ 855 | case BAUD128000: 856 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 128000 baud operation."); 857 | Win_CommConfig.dcb.BaudRate=CBR_128000; 858 | break; 859 | 860 | /*256000 baud*/ 861 | case BAUD256000: 862 | TTY_PORTABILITY_WARNING("Win_QextSerialPort Portability Warning: POSIX does not support 256000 baud operation."); 863 | Win_CommConfig.dcb.BaudRate=CBR_256000; 864 | break; 865 | } 866 | SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG)); 867 | } 868 | UNLOCK_MUTEX(); 869 | } 870 | 871 | /*! 872 | \fn void Win_QextSerialPort::setDtr(bool set) 873 | Sets DTR line to the requested state (high by default). This function will have no effect if 874 | the port associated with the class is not currently open. 875 | */ 876 | void Win_QextSerialPort::setDtr(bool set) { 877 | LOCK_MUTEX(); 878 | if (isOpen()) { 879 | if (set) { 880 | EscapeCommFunction(Win_Handle, SETDTR); 881 | } 882 | else { 883 | EscapeCommFunction(Win_Handle, CLRDTR); 884 | } 885 | } 886 | UNLOCK_MUTEX(); 887 | } 888 | 889 | /*! 890 | \fn void Win_QextSerialPort::setRts(bool set) 891 | Sets RTS line to the requested state (high by default). This function will have no effect if 892 | the port associated with the class is not currently open. 893 | */ 894 | void Win_QextSerialPort::setRts(bool set) { 895 | LOCK_MUTEX(); 896 | if (isOpen()) { 897 | if (set) { 898 | EscapeCommFunction(Win_Handle, SETRTS); 899 | } 900 | else { 901 | EscapeCommFunction(Win_Handle, CLRRTS); 902 | } 903 | } 904 | UNLOCK_MUTEX(); 905 | } 906 | 907 | /*! 908 | \fn ulong Win_QextSerialPort::lineStatus(void) 909 | returns the line status as stored by the port function. This function will retrieve the states 910 | of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines 911 | can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned 912 | long with specific bits indicating which lines are high. The following constants should be used 913 | to examine the states of individual lines: 914 | 915 | \verbatim 916 | Mask Line 917 | ------ ---- 918 | LS_CTS CTS 919 | LS_DSR DSR 920 | LS_DCD DCD 921 | LS_RI RI 922 | \endverbatim 923 | 924 | This function will return 0 if the port associated with the class is not currently open. 925 | */ 926 | ulong Win_QextSerialPort::lineStatus(void) { 927 | unsigned long Status=0, Temp=0; 928 | LOCK_MUTEX(); 929 | if (isOpen()) { 930 | GetCommModemStatus(Win_Handle, &Temp); 931 | if (Temp&MS_CTS_ON) { 932 | Status|=LS_CTS; 933 | } 934 | if (Temp&MS_DSR_ON) { 935 | Status|=LS_DSR; 936 | } 937 | if (Temp&MS_RING_ON) { 938 | Status|=LS_RI; 939 | } 940 | if (Temp&MS_RLSD_ON) { 941 | Status|=LS_DCD; 942 | } 943 | } 944 | UNLOCK_MUTEX(); 945 | return Status; 946 | } 947 | 948 | bool Win_QextSerialPort::waitForReadyRead(int msecs) 949 | { 950 | //@todo implement 951 | return false; 952 | } 953 | 954 | qint64 Win_QextSerialPort::bytesToWrite() const 955 | { 956 | return _bytesToWrite; 957 | } 958 | 959 | void Win_QextSerialPort::monitorCommEvent() 960 | { 961 | DWORD eventMask = 0; 962 | 963 | ResetEvent(overlap.hEvent); 964 | if (!WaitCommEvent(Win_Handle, & eventMask, & overlap)) 965 | if (GetLastError() != ERROR_IO_PENDING) 966 | qCritical("WaitCommEvent error %ld\n", GetLastError()); 967 | 968 | if (WaitForSingleObject(overlap.hEvent, INFINITE) == WAIT_OBJECT_0) { 969 | //overlap event occured 970 | DWORD undefined; 971 | if (!GetOverlappedResult(Win_Handle, & overlap, & undefined, false)) { 972 | qWarning("Comm event overlapped error %ld", GetLastError()); 973 | return; 974 | } 975 | if (eventMask & EV_RXCHAR) { 976 | if (sender() != this) 977 | emit readyRead(); 978 | } 979 | if (eventMask & EV_TXEMPTY) { 980 | DWORD numBytes; 981 | GetOverlappedResult(Win_Handle, & overlapWrite, & numBytes, true); 982 | bytesToWriteLock->lockForWrite(); 983 | if (sender() != this) 984 | emit bytesWritten(bytesToWrite()); 985 | _bytesToWrite = 0; 986 | bytesToWriteLock->unlock(); 987 | } 988 | if (eventMask & EV_DSR) 989 | if (lineStatus() & LS_DSR) 990 | emit dsrChanged(true); 991 | else 992 | emit dsrChanged(false); 993 | } 994 | } 995 | 996 | void Win_QextSerialPort::terminateCommWait() 997 | { 998 | SetCommMask(Win_Handle, 0); 999 | } 1000 | 1001 | 1002 | /*! 1003 | \fn void Win_QextSerialPort::setTimeout(ulong millisec); 1004 | Sets the read and write timeouts for the port to millisec milliseconds. 1005 | Setting 0 for both sec and millisec indicates that timeouts are not used for read nor 1006 | write operations. Setting -1 indicates that read and write should return immediately. 1007 | 1008 | \note this function does nothing in event driven mode. 1009 | */ 1010 | void Win_QextSerialPort::setTimeout(long millisec) { 1011 | LOCK_MUTEX(); 1012 | Settings.Timeout_Millisec = millisec; 1013 | 1014 | if (millisec == -1) { 1015 | Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD; 1016 | Win_CommTimeouts.ReadTotalTimeoutConstant = 0; 1017 | } else { 1018 | Win_CommTimeouts.ReadIntervalTimeout = millisec; 1019 | Win_CommTimeouts.ReadTotalTimeoutConstant = millisec; 1020 | } 1021 | Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0; 1022 | Win_CommTimeouts.WriteTotalTimeoutMultiplier = millisec; 1023 | Win_CommTimeouts.WriteTotalTimeoutConstant = 0; 1024 | if (queryMode() != QextSerialBase::EventDriven) 1025 | SetCommTimeouts(Win_Handle, &Win_CommTimeouts); 1026 | 1027 | UNLOCK_MUTEX(); 1028 | } 1029 | 1030 | 1031 | Win_QextSerialThread::Win_QextSerialThread(Win_QextSerialPort * qesp): 1032 | QThread() 1033 | { 1034 | this->qesp = qesp; 1035 | terminate = false; 1036 | } 1037 | 1038 | void Win_QextSerialThread::stop() 1039 | { 1040 | terminate = true; 1041 | qesp->terminateCommWait(); 1042 | } 1043 | 1044 | void Win_QextSerialThread::run() 1045 | { 1046 | while (!terminate) 1047 | qesp->monitorCommEvent(); 1048 | terminate = false; 1049 | } 1050 | -------------------------------------------------------------------------------- /qcustomplot.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | ** ** 3 | ** QCustomPlot, an easy to use, modern plotting widget for Qt ** 4 | ** Copyright (C) 2011, 2012, 2013 Emanuel Eichhammer ** 5 | ** ** 6 | ** This program is free software: you can redistribute it and/or modify ** 7 | ** it under the terms of the GNU General Public License as published by ** 8 | ** the Free Software Foundation, either version 3 of the License, or ** 9 | ** (at your option) any later version. ** 10 | ** ** 11 | ** This program is distributed in the hope that it will be useful, ** 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 14 | ** GNU General Public License for more details. ** 15 | ** ** 16 | ** You should have received a copy of the GNU General Public License ** 17 | ** along with this program. If not, see http://www.gnu.org/licenses/. ** 18 | ** ** 19 | **************************************************************************** 20 | ** Author: Emanuel Eichhammer ** 21 | ** Website/Contact: http://www.qcustomplot.com/ ** 22 | ** Date: 01.08.13 ** 23 | ** Version: 1.0.0 ** 24 | ****************************************************************************/ 25 | 26 | #ifndef QCUSTOMPLOT_H 27 | #define QCUSTOMPLOT_H 28 | 29 | #ifdef QT_DISABLE_DEPRECATED_BEFORE 30 | # undef QT_DISABLE_DEPRECATED_BEFORE 31 | #endif 32 | #define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(0, 0, 0) 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) 54 | # include 55 | # include 56 | #else 57 | # include 58 | # include 59 | #endif 60 | 61 | class QCPPainter; 62 | class QCustomPlot; 63 | class QCPLayerable; 64 | class QCPLayoutElement; 65 | class QCPLayout; 66 | class QCPAxis; 67 | class QCPAxisRect; 68 | class QCPAbstractPlottable; 69 | class QCPGraph; 70 | class QCPAbstractItem; 71 | class QCPItemPosition; 72 | class QCPLayer; 73 | class QCPPlotTitle; 74 | class QCPLegend; 75 | class QCPAbstractLegendItem; 76 | class QCPAbstractItem; 77 | 78 | 79 | /*! \file */ 80 | 81 | #ifdef QT_DISABLE_DEPRECATED_BEFORE 82 | # undef QT_DISABLE_DEPRECATED_BEFORE 83 | #endif 84 | #define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(0, 0, 0) 85 | 86 | 87 | // decl definitions for shared library compilation/usage: 88 | #if defined(QCUSTOMPLOT_COMPILE_LIBRARY) 89 | # define QCP_LIB_DECL Q_DECL_EXPORT 90 | #elif defined(QCUSTOMPLOT_USE_LIBRARY) 91 | # define QCP_LIB_DECL Q_DECL_IMPORT 92 | #else 93 | # define QCP_LIB_DECL 94 | #endif 95 | 96 | /*! 97 | The QCP Namespace contains general enums and QFlags used throughout the QCustomPlot library 98 | */ 99 | namespace QCP 100 | { 101 | /*! 102 | Defines the sides of a rectangular entity to which margins can be applied. 103 | 104 | \see QCPLayoutElement::setAutoMargins, QCPAxisRect::setAutoMargins 105 | */ 106 | enum MarginSide { msLeft = 0x01 ///< 0x01 left margin 107 | ,msRight = 0x02 ///< 0x02 right margin 108 | ,msTop = 0x04 ///< 0x04 top margin 109 | ,msBottom = 0x08 ///< 0x08 bottom margin 110 | ,msAll = 0xFF ///< 0xFF all margins 111 | ,msNone = 0x00 ///< 0x00 no margin 112 | }; 113 | Q_DECLARE_FLAGS(MarginSides, MarginSide) 114 | 115 | /*! 116 | Defines what objects of a plot can be forcibly drawn antialiased/not antialiased. If an object is 117 | neither forcibly drawn antialiased nor forcibly drawn not antialiased, it is up to the respective 118 | element how it is drawn. Typically it provides a \a setAntialiased function for this. 119 | 120 | \c AntialiasedElements is a flag of or-combined elements of this enum type. 121 | 122 | \see QCustomPlot::setAntialiasedElements, QCustomPlot::setNotAntialiasedElements 123 | */ 124 | enum AntialiasedElement { aeAxes = 0x0001 ///< 0x0001 Axis base line and tick marks 125 | ,aeGrid = 0x0002 ///< 0x0002 Grid lines 126 | ,aeSubGrid = 0x0004 ///< 0x0004 Sub grid lines 127 | ,aeLegend = 0x0008 ///< 0x0008 Legend box 128 | ,aeLegendItems = 0x0010 ///< 0x0010 Legend items 129 | ,aePlottables = 0x0020 ///< 0x0020 Main lines of plottables (excluding error bars, see element \ref aeErrorBars) 130 | ,aeItems = 0x0040 ///< 0x0040 Main lines of items 131 | ,aeScatters = 0x0080 ///< 0x0080 Scatter symbols of plottables (excluding scatter symbols of type ssPixmap) 132 | ,aeErrorBars = 0x0100 ///< 0x0100 Error bars 133 | ,aeFills = 0x0200 ///< 0x0200 Borders of fills (e.g. under or between graphs) 134 | ,aeZeroLine = 0x0400 ///< 0x0400 Zero-lines, see \ref QCPGrid::setZeroLinePen 135 | ,aeAll = 0xFFFF ///< 0xFFFF All elements 136 | ,aeNone = 0x0000 ///< 0x0000 No elements 137 | }; 138 | Q_DECLARE_FLAGS(AntialiasedElements, AntialiasedElement) 139 | 140 | /*! 141 | Defines plotting hints that control various aspects of the quality and speed of plotting. 142 | 143 | \see QCustomPlot::setPlottingHints 144 | */ 145 | enum PlottingHint { phNone = 0x000 ///< 0x000 No hints are set 146 | ,phFastPolylines = 0x001 ///< 0x001 Graph/Curve lines are drawn with a faster method. This reduces the quality 147 | ///< especially of the line segment joins. (Only relevant for solid line pens.) 148 | ,phForceRepaint = 0x002 ///< 0x002 causes an immediate repaint() instead of a soft update() when QCustomPlot::replot() is called. This is set by default 149 | ///< on Windows-Systems to prevent the plot from freezing on fast consecutive replots (e.g. user drags ranges with mouse). 150 | ,phCacheLabels = 0x004 ///< 0x004 axis (tick) labels will be cached as pixmaps, increasing replot performance. 151 | }; 152 | Q_DECLARE_FLAGS(PlottingHints, PlottingHint) 153 | 154 | /*! 155 | Defines the mouse interactions possible with QCustomPlot. 156 | 157 | \c Interactions is a flag of or-combined elements of this enum type. 158 | 159 | \see QCustomPlot::setInteractions 160 | */ 161 | enum Interaction { iRangeDrag = 0x001 ///< 0x001 Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes) 162 | ,iRangeZoom = 0x002 ///< 0x002 Axis ranges are zoomable with the mouse wheel (see \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeZoomAxes) 163 | ,iMultiSelect = 0x004 ///< 0x004 The user can select multiple objects by holding the modifier set by \ref QCustomPlot::setMultiSelectModifier while clicking 164 | ,iSelectPlottables = 0x008 ///< 0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable) 165 | ,iSelectAxes = 0x010 ///< 0x010 Axes are selectable (or parts of them, see QCPAxis::setSelectableParts) 166 | ,iSelectLegend = 0x020 ///< 0x020 Legends are selectable (or their child items, see QCPLegend::setSelectableParts) 167 | ,iSelectItems = 0x040 ///< 0x040 Items are selectable (Rectangles, Arrows, Textitems, etc. see \ref QCPAbstractItem) 168 | ,iSelectOther = 0x080 ///< 0x080 All other objects are selectable (e.g. your own derived layerables, the plot title,...) 169 | }; 170 | Q_DECLARE_FLAGS(Interactions, Interaction) 171 | 172 | /*! \internal 173 | 174 | Returns whether the specified \a value is considered an invalid data value for plottables (i.e. 175 | is \e nan or \e +/-inf). This function is used to check data validity upon replots, when the 176 | compiler flag \c QCUSTOMPLOT_CHECK_DATA is set. 177 | */ 178 | inline bool isInvalidData(double value) 179 | { 180 | return (!qIsNaN(value) && !qIsInf(value)); 181 | } 182 | 183 | /*! \internal 184 | \overload 185 | 186 | Checks two arguments instead of one. 187 | */ 188 | inline bool isInvalidData(double value1, double value2) 189 | { 190 | return isInvalidData(value1) || isInvalidData(value2); 191 | } 192 | 193 | /*! \internal 194 | 195 | Sets the specified \a side of \a margins to \a value 196 | 197 | \see getMarginValue 198 | */ 199 | inline void setMarginValue(QMargins &margins, QCP::MarginSide side, int value) 200 | { 201 | switch (side) 202 | { 203 | case QCP::msLeft: margins.setLeft(value); break; 204 | case QCP::msRight: margins.setRight(value); break; 205 | case QCP::msTop: margins.setTop(value); break; 206 | case QCP::msBottom: margins.setBottom(value); break; 207 | case QCP::msAll: margins = QMargins(value, value, value, value); break; 208 | default: break; 209 | } 210 | } 211 | 212 | /*! \internal 213 | 214 | Returns the value of the specified \a side of \a margins. If \a side is \ref QCP::msNone or 215 | \ref QCP::msAll, returns 0. 216 | 217 | \see setMarginValue 218 | */ 219 | inline int getMarginValue(const QMargins &margins, QCP::MarginSide side) 220 | { 221 | switch (side) 222 | { 223 | case QCP::msLeft: return margins.left(); 224 | case QCP::msRight: return margins.right(); 225 | case QCP::msTop: return margins.top(); 226 | case QCP::msBottom: return margins.bottom(); 227 | default: break; 228 | } 229 | return 0; 230 | } 231 | 232 | } // end of namespace QCP 233 | 234 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::AntialiasedElements) 235 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::PlottingHints) 236 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::MarginSides) 237 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::Interactions) 238 | 239 | 240 | class QCP_LIB_DECL QCPScatterStyle 241 | { 242 | Q_GADGET 243 | public: 244 | /*! 245 | Defines the shape used for scatter points. 246 | 247 | On plottables/items that draw scatters, the sizes of these visualizations (with exception of 248 | \ref ssDot and \ref ssPixmap) can be controlled with the \ref setSize function. Scatters are 249 | drawn with the pen and brush specified with \ref setPen and \ref setBrush. 250 | */ 251 | Q_ENUMS(ScatterShape) 252 | enum ScatterShape { ssNone ///< no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines) 253 | ,ssDot ///< \enumimage{ssDot.png} a single pixel (use \ref ssDisc or \ref ssCircle if you want a round shape with a certain radius) 254 | ,ssCross ///< \enumimage{ssCross.png} a cross 255 | ,ssPlus ///< \enumimage{ssPlus.png} a plus 256 | ,ssCircle ///< \enumimage{ssCircle.png} a circle 257 | ,ssDisc ///< \enumimage{ssDisc.png} a circle which is filled with the pen (not the brush as with ssCircle) 258 | ,ssSquare ///< \enumimage{ssSquare.png} a square 259 | ,ssDiamond ///< \enumimage{ssDiamond.png} a diamond 260 | ,ssStar ///< \enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus 261 | ,ssTriangle ///< \enumimage{ssTriangle.png} an equilateral triangle, standing on baseline 262 | ,ssTriangleInverted ///< \enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner 263 | ,ssCrossSquare ///< \enumimage{ssCrossSquare.png} a square with a cross inside 264 | ,ssPlusSquare ///< \enumimage{ssPlusSquare.png} a square with a plus inside 265 | ,ssCrossCircle ///< \enumimage{ssCrossCircle.png} a circle with a cross inside 266 | ,ssPlusCircle ///< \enumimage{ssPlusCircle.png} a circle with a plus inside 267 | ,ssPeace ///< \enumimage{ssPeace.png} a circle, with one vertical and two downward diagonal lines 268 | ,ssPixmap ///< a custom pixmap specified by setScatterPixmap, centered on the data point coordinates 269 | ,ssCustom ///< custom painter operations are performed per scatter (As QPainterPath, see \ref setCustomPath) 270 | }; 271 | 272 | QCPScatterStyle(); 273 | QCPScatterStyle(ScatterShape shape, double size=6); 274 | QCPScatterStyle(ScatterShape shape, const QColor &color, double size); 275 | QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size); 276 | QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size); 277 | QCPScatterStyle(const QPixmap &pixmap); 278 | QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush=Qt::NoBrush, double size=6); 279 | 280 | // getters: 281 | double size() const { return mSize; } 282 | ScatterShape shape() const { return mShape; } 283 | QPen pen() const { return mPen; } 284 | QBrush brush() const { return mBrush; } 285 | QPixmap pixmap() const { return mPixmap; } 286 | QPainterPath customPath() const { return mCustomPath; } 287 | 288 | // setters: 289 | void setSize(double size); 290 | void setShape(ScatterShape shape); 291 | void setPen(const QPen &pen); 292 | void setBrush(const QBrush &brush); 293 | void setPixmap(const QPixmap &pixmap); 294 | void setCustomPath(const QPainterPath &customPath); 295 | 296 | // non-property methods: 297 | bool isNone() const { return mShape == ssNone; } 298 | bool isPenDefined() const { return mPenDefined; } 299 | void applyTo(QCPPainter *painter, const QPen &defaultPen) const; 300 | void drawShape(QCPPainter *painter, QPointF pos) const; 301 | void drawShape(QCPPainter *painter, double x, double y) const; 302 | 303 | protected: 304 | // property members: 305 | double mSize; 306 | ScatterShape mShape; 307 | QPen mPen; 308 | QBrush mBrush; 309 | QPixmap mPixmap; 310 | QPainterPath mCustomPath; 311 | 312 | // non-property members: 313 | bool mPenDefined; 314 | }; 315 | Q_DECLARE_TYPEINFO(QCPScatterStyle, Q_MOVABLE_TYPE); 316 | 317 | 318 | class QCP_LIB_DECL QCPPainter : public QPainter 319 | { 320 | Q_GADGET 321 | public: 322 | /*! 323 | Defines special modes the painter can operate in. They disable or enable certain subsets of features/fixes/workarounds, 324 | depending on whether they are wanted on the respective output device. 325 | */ 326 | enum PainterMode {pmDefault = 0x00 ///< 0x00 Default mode for painting on screen devices 327 | ,pmVectorized = 0x01 ///< 0x01 Mode for vectorized painting (e.g. PDF export). For example, this prevents some antialiasing fixes. 328 | ,pmNoCaching = 0x02 ///< 0x02 Mode for all sorts of exports (e.g. PNG, PDF,...). For example, this prevents using cached pixmap labels 329 | ,pmNonCosmetic = 0x04 ///< 0x04 Turns pen widths 0 to 1, i.e. disables cosmetic pens. (A cosmetic pen is always drawn with width 1 pixel in the vector image/pdf viewer, independent of zoom.) 330 | }; 331 | Q_FLAGS(PainterMode PainterModes) 332 | Q_DECLARE_FLAGS(PainterModes, PainterMode) 333 | 334 | QCPPainter(); 335 | QCPPainter(QPaintDevice *device); 336 | ~QCPPainter(); 337 | 338 | // getters: 339 | bool antialiasing() const { return testRenderHint(QPainter::Antialiasing); } 340 | PainterModes modes() const { return mModes; } 341 | 342 | // setters: 343 | void setAntialiasing(bool enabled); 344 | void setMode(PainterMode mode, bool enabled=true); 345 | void setModes(PainterModes modes); 346 | 347 | // methods hiding non-virtual base class functions (QPainter bug workarounds): 348 | bool begin(QPaintDevice *device); 349 | void setPen(const QPen &pen); 350 | void setPen(const QColor &color); 351 | void setPen(Qt::PenStyle penStyle); 352 | void drawLine(const QLineF &line); 353 | void drawLine(const QPointF &p1, const QPointF &p2) {drawLine(QLineF(p1, p2));} 354 | void save(); 355 | void restore(); 356 | 357 | // non-virtual methods: 358 | void makeNonCosmetic(); 359 | 360 | protected: 361 | // property members: 362 | PainterModes mModes; 363 | bool mIsAntialiasing; 364 | 365 | // non-property members: 366 | QStack mAntialiasingStack; 367 | }; 368 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPainter::PainterModes) 369 | 370 | 371 | class QCP_LIB_DECL QCPLayer : public QObject 372 | { 373 | Q_OBJECT 374 | /// \cond INCLUDE_QPROPERTIES 375 | Q_PROPERTY(QCustomPlot* parentPlot READ parentPlot) 376 | Q_PROPERTY(QString name READ name) 377 | Q_PROPERTY(int index READ index) 378 | Q_PROPERTY(QList children READ children) 379 | /// \endcond 380 | public: 381 | QCPLayer(QCustomPlot* parentPlot, const QString &layerName); 382 | ~QCPLayer(); 383 | 384 | // getters: 385 | QCustomPlot *parentPlot() const { return mParentPlot; } 386 | QString name() const { return mName; } 387 | int index() const { return mIndex; } 388 | QList children() const { return mChildren; } 389 | 390 | protected: 391 | // property members: 392 | QCustomPlot *mParentPlot; 393 | QString mName; 394 | int mIndex; 395 | QList mChildren; 396 | 397 | // non-virtual methods: 398 | void addChild(QCPLayerable *layerable, bool prepend); 399 | void removeChild(QCPLayerable *layerable); 400 | 401 | private: 402 | Q_DISABLE_COPY(QCPLayer) 403 | 404 | friend class QCustomPlot; 405 | friend class QCPLayerable; 406 | }; 407 | 408 | class QCP_LIB_DECL QCPLayerable : public QObject 409 | { 410 | Q_OBJECT 411 | /// \cond INCLUDE_QPROPERTIES 412 | Q_PROPERTY(bool visible READ visible WRITE setVisible) 413 | Q_PROPERTY(QCustomPlot* parentPlot READ parentPlot) 414 | Q_PROPERTY(QCPLayerable* parentLayerable READ parentLayerable) 415 | Q_PROPERTY(QCPLayer* layer READ layer WRITE setLayer) 416 | Q_PROPERTY(bool antialiased READ antialiased WRITE setAntialiased) 417 | /// \endcond 418 | public: 419 | QCPLayerable(QCustomPlot *plot, QString targetLayer="", QCPLayerable *parentLayerable=0); 420 | ~QCPLayerable(); 421 | 422 | // getters: 423 | bool visible() const { return mVisible; } 424 | QCustomPlot *parentPlot() const { return mParentPlot; } 425 | QCPLayerable *parentLayerable() const { return mParentLayerable.data(); } 426 | QCPLayer *layer() const { return mLayer; } 427 | bool antialiased() const { return mAntialiased; } 428 | 429 | // setters: 430 | void setVisible(bool on); 431 | bool setLayer(QCPLayer *layer); 432 | bool setLayer(const QString &layerName); 433 | void setAntialiased(bool enabled); 434 | 435 | // introduced virtual methods: 436 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 437 | 438 | // non-property methods: 439 | bool realVisibility() const; 440 | 441 | protected: 442 | // property members: 443 | bool mVisible; 444 | QCustomPlot *mParentPlot; 445 | QWeakPointer mParentLayerable; 446 | QCPLayer *mLayer; 447 | bool mAntialiased; 448 | 449 | // introduced virtual methods: 450 | virtual void parentPlotInitialized(QCustomPlot *parentPlot); 451 | virtual QCP::Interaction selectionCategory() const; 452 | virtual QRect clipRect() const; 453 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const = 0; 454 | virtual void draw(QCPPainter *painter) = 0; 455 | // events: 456 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 457 | virtual void deselectEvent(bool *selectionStateChanged); 458 | 459 | // non-property methods: 460 | void initializeParentPlot(QCustomPlot *parentPlot); 461 | void setParentLayerable(QCPLayerable* parentLayerable); 462 | bool moveToLayer(QCPLayer *layer, bool prepend); 463 | void applyAntialiasingHint(QCPPainter *painter, bool localAntialiased, QCP::AntialiasedElement overrideElement) const; 464 | 465 | private: 466 | Q_DISABLE_COPY(QCPLayerable) 467 | 468 | friend class QCustomPlot; 469 | friend class QCPAxisRect; 470 | }; 471 | 472 | 473 | class QCP_LIB_DECL QCPRange 474 | { 475 | public: 476 | double lower, upper; 477 | 478 | QCPRange(); 479 | QCPRange(double lower, double upper); 480 | 481 | double size() const; 482 | double center() const; 483 | void normalize(); 484 | QCPRange sanitizedForLogScale() const; 485 | QCPRange sanitizedForLinScale() const; 486 | bool contains(double value) const; 487 | 488 | static bool validRange(double lower, double upper); 489 | static bool validRange(const QCPRange &range); 490 | static const double minRange; //1e-280; 491 | static const double maxRange; //1e280; 492 | }; 493 | Q_DECLARE_TYPEINFO(QCPRange, Q_MOVABLE_TYPE); 494 | 495 | 496 | class QCP_LIB_DECL QCPMarginGroup : public QObject 497 | { 498 | Q_OBJECT 499 | public: 500 | QCPMarginGroup(QCustomPlot *parentPlot); 501 | ~QCPMarginGroup(); 502 | 503 | // non-virtual methods: 504 | QList elements(QCP::MarginSide side) const { return mChildren.value(side); } 505 | bool isEmpty() const; 506 | void clear(); 507 | 508 | protected: 509 | // non-property members: 510 | QCustomPlot *mParentPlot; 511 | QHash > mChildren; 512 | 513 | // non-virtual methods: 514 | int commonMargin(QCP::MarginSide side) const; 515 | void addChild(QCP::MarginSide side, QCPLayoutElement *element); 516 | void removeChild(QCP::MarginSide side, QCPLayoutElement *element); 517 | 518 | private: 519 | Q_DISABLE_COPY(QCPMarginGroup) 520 | 521 | friend class QCPLayoutElement; 522 | }; 523 | 524 | 525 | class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable 526 | { 527 | Q_OBJECT 528 | /// \cond INCLUDE_QPROPERTIES 529 | Q_PROPERTY(QCPLayout* layout READ layout) 530 | Q_PROPERTY(QRect rect READ rect) 531 | Q_PROPERTY(QRect outerRect READ outerRect WRITE setOuterRect) 532 | Q_PROPERTY(QMargins margins READ margins WRITE setMargins) 533 | Q_PROPERTY(QMargins minimumMargins READ minimumMargins WRITE setMinimumMargins) 534 | Q_PROPERTY(QSize minimumSize READ minimumSize WRITE setMinimumSize) 535 | Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize) 536 | /// \endcond 537 | public: 538 | explicit QCPLayoutElement(QCustomPlot *parentPlot=0); 539 | virtual ~QCPLayoutElement(); 540 | 541 | // getters: 542 | QCPLayout *layout() const { return mParentLayout; } 543 | QRect rect() const { return mRect; } 544 | QRect outerRect() const { return mOuterRect; } 545 | QMargins margins() const { return mMargins; } 546 | QMargins minimumMargins() const { return mMinimumMargins; } 547 | QCP::MarginSides autoMargins() const { return mAutoMargins; } 548 | QSize minimumSize() const { return mMinimumSize; } 549 | QSize maximumSize() const { return mMaximumSize; } 550 | QCPMarginGroup *marginGroup(QCP::MarginSide side) const { return mMarginGroups.value(side, (QCPMarginGroup*)0); } 551 | QHash marginGroups() const { return mMarginGroups; } 552 | 553 | // setters: 554 | void setOuterRect(const QRect &rect); 555 | void setMargins(const QMargins &margins); 556 | void setMinimumMargins(const QMargins &margins); 557 | void setAutoMargins(QCP::MarginSides sides); 558 | void setMinimumSize(const QSize &size); 559 | void setMinimumSize(int width, int height); 560 | void setMaximumSize(const QSize &size); 561 | void setMaximumSize(int width, int height); 562 | void setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group); 563 | 564 | // introduced virtual methods: 565 | virtual void update(); 566 | virtual QSize minimumSizeHint() const; 567 | virtual QSize maximumSizeHint() const; 568 | virtual QList elements(bool recursive) const; 569 | 570 | // reimplemented virtual methods: 571 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 572 | 573 | protected: 574 | // property members: 575 | QCPLayout *mParentLayout; 576 | QSize mMinimumSize, mMaximumSize; 577 | QRect mRect, mOuterRect; 578 | QMargins mMargins, mMinimumMargins; 579 | QCP::MarginSides mAutoMargins; 580 | QHash mMarginGroups; 581 | 582 | // introduced virtual methods: 583 | virtual int calculateAutoMargin(QCP::MarginSide side); 584 | // events: 585 | virtual void mousePressEvent(QMouseEvent *event) {Q_UNUSED(event)} 586 | virtual void mouseMoveEvent(QMouseEvent *event) {Q_UNUSED(event)} 587 | virtual void mouseReleaseEvent(QMouseEvent *event) {Q_UNUSED(event)} 588 | virtual void mouseDoubleClickEvent(QMouseEvent *event) {Q_UNUSED(event)} 589 | virtual void wheelEvent(QWheelEvent *event) {Q_UNUSED(event)} 590 | 591 | // reimplemented virtual methods: 592 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const { Q_UNUSED(painter) } 593 | virtual void draw(QCPPainter *painter) { Q_UNUSED(painter) } 594 | virtual void parentPlotInitialized(QCustomPlot *parentPlot); 595 | 596 | private: 597 | Q_DISABLE_COPY(QCPLayoutElement) 598 | 599 | friend class QCustomPlot; 600 | friend class QCPLayout; 601 | friend class QCPMarginGroup; 602 | }; 603 | 604 | 605 | class QCP_LIB_DECL QCPLayout : public QCPLayoutElement 606 | { 607 | Q_OBJECT 608 | public: 609 | explicit QCPLayout(); 610 | 611 | // reimplemented virtual methods: 612 | virtual void update(); 613 | virtual QList elements(bool recursive) const; 614 | 615 | // introduced virtual methods: 616 | virtual int elementCount() const = 0; 617 | virtual QCPLayoutElement* elementAt(int index) const = 0; 618 | virtual QCPLayoutElement* takeAt(int index) = 0; 619 | virtual bool take(QCPLayoutElement* element) = 0; 620 | virtual void simplify(); 621 | 622 | // non-virtual methods: 623 | bool removeAt(int index); 624 | bool remove(QCPLayoutElement* element); 625 | void clear(); 626 | 627 | protected: 628 | // introduced virtual methods: 629 | virtual void updateLayout(); 630 | 631 | // non-virtual methods: 632 | void sizeConstraintsChanged() const; 633 | void adoptElement(QCPLayoutElement *el); 634 | void releaseElement(QCPLayoutElement *el); 635 | QVector getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const; 636 | 637 | private: 638 | Q_DISABLE_COPY(QCPLayout) 639 | friend class QCPLayoutElement; 640 | }; 641 | 642 | 643 | class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout 644 | { 645 | Q_OBJECT 646 | /// \cond INCLUDE_QPROPERTIES 647 | Q_PROPERTY(int rowCount READ rowCount) 648 | Q_PROPERTY(int columnCount READ columnCount) 649 | Q_PROPERTY(QList columnStretchFactors READ columnStretchFactors WRITE setColumnStretchFactors) 650 | Q_PROPERTY(QList rowStretchFactors READ rowStretchFactors WRITE setRowStretchFactors) 651 | Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing) 652 | Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing) 653 | /// \endcond 654 | public: 655 | explicit QCPLayoutGrid(); 656 | virtual ~QCPLayoutGrid(); 657 | 658 | // getters: 659 | int rowCount() const; 660 | int columnCount() const; 661 | QList columnStretchFactors() const { return mColumnStretchFactors; } 662 | QList rowStretchFactors() const { return mRowStretchFactors; } 663 | int columnSpacing() const { return mColumnSpacing; } 664 | int rowSpacing() const { return mRowSpacing; } 665 | 666 | // setters: 667 | void setColumnStretchFactor(int column, double factor); 668 | void setColumnStretchFactors(const QList &factors); 669 | void setRowStretchFactor(int row, double factor); 670 | void setRowStretchFactors(const QList &factors); 671 | void setColumnSpacing(int pixels); 672 | void setRowSpacing(int pixels); 673 | 674 | // reimplemented virtual methods: 675 | virtual void updateLayout(); 676 | virtual int elementCount() const; 677 | virtual QCPLayoutElement* elementAt(int index) const; 678 | virtual QCPLayoutElement* takeAt(int index); 679 | virtual bool take(QCPLayoutElement* element); 680 | virtual QList elements(bool recursive) const; 681 | virtual void simplify(); 682 | virtual QSize minimumSizeHint() const; 683 | virtual QSize maximumSizeHint() const; 684 | 685 | // non-virtual methods: 686 | QCPLayoutElement *element(int row, int column) const; 687 | bool addElement(int row, int column, QCPLayoutElement *element); 688 | bool hasElement(int row, int column); 689 | void expandTo(int newRowCount, int newColumnCount); 690 | void insertRow(int newIndex); 691 | void insertColumn(int newIndex); 692 | 693 | protected: 694 | // property members: 695 | QList > mElements; 696 | QList mColumnStretchFactors; 697 | QList mRowStretchFactors; 698 | int mColumnSpacing, mRowSpacing; 699 | 700 | // non-virtual methods: 701 | void getMinimumRowColSizes(QVector *minColWidths, QVector *minRowHeights) const; 702 | void getMaximumRowColSizes(QVector *maxColWidths, QVector *maxRowHeights) const; 703 | 704 | private: 705 | Q_DISABLE_COPY(QCPLayoutGrid) 706 | }; 707 | 708 | 709 | class QCP_LIB_DECL QCPLayoutInset : public QCPLayout 710 | { 711 | Q_OBJECT 712 | public: 713 | /*! 714 | Defines how the placement and sizing is handled for a certain element in a QCPLayoutInset. 715 | */ 716 | enum InsetPlacement {ipFree ///< The element may be positioned/sized arbitrarily, see \ref setInsetRect 717 | ,ipBorderAligned ///< The element is aligned to one of the layout sides, see \ref setInsetAlignment 718 | }; 719 | 720 | explicit QCPLayoutInset(); 721 | virtual ~QCPLayoutInset(); 722 | 723 | // getters: 724 | InsetPlacement insetPlacement(int index) const; 725 | Qt::Alignment insetAlignment(int index) const; 726 | QRectF insetRect(int index) const; 727 | 728 | // setters: 729 | void setInsetPlacement(int index, InsetPlacement placement); 730 | void setInsetAlignment(int index, Qt::Alignment alignment); 731 | void setInsetRect(int index, const QRectF &rect); 732 | 733 | // reimplemented virtual methods: 734 | virtual void updateLayout(); 735 | virtual int elementCount() const; 736 | virtual QCPLayoutElement* elementAt(int index) const; 737 | virtual QCPLayoutElement* takeAt(int index); 738 | virtual bool take(QCPLayoutElement* element); 739 | virtual void simplify() {} 740 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 741 | 742 | // non-virtual methods: 743 | void addElement(QCPLayoutElement *element, Qt::Alignment alignment); 744 | void addElement(QCPLayoutElement *element, const QRectF &rect); 745 | 746 | protected: 747 | // property members: 748 | QList mElements; 749 | QList mInsetPlacement; 750 | QList mInsetAlignment; 751 | QList mInsetRect; 752 | 753 | private: 754 | Q_DISABLE_COPY(QCPLayoutInset) 755 | }; 756 | 757 | 758 | class QCP_LIB_DECL QCPLineEnding 759 | { 760 | Q_GADGET 761 | public: 762 | /*! 763 | Defines the type of ending decoration for line-like items, e.g. an arrow. 764 | 765 | \image html QCPLineEnding.png 766 | 767 | The width and length of these decorations can be controlled with the functions \ref setWidth 768 | and \ref setLength. Some decorations like \ref esDisc, \ref esSquare, \ref esDiamond and \ref esBar only 769 | support a width, the length property is ignored. 770 | 771 | \see QCPItemLine::setHead, QCPItemLine::setTail, QCPItemCurve::setHead, QCPItemCurve::setTail 772 | */ 773 | Q_ENUMS(EndingStyle) 774 | enum EndingStyle { esNone ///< No ending decoration 775 | ,esFlatArrow ///< A filled arrow head with a straight/flat back (a triangle) 776 | ,esSpikeArrow ///< A filled arrow head with an indented back 777 | ,esLineArrow ///< A non-filled arrow head with open back 778 | ,esDisc ///< A filled circle 779 | ,esSquare ///< A filled square 780 | ,esDiamond ///< A filled diamond (45° rotated square) 781 | ,esBar ///< A bar perpendicular to the line 782 | ,esHalfBar ///< A bar perpendicular to the line sticking out to one side 783 | ,esSkewedBar ///< A bar that is skewed (skew controllable via \ref setLength) 784 | }; 785 | 786 | QCPLineEnding(); 787 | QCPLineEnding(EndingStyle style, double width=8, double length=10, bool inverted=false); 788 | 789 | // getters: 790 | EndingStyle style() const { return mStyle; } 791 | double width() const { return mWidth; } 792 | double length() const { return mLength; } 793 | bool inverted() const { return mInverted; } 794 | 795 | // setters: 796 | void setStyle(EndingStyle style); 797 | void setWidth(double width); 798 | void setLength(double length); 799 | void setInverted(bool inverted); 800 | 801 | // non-property methods: 802 | double boundingDistance() const; 803 | double realLength() const; 804 | void draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const; 805 | void draw(QCPPainter *painter, const QVector2D &pos, double angle) const; 806 | 807 | protected: 808 | // property members: 809 | EndingStyle mStyle; 810 | double mWidth, mLength; 811 | bool mInverted; 812 | }; 813 | Q_DECLARE_TYPEINFO(QCPLineEnding, Q_MOVABLE_TYPE); 814 | 815 | 816 | class QCP_LIB_DECL QCPGrid :public QCPLayerable 817 | { 818 | Q_OBJECT 819 | /// \cond INCLUDE_QPROPERTIES 820 | Q_PROPERTY(bool subGridVisible READ subGridVisible WRITE setSubGridVisible) 821 | Q_PROPERTY(bool antialiasedSubGrid READ antialiasedSubGrid WRITE setAntialiasedSubGrid) 822 | Q_PROPERTY(bool antialiasedZeroLine READ antialiasedZeroLine WRITE setAntialiasedZeroLine) 823 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 824 | Q_PROPERTY(QPen subGridPen READ subGridPen WRITE setSubGridPen) 825 | Q_PROPERTY(QPen zeroLinePen READ zeroLinePen WRITE setZeroLinePen) 826 | /// \endcond 827 | public: 828 | QCPGrid(QCPAxis *parentAxis); 829 | 830 | // getters: 831 | bool subGridVisible() const { return mSubGridVisible; } 832 | bool antialiasedSubGrid() const { return mAntialiasedSubGrid; } 833 | bool antialiasedZeroLine() const { return mAntialiasedZeroLine; } 834 | QPen pen() const { return mPen; } 835 | QPen subGridPen() const { return mSubGridPen; } 836 | QPen zeroLinePen() const { return mZeroLinePen; } 837 | 838 | // setters: 839 | void setSubGridVisible(bool visible); 840 | void setAntialiasedSubGrid(bool enabled); 841 | void setAntialiasedZeroLine(bool enabled); 842 | void setPen(const QPen &pen); 843 | void setSubGridPen(const QPen &pen); 844 | void setZeroLinePen(const QPen &pen); 845 | 846 | protected: 847 | // property members: 848 | bool mSubGridVisible; 849 | bool mAntialiasedSubGrid, mAntialiasedZeroLine; 850 | QPen mPen, mSubGridPen, mZeroLinePen; 851 | // non-property members: 852 | QCPAxis *mParentAxis; 853 | 854 | // reimplemented virtual methods: 855 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 856 | virtual void draw(QCPPainter *painter); 857 | 858 | // non-virtual methods: 859 | void drawGridLines(QCPPainter *painter) const; 860 | void drawSubGridLines(QCPPainter *painter) const; 861 | 862 | friend class QCPAxis; 863 | }; 864 | 865 | 866 | class QCP_LIB_DECL QCPAxis : public QCPLayerable 867 | { 868 | Q_OBJECT 869 | /// \cond INCLUDE_QPROPERTIES 870 | Q_PROPERTY(AxisType axisType READ axisType) 871 | Q_PROPERTY(QCPAxisRect* axisRect READ axisRect) 872 | Q_PROPERTY(ScaleType scaleType READ scaleType WRITE setScaleType) 873 | Q_PROPERTY(double scaleLogBase READ scaleLogBase WRITE setScaleLogBase) 874 | Q_PROPERTY(QCPRange range READ range WRITE setRange) 875 | Q_PROPERTY(bool rangeReversed READ rangeReversed WRITE setRangeReversed) 876 | Q_PROPERTY(bool autoTicks READ autoTicks WRITE setAutoTicks) 877 | Q_PROPERTY(int autoTickCount READ autoTickCount WRITE setAutoTickCount) 878 | Q_PROPERTY(bool autoTickLabels READ autoTickLabels WRITE setAutoTickLabels) 879 | Q_PROPERTY(bool autoTickStep READ autoTickStep WRITE setAutoTickStep) 880 | Q_PROPERTY(bool autoSubTicks READ autoSubTicks WRITE setAutoSubTicks) 881 | Q_PROPERTY(bool ticks READ ticks WRITE setTicks) 882 | Q_PROPERTY(bool tickLabels READ tickLabels WRITE setTickLabels) 883 | Q_PROPERTY(int tickLabelPadding READ tickLabelPadding WRITE setTickLabelPadding) 884 | Q_PROPERTY(LabelType tickLabelType READ tickLabelType WRITE setTickLabelType) 885 | Q_PROPERTY(QFont tickLabelFont READ tickLabelFont WRITE setTickLabelFont) 886 | Q_PROPERTY(QColor tickLabelColor READ tickLabelColor WRITE setTickLabelColor) 887 | Q_PROPERTY(double tickLabelRotation READ tickLabelRotation WRITE setTickLabelRotation) 888 | Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat) 889 | Q_PROPERTY(QString numberFormat READ numberFormat WRITE setNumberFormat) 890 | Q_PROPERTY(int numberPrecision READ numberPrecision WRITE setNumberPrecision) 891 | Q_PROPERTY(double tickStep READ tickStep WRITE setTickStep) 892 | Q_PROPERTY(QVector tickVector READ tickVector WRITE setTickVector) 893 | Q_PROPERTY(QVector tickVectorLabels READ tickVectorLabels WRITE setTickVectorLabels) 894 | Q_PROPERTY(int tickLengthIn READ tickLengthIn WRITE setTickLengthIn) 895 | Q_PROPERTY(int tickLengthOut READ tickLengthOut WRITE setTickLengthOut) 896 | Q_PROPERTY(int subTickCount READ subTickCount WRITE setSubTickCount) 897 | Q_PROPERTY(int subTickLengthIn READ subTickLengthIn WRITE setSubTickLengthIn) 898 | Q_PROPERTY(int subTickLengthOut READ subTickLengthOut WRITE setSubTickLengthOut) 899 | Q_PROPERTY(QPen basePen READ basePen WRITE setBasePen) 900 | Q_PROPERTY(QPen tickPen READ tickPen WRITE setTickPen) 901 | Q_PROPERTY(QPen subTickPen READ subTickPen WRITE setSubTickPen) 902 | Q_PROPERTY(QFont labelFont READ labelFont WRITE setLabelFont) 903 | Q_PROPERTY(QColor labelColor READ labelColor WRITE setLabelColor) 904 | Q_PROPERTY(QString label READ label WRITE setLabel) 905 | Q_PROPERTY(int labelPadding READ labelPadding WRITE setLabelPadding) 906 | Q_PROPERTY(int padding READ padding WRITE setPadding) 907 | Q_PROPERTY(int offset READ offset WRITE setOffset) 908 | Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE setSelectedParts) 909 | Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE setSelectableParts) 910 | Q_PROPERTY(QFont selectedTickLabelFont READ selectedTickLabelFont WRITE setSelectedTickLabelFont) 911 | Q_PROPERTY(QFont selectedLabelFont READ selectedLabelFont WRITE setSelectedLabelFont) 912 | Q_PROPERTY(QColor selectedTickLabelColor READ selectedTickLabelColor WRITE setSelectedTickLabelColor) 913 | Q_PROPERTY(QColor selectedLabelColor READ selectedLabelColor WRITE setSelectedLabelColor) 914 | Q_PROPERTY(QPen selectedBasePen READ selectedBasePen WRITE setSelectedBasePen) 915 | Q_PROPERTY(QPen selectedTickPen READ selectedTickPen WRITE setSelectedTickPen) 916 | Q_PROPERTY(QPen selectedSubTickPen READ selectedSubTickPen WRITE setSelectedSubTickPen) 917 | Q_PROPERTY(QCPLineEnding lowerEnding READ lowerEnding WRITE setLowerEnding) 918 | Q_PROPERTY(QCPLineEnding upperEnding READ upperEnding WRITE setUpperEnding) 919 | Q_PROPERTY(QCPGrid* grid READ grid) 920 | /// \endcond 921 | public: 922 | /*! 923 | Defines at which side of the axis rect the axis will appear. This also affects how the tick 924 | marks are drawn, on which side the labels are placed etc. 925 | */ 926 | enum AxisType { atLeft = 0x01 ///< 0x01 Axis is vertical and on the left side of the axis rect 927 | ,atRight = 0x02 ///< 0x02 Axis is vertical and on the right side of the axis rect 928 | ,atTop = 0x04 ///< 0x04 Axis is horizontal and on the top side of the axis rect 929 | ,atBottom = 0x08 ///< 0x08 Axis is horizontal and on the bottom side of the axis rect 930 | }; 931 | Q_FLAGS(AxisType AxisTypes) 932 | Q_DECLARE_FLAGS(AxisTypes, AxisType) 933 | /*! 934 | When automatic tick label generation is enabled (\ref setAutoTickLabels), defines how the 935 | coordinate of the tick is interpreted, i.e. translated into a string. 936 | 937 | \see setTickLabelType 938 | */ 939 | enum LabelType { ltNumber ///< Tick coordinate is regarded as normal number and will be displayed as such. (see \ref setNumberFormat) 940 | ,ltDateTime ///< Tick coordinate is regarded as a date/time (seconds since 1970-01-01T00:00:00 UTC) and will be displayed and formatted as such. (for details, see \ref setDateTimeFormat) 941 | }; 942 | Q_ENUMS(LabelType) 943 | /*! 944 | Defines the scale of an axis. 945 | \see setScaleType 946 | */ 947 | enum ScaleType { stLinear ///< Linear scaling 948 | ,stLogarithmic ///< Logarithmic scaling with correspondingly transformed plots and (major) tick marks at every base power (see \ref setScaleLogBase). 949 | }; 950 | Q_ENUMS(ScaleType) 951 | /*! 952 | Defines the selectable parts of an axis. 953 | \see setSelectableParts, setSelectedParts 954 | */ 955 | enum SelectablePart { spNone = 0 ///< None of the selectable parts 956 | ,spAxis = 0x001 ///< The axis backbone and tick marks 957 | ,spTickLabels = 0x002 ///< Tick labels (numbers) of this axis (as a whole, not individually) 958 | ,spAxisLabel = 0x004 ///< The axis label 959 | }; 960 | Q_FLAGS(SelectablePart SelectableParts) 961 | Q_DECLARE_FLAGS(SelectableParts, SelectablePart) 962 | 963 | explicit QCPAxis(QCPAxisRect *parent, AxisType type); 964 | 965 | // getters: 966 | AxisType axisType() const { return mAxisType; } 967 | QCPAxisRect *axisRect() const { return mAxisRect; } 968 | ScaleType scaleType() const { return mScaleType; } 969 | double scaleLogBase() const { return mScaleLogBase; } 970 | const QCPRange range() const { return mRange; } 971 | bool rangeReversed() const { return mRangeReversed; } 972 | bool autoTicks() const { return mAutoTicks; } 973 | int autoTickCount() const { return mAutoTickCount; } 974 | bool autoTickLabels() const { return mAutoTickLabels; } 975 | bool autoTickStep() const { return mAutoTickStep; } 976 | bool autoSubTicks() const { return mAutoSubTicks; } 977 | bool ticks() const { return mTicks; } 978 | bool tickLabels() const { return mTickLabels; } 979 | int tickLabelPadding() const { return mTickLabelPadding; } 980 | LabelType tickLabelType() const { return mTickLabelType; } 981 | QFont tickLabelFont() const { return mTickLabelFont; } 982 | QColor tickLabelColor() const { return mTickLabelColor; } 983 | double tickLabelRotation() const { return mTickLabelRotation; } 984 | QString dateTimeFormat() const { return mDateTimeFormat; } 985 | QString numberFormat() const; 986 | int numberPrecision() const { return mNumberPrecision; } 987 | double tickStep() const { return mTickStep; } 988 | QVector tickVector() const { return mTickVector; } 989 | QVector tickVectorLabels() const { return mTickVectorLabels; } 990 | int tickLengthIn() const { return mTickLengthIn; } 991 | int tickLengthOut() const { return mTickLengthOut; } 992 | int subTickCount() const { return mSubTickCount; } 993 | int subTickLengthIn() const { return mSubTickLengthIn; } 994 | int subTickLengthOut() const { return mSubTickLengthOut; } 995 | QPen basePen() const { return mBasePen; } 996 | QPen tickPen() const { return mTickPen; } 997 | QPen subTickPen() const { return mSubTickPen; } 998 | QFont labelFont() const { return mLabelFont; } 999 | QColor labelColor() const { return mLabelColor; } 1000 | QString label() const { return mLabel; } 1001 | int labelPadding() const { return mLabelPadding; } 1002 | int padding() const { return mPadding; } 1003 | int offset() const { return mOffset; } 1004 | SelectableParts selectedParts() const { return mSelectedParts; } 1005 | SelectableParts selectableParts() const { return mSelectableParts; } 1006 | QFont selectedTickLabelFont() const { return mSelectedTickLabelFont; } 1007 | QFont selectedLabelFont() const { return mSelectedLabelFont; } 1008 | QColor selectedTickLabelColor() const { return mSelectedTickLabelColor; } 1009 | QColor selectedLabelColor() const { return mSelectedLabelColor; } 1010 | QPen selectedBasePen() const { return mSelectedBasePen; } 1011 | QPen selectedTickPen() const { return mSelectedTickPen; } 1012 | QPen selectedSubTickPen() const { return mSelectedSubTickPen; } 1013 | QCPLineEnding lowerEnding() const { return mLowerEnding; } 1014 | QCPLineEnding upperEnding() const { return mUpperEnding; } 1015 | QCPGrid *grid() const { return mGrid; } 1016 | 1017 | // setters: 1018 | void setScaleType(ScaleType type); 1019 | void setScaleLogBase(double base); 1020 | Q_SLOT void setRange(const QCPRange &range); 1021 | void setRange(double lower, double upper); 1022 | void setRange(double position, double size, Qt::AlignmentFlag alignment); 1023 | void setRangeLower(double lower); 1024 | void setRangeUpper(double upper); 1025 | void setRangeReversed(bool reversed); 1026 | void setAutoTicks(bool on); 1027 | void setAutoTickCount(int approximateCount); 1028 | void setAutoTickLabels(bool on); 1029 | void setAutoTickStep(bool on); 1030 | void setAutoSubTicks(bool on); 1031 | void setTicks(bool show); 1032 | void setTickLabels(bool show); 1033 | void setTickLabelPadding(int padding); 1034 | void setTickLabelType(LabelType type); 1035 | void setTickLabelFont(const QFont &font); 1036 | void setTickLabelColor(const QColor &color); 1037 | void setTickLabelRotation(double degrees); 1038 | void setDateTimeFormat(const QString &format); 1039 | void setNumberFormat(const QString &formatCode); 1040 | void setNumberPrecision(int precision); 1041 | void setTickStep(double step); 1042 | void setTickVector(const QVector &vec); 1043 | void setTickVectorLabels(const QVector &vec); 1044 | void setTickLength(int inside, int outside=0); 1045 | void setTickLengthIn(int inside); 1046 | void setTickLengthOut(int outside); 1047 | void setSubTickCount(int count); 1048 | void setSubTickLength(int inside, int outside=0); 1049 | void setSubTickLengthIn(int inside); 1050 | void setSubTickLengthOut(int outside); 1051 | void setBasePen(const QPen &pen); 1052 | void setTickPen(const QPen &pen); 1053 | void setSubTickPen(const QPen &pen); 1054 | void setLabelFont(const QFont &font); 1055 | void setLabelColor(const QColor &color); 1056 | void setLabel(const QString &str); 1057 | void setLabelPadding(int padding); 1058 | void setPadding(int padding); 1059 | void setOffset(int offset); 1060 | void setSelectedTickLabelFont(const QFont &font); 1061 | void setSelectedLabelFont(const QFont &font); 1062 | void setSelectedTickLabelColor(const QColor &color); 1063 | void setSelectedLabelColor(const QColor &color); 1064 | void setSelectedBasePen(const QPen &pen); 1065 | void setSelectedTickPen(const QPen &pen); 1066 | void setSelectedSubTickPen(const QPen &pen); 1067 | Q_SLOT void setSelectableParts(const QCPAxis::SelectableParts &selectableParts); 1068 | Q_SLOT void setSelectedParts(const QCPAxis::SelectableParts &selectedParts); 1069 | void setLowerEnding(const QCPLineEnding &ending); 1070 | void setUpperEnding(const QCPLineEnding &ending); 1071 | 1072 | // reimplemented virtual methods: 1073 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 1074 | 1075 | // non-virtual methods: 1076 | Qt::Orientation orientation() const { return mOrientation; } 1077 | void moveRange(double diff); 1078 | void scaleRange(double factor, double center); 1079 | void setScaleRatio(const QCPAxis *otherAxis, double ratio=1.0); 1080 | double pixelToCoord(double value) const; 1081 | double coordToPixel(double value) const; 1082 | SelectablePart getPartAt(const QPointF &pos) const; 1083 | QList plottables() const; 1084 | QList graphs() const; 1085 | QList items() const; 1086 | 1087 | static AxisType marginSideToAxisType(QCP::MarginSide side); 1088 | 1089 | signals: 1090 | void ticksRequest(); 1091 | void rangeChanged(const QCPRange &newRange); 1092 | void selectionChanged(const QCPAxis::SelectableParts &parts); 1093 | 1094 | protected: 1095 | struct CachedLabel 1096 | { 1097 | QPointF offset; 1098 | QPixmap pixmap; 1099 | }; 1100 | struct TickLabelData 1101 | { 1102 | QString basePart, expPart; 1103 | QRect baseBounds, expBounds, totalBounds, rotatedTotalBounds; 1104 | QFont baseFont, expFont; 1105 | }; 1106 | 1107 | // property members: 1108 | // axis base: 1109 | AxisType mAxisType; 1110 | QCPAxisRect *mAxisRect; 1111 | int mOffset, mPadding; 1112 | Qt::Orientation mOrientation; 1113 | SelectableParts mSelectableParts, mSelectedParts; 1114 | QPen mBasePen, mSelectedBasePen; 1115 | QCPLineEnding mLowerEnding, mUpperEnding; 1116 | // axis label: 1117 | int mLabelPadding; 1118 | QString mLabel; 1119 | QFont mLabelFont, mSelectedLabelFont; 1120 | QColor mLabelColor, mSelectedLabelColor; 1121 | // tick labels: 1122 | int mTickLabelPadding; 1123 | bool mTickLabels, mAutoTickLabels; 1124 | double mTickLabelRotation; 1125 | LabelType mTickLabelType; 1126 | QFont mTickLabelFont, mSelectedTickLabelFont; 1127 | QColor mTickLabelColor, mSelectedTickLabelColor; 1128 | QString mDateTimeFormat; 1129 | int mNumberPrecision; 1130 | char mNumberFormatChar; 1131 | bool mNumberBeautifulPowers; 1132 | bool mNumberMultiplyCross; 1133 | // ticks and subticks: 1134 | bool mTicks; 1135 | double mTickStep; 1136 | int mSubTickCount, mAutoTickCount; 1137 | bool mAutoTicks, mAutoTickStep, mAutoSubTicks; 1138 | int mTickLengthIn, mTickLengthOut, mSubTickLengthIn, mSubTickLengthOut; 1139 | QPen mTickPen, mSelectedTickPen; 1140 | QPen mSubTickPen, mSelectedSubTickPen; 1141 | // scale and range: 1142 | QCPRange mRange; 1143 | bool mRangeReversed; 1144 | ScaleType mScaleType; 1145 | double mScaleLogBase, mScaleLogBaseLogInv; 1146 | 1147 | // non-property members: 1148 | QCPGrid *mGrid; 1149 | QCache mLabelCache; 1150 | int mLowestVisibleTick, mHighestVisibleTick; 1151 | QChar mExponentialChar, mPositiveSignChar; 1152 | QVector mTickVector; 1153 | QVector mTickVectorLabels; 1154 | QVector mSubTickVector; 1155 | QRect mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox; 1156 | bool mCachedMarginValid; 1157 | int mCachedMargin; 1158 | 1159 | // introduced virtual methods: 1160 | virtual void setupTickVectors(); 1161 | virtual void generateAutoTicks(); 1162 | virtual int calculateAutoSubTickCount(double tickStep) const; 1163 | virtual int calculateMargin(); 1164 | // tick label drawing/caching: 1165 | virtual void placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize); 1166 | virtual void drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const; 1167 | virtual TickLabelData getTickLabelData(const QFont &font, const QString &text) const; 1168 | virtual QPointF getTickLabelDrawOffset(const TickLabelData &labelData) const; 1169 | virtual void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const; 1170 | 1171 | // reimplemented virtual methods: 1172 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 1173 | virtual void draw(QCPPainter *painter); 1174 | virtual QCP::Interaction selectionCategory() const; 1175 | // events: 1176 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 1177 | virtual void deselectEvent(bool *selectionStateChanged); 1178 | 1179 | // non-virtual methods: 1180 | void visibleTickBounds(int &lowIndex, int &highIndex) const; 1181 | double baseLog(double value) const; 1182 | double basePow(double value) const; 1183 | QPen getBasePen() const; 1184 | QPen getTickPen() const; 1185 | QPen getSubTickPen() const; 1186 | QFont getTickLabelFont() const; 1187 | QFont getLabelFont() const; 1188 | QColor getTickLabelColor() const; 1189 | QColor getLabelColor() const; 1190 | 1191 | private: 1192 | Q_DISABLE_COPY(QCPAxis) 1193 | 1194 | friend class QCustomPlot; 1195 | friend class QCPGrid; 1196 | friend class QCPAxisRect; 1197 | }; 1198 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::SelectableParts) 1199 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::AxisTypes) 1200 | Q_DECLARE_METATYPE(QCPAxis::SelectablePart) 1201 | 1202 | 1203 | class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable 1204 | { 1205 | Q_OBJECT 1206 | /// \cond INCLUDE_QPROPERTIES 1207 | Q_PROPERTY(QString name READ name WRITE setName) 1208 | Q_PROPERTY(bool antialiasedFill READ antialiasedFill WRITE setAntialiasedFill) 1209 | Q_PROPERTY(bool antialiasedScatters READ antialiasedScatters WRITE setAntialiasedScatters) 1210 | Q_PROPERTY(bool antialiasedErrorBars READ antialiasedErrorBars WRITE setAntialiasedErrorBars) 1211 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 1212 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 1213 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 1214 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 1215 | Q_PROPERTY(QCPAxis* keyAxis READ keyAxis WRITE setKeyAxis) 1216 | Q_PROPERTY(QCPAxis* valueAxis READ valueAxis WRITE setValueAxis) 1217 | Q_PROPERTY(bool selectable READ selectable WRITE setSelectable) 1218 | Q_PROPERTY(bool selected READ selected WRITE setSelected) 1219 | /// \endcond 1220 | public: 1221 | QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis); 1222 | 1223 | // getters: 1224 | QString name() const { return mName; } 1225 | bool antialiasedFill() const { return mAntialiasedFill; } 1226 | bool antialiasedScatters() const { return mAntialiasedScatters; } 1227 | bool antialiasedErrorBars() const { return mAntialiasedErrorBars; } 1228 | QPen pen() const { return mPen; } 1229 | QPen selectedPen() const { return mSelectedPen; } 1230 | QBrush brush() const { return mBrush; } 1231 | QBrush selectedBrush() const { return mSelectedBrush; } 1232 | QCPAxis *keyAxis() const { return mKeyAxis.data(); } 1233 | QCPAxis *valueAxis() const { return mValueAxis.data(); } 1234 | bool selectable() const { return mSelectable; } 1235 | bool selected() const { return mSelected; } 1236 | 1237 | // setters: 1238 | void setName(const QString &name); 1239 | void setAntialiasedFill(bool enabled); 1240 | void setAntialiasedScatters(bool enabled); 1241 | void setAntialiasedErrorBars(bool enabled); 1242 | void setPen(const QPen &pen); 1243 | void setSelectedPen(const QPen &pen); 1244 | void setBrush(const QBrush &brush); 1245 | void setSelectedBrush(const QBrush &brush); 1246 | void setKeyAxis(QCPAxis *axis); 1247 | void setValueAxis(QCPAxis *axis); 1248 | Q_SLOT void setSelectable(bool selectable); 1249 | Q_SLOT void setSelected(bool selected); 1250 | 1251 | // introduced virtual methods: 1252 | virtual void clearData() = 0; 1253 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const = 0; 1254 | virtual bool addToLegend(); 1255 | virtual bool removeFromLegend() const; 1256 | 1257 | // non-property methods: 1258 | void rescaleAxes(bool onlyEnlarge=false) const; 1259 | void rescaleKeyAxis(bool onlyEnlarge=false) const; 1260 | void rescaleValueAxis(bool onlyEnlarge=false) const; 1261 | 1262 | signals: 1263 | void selectionChanged(bool selected); 1264 | 1265 | protected: 1266 | /*! 1267 | Represents negative and positive sign domain for passing to \ref getKeyRange and \ref getValueRange. 1268 | */ 1269 | enum SignDomain { sdNegative ///< The negative sign domain, i.e. numbers smaller than zero 1270 | ,sdBoth ///< Both sign domains, including zero, i.e. all (rational) numbers 1271 | ,sdPositive ///< The positive sign domain, i.e. numbers greater than zero 1272 | }; 1273 | 1274 | // property members: 1275 | QString mName; 1276 | bool mAntialiasedFill, mAntialiasedScatters, mAntialiasedErrorBars; 1277 | QPen mPen, mSelectedPen; 1278 | QBrush mBrush, mSelectedBrush; 1279 | QWeakPointer mKeyAxis, mValueAxis; 1280 | bool mSelectable, mSelected; 1281 | 1282 | // reimplemented virtual methods: 1283 | virtual QRect clipRect() const; 1284 | virtual void draw(QCPPainter *painter) = 0; 1285 | virtual QCP::Interaction selectionCategory() const; 1286 | void applyDefaultAntialiasingHint(QCPPainter *painter) const; 1287 | // events: 1288 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 1289 | virtual void deselectEvent(bool *selectionStateChanged); 1290 | 1291 | // introduced virtual methods: 1292 | virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const = 0; 1293 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const = 0; 1294 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const = 0; 1295 | 1296 | // non-virtual methods: 1297 | void coordsToPixels(double key, double value, double &x, double &y) const; 1298 | const QPointF coordsToPixels(double key, double value) const; 1299 | void pixelsToCoords(double x, double y, double &key, double &value) const; 1300 | void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const; 1301 | QPen mainPen() const; 1302 | QBrush mainBrush() const; 1303 | void applyFillAntialiasingHint(QCPPainter *painter) const; 1304 | void applyScattersAntialiasingHint(QCPPainter *painter) const; 1305 | void applyErrorBarsAntialiasingHint(QCPPainter *painter) const; 1306 | double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const; 1307 | 1308 | private: 1309 | Q_DISABLE_COPY(QCPAbstractPlottable) 1310 | 1311 | friend class QCustomPlot; 1312 | friend class QCPPlottableLegendItem; 1313 | }; 1314 | 1315 | 1316 | class QCP_LIB_DECL QCPItemAnchor 1317 | { 1318 | public: 1319 | QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId=-1); 1320 | virtual ~QCPItemAnchor(); 1321 | 1322 | // getters: 1323 | QString name() const { return mName; } 1324 | virtual QPointF pixelPoint() const; 1325 | 1326 | protected: 1327 | // property members: 1328 | QString mName; 1329 | 1330 | // non-property members: 1331 | QCustomPlot *mParentPlot; 1332 | QCPAbstractItem *mParentItem; 1333 | int mAnchorId; 1334 | QSet mChildren; 1335 | 1336 | // introduced virtual methods: 1337 | virtual QCPItemPosition *toQCPItemPosition() { return 0; } 1338 | 1339 | // non-virtual methods: 1340 | void addChild(QCPItemPosition* pos); // called from pos when this anchor is set as parent 1341 | void removeChild(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted 1342 | 1343 | private: 1344 | Q_DISABLE_COPY(QCPItemAnchor) 1345 | 1346 | friend class QCPItemPosition; 1347 | }; 1348 | 1349 | 1350 | 1351 | class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor 1352 | { 1353 | public: 1354 | /*! 1355 | Defines the ways an item position can be specified. Thus it defines what the numbers passed to 1356 | \ref setCoords actually mean. 1357 | 1358 | \see setType 1359 | */ 1360 | enum PositionType { ptAbsolute ///< Static positioning in pixels, starting from the top left corner of the viewport/widget. 1361 | ,ptViewportRatio ///< Static positioning given by a fraction of the viewport size. 1362 | ,ptAxisRectRatio ///< Static positioning given by a fraction of the axis rect size (see \ref setAxisRect). 1363 | ,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes). 1364 | }; 1365 | 1366 | QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name); 1367 | virtual ~QCPItemPosition(); 1368 | 1369 | // getters: 1370 | PositionType type() const { return mPositionType; } 1371 | QCPItemAnchor *parentAnchor() const { return mParentAnchor; } 1372 | double key() const { return mKey; } 1373 | double value() const { return mValue; } 1374 | QPointF coords() const { return QPointF(mKey, mValue); } 1375 | QCPAxis *keyAxis() const { return mKeyAxis.data(); } 1376 | QCPAxis *valueAxis() const { return mValueAxis.data(); } 1377 | QCPAxisRect *axisRect() const { return mAxisRect.data(); } 1378 | virtual QPointF pixelPoint() const; 1379 | 1380 | // setters: 1381 | void setType(PositionType type); 1382 | bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); 1383 | void setCoords(double key, double value); 1384 | void setCoords(const QPointF &coords); 1385 | void setAxes(QCPAxis* keyAxis, QCPAxis* valueAxis); 1386 | void setAxisRect(QCPAxisRect *axisRect); 1387 | void setPixelPoint(const QPointF &pixelPoint); 1388 | 1389 | protected: 1390 | // property members: 1391 | PositionType mPositionType; 1392 | QWeakPointer mKeyAxis, mValueAxis; 1393 | QWeakPointer mAxisRect; 1394 | double mKey, mValue; 1395 | QCPItemAnchor *mParentAnchor; 1396 | 1397 | // reimplemented virtual methods: 1398 | virtual QCPItemPosition *toQCPItemPosition() { return this; } 1399 | 1400 | private: 1401 | Q_DISABLE_COPY(QCPItemPosition) 1402 | 1403 | }; 1404 | 1405 | 1406 | class QCP_LIB_DECL QCPAbstractItem : public QCPLayerable 1407 | { 1408 | Q_OBJECT 1409 | /// \cond INCLUDE_QPROPERTIES 1410 | Q_PROPERTY(bool clipToAxisRect READ clipToAxisRect WRITE setClipToAxisRect) 1411 | Q_PROPERTY(QCPAxisRect* clipAxisRect READ clipAxisRect WRITE setClipAxisRect) 1412 | Q_PROPERTY(bool selectable READ selectable WRITE setSelectable) 1413 | Q_PROPERTY(bool selected READ selected WRITE setSelected) 1414 | /// \endcond 1415 | public: 1416 | QCPAbstractItem(QCustomPlot *parentPlot); 1417 | virtual ~QCPAbstractItem(); 1418 | 1419 | // getters: 1420 | bool clipToAxisRect() const { return mClipToAxisRect; } 1421 | QCPAxisRect *clipAxisRect() const { return mClipAxisRect.data(); } 1422 | bool selectable() const { return mSelectable; } 1423 | bool selected() const { return mSelected; } 1424 | 1425 | // setters: 1426 | void setClipToAxisRect(bool clip); 1427 | void setClipAxisRect(QCPAxisRect *rect); 1428 | void setSelectable(bool selectable); 1429 | void setSelected(bool selected); 1430 | 1431 | // reimplemented virtual methods: 1432 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const = 0; 1433 | 1434 | // non-virtual methods: 1435 | QList positions() const { return mPositions; } 1436 | QList anchors() const { return mAnchors; } 1437 | QCPItemPosition *position(const QString &name) const; 1438 | QCPItemAnchor *anchor(const QString &name) const; 1439 | bool hasAnchor(const QString &name) const; 1440 | 1441 | signals: 1442 | void selectionChanged(bool selected); 1443 | 1444 | protected: 1445 | // property members: 1446 | bool mClipToAxisRect; 1447 | QWeakPointer mClipAxisRect; 1448 | QList mPositions; 1449 | QList mAnchors; 1450 | bool mSelectable, mSelected; 1451 | 1452 | // reimplemented virtual methods: 1453 | virtual QCP::Interaction selectionCategory() const; 1454 | virtual QRect clipRect() const; 1455 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 1456 | virtual void draw(QCPPainter *painter) = 0; 1457 | // events: 1458 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 1459 | virtual void deselectEvent(bool *selectionStateChanged); 1460 | 1461 | // introduced virtual methods: 1462 | virtual QPointF anchorPixelPoint(int anchorId) const; 1463 | 1464 | // non-virtual methods: 1465 | double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const; 1466 | double rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const; 1467 | QCPItemPosition *createPosition(const QString &name); 1468 | QCPItemAnchor *createAnchor(const QString &name, int anchorId); 1469 | 1470 | private: 1471 | Q_DISABLE_COPY(QCPAbstractItem) 1472 | 1473 | friend class QCustomPlot; 1474 | friend class QCPItemAnchor; 1475 | }; 1476 | 1477 | 1478 | class QCP_LIB_DECL QCustomPlot : public QWidget 1479 | { 1480 | Q_OBJECT 1481 | /// \cond INCLUDE_QPROPERTIES 1482 | Q_PROPERTY(QRect viewport READ viewport WRITE setViewport) 1483 | Q_PROPERTY(QPixmap background READ background WRITE setBackground) 1484 | Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) 1485 | Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) 1486 | Q_PROPERTY(QCPLayoutGrid* plotLayout READ plotLayout) 1487 | Q_PROPERTY(bool autoAddPlottableToLegend READ autoAddPlottableToLegend WRITE setAutoAddPlottableToLegend) 1488 | Q_PROPERTY(int selectionTolerance READ selectionTolerance WRITE setSelectionTolerance) 1489 | Q_PROPERTY(bool noAntialiasingOnDrag READ noAntialiasingOnDrag WRITE setNoAntialiasingOnDrag) 1490 | Q_PROPERTY(Qt::KeyboardModifier multiSelectModifier READ multiSelectModifier WRITE setMultiSelectModifier) 1491 | /// \endcond 1492 | public: 1493 | /*! 1494 | Defines how a layer should be inserted relative to an other layer. 1495 | 1496 | \see addLayer, moveLayer 1497 | */ 1498 | enum LayerInsertMode { limBelow ///< Layer is inserted below other layer 1499 | ,limAbove ///< Layer is inserted above other layer 1500 | }; 1501 | Q_ENUMS(LayerInsertMode) 1502 | 1503 | explicit QCustomPlot(QWidget *parent = 0); 1504 | virtual ~QCustomPlot(); 1505 | 1506 | // getters: 1507 | QRect viewport() const { return mViewport; } 1508 | QPixmap background() const { return mBackgroundPixmap; } 1509 | bool backgroundScaled() const { return mBackgroundScaled; } 1510 | Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } 1511 | QCPLayoutGrid *plotLayout() const { return mPlotLayout; } 1512 | QCP::AntialiasedElements antialiasedElements() const { return mAntialiasedElements; } 1513 | QCP::AntialiasedElements notAntialiasedElements() const { return mNotAntialiasedElements; } 1514 | bool autoAddPlottableToLegend() const { return mAutoAddPlottableToLegend; } 1515 | const QCP::Interactions interactions() const { return mInteractions; } 1516 | int selectionTolerance() const { return mSelectionTolerance; } 1517 | bool noAntialiasingOnDrag() const { return mNoAntialiasingOnDrag; } 1518 | QCP::PlottingHints plottingHints() const { return mPlottingHints; } 1519 | Qt::KeyboardModifier multiSelectModifier() const { return mMultiSelectModifier; } 1520 | 1521 | // setters: 1522 | void setViewport(const QRect &rect); 1523 | void setBackground(const QPixmap &pm); 1524 | void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); 1525 | void setBackground(const QBrush &brush); 1526 | void setBackgroundScaled(bool scaled); 1527 | void setBackgroundScaledMode(Qt::AspectRatioMode mode); 1528 | void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements); 1529 | void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true); 1530 | void setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements); 1531 | void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true); 1532 | void setAutoAddPlottableToLegend(bool on); 1533 | void setInteractions(const QCP::Interactions &interactions); 1534 | void setInteraction(const QCP::Interaction &interaction, bool enabled=true); 1535 | void setSelectionTolerance(int pixels); 1536 | void setNoAntialiasingOnDrag(bool enabled); 1537 | void setPlottingHints(const QCP::PlottingHints &hints); 1538 | void setPlottingHint(QCP::PlottingHint hint, bool enabled=true); 1539 | void setMultiSelectModifier(Qt::KeyboardModifier modifier); 1540 | 1541 | // non-property methods: 1542 | // plottable interface: 1543 | QCPAbstractPlottable *plottable(int index); 1544 | QCPAbstractPlottable *plottable(); 1545 | bool addPlottable(QCPAbstractPlottable *plottable); 1546 | bool removePlottable(QCPAbstractPlottable *plottable); 1547 | bool removePlottable(int index); 1548 | int clearPlottables(); 1549 | int plottableCount() const; 1550 | QList selectedPlottables() const; 1551 | QCPAbstractPlottable *plottableAt(const QPointF &pos, bool onlySelectable=false) const; 1552 | bool hasPlottable(QCPAbstractPlottable *plottable) const; 1553 | 1554 | // specialized interface for QCPGraph: 1555 | QCPGraph *graph(int index) const; 1556 | QCPGraph *graph() const; 1557 | QCPGraph *addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0); 1558 | bool removeGraph(QCPGraph *graph); 1559 | bool removeGraph(int index); 1560 | int clearGraphs(); 1561 | int graphCount() const; 1562 | QList selectedGraphs() const; 1563 | 1564 | // item interface: 1565 | QCPAbstractItem *item(int index) const; 1566 | QCPAbstractItem *item() const; 1567 | bool addItem(QCPAbstractItem* item); 1568 | bool removeItem(QCPAbstractItem *item); 1569 | bool removeItem(int index); 1570 | int clearItems(); 1571 | int itemCount() const; 1572 | QList selectedItems() const; 1573 | QCPAbstractItem *itemAt(const QPointF &pos, bool onlySelectable=false) const; 1574 | bool hasItem(QCPAbstractItem *item) const; 1575 | 1576 | // layer interface: 1577 | QCPLayer *layer(const QString &name) const; 1578 | QCPLayer *layer(int index) const; 1579 | QCPLayer *currentLayer() const; 1580 | bool setCurrentLayer(const QString &name); 1581 | bool setCurrentLayer(QCPLayer *layer); 1582 | int layerCount() const; 1583 | bool addLayer(const QString &name, QCPLayer *otherLayer=0, LayerInsertMode insertMode=limAbove); 1584 | bool removeLayer(QCPLayer *layer); 1585 | bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove); 1586 | 1587 | // axis rect/layout interface: 1588 | int axisRectCount() const; 1589 | QCPAxisRect* axisRect(int index=0) const; 1590 | QList axisRects() const; 1591 | QCPLayoutElement* layoutElementAt(const QPointF &pos) const; 1592 | Q_SLOT void rescaleAxes(bool onlyVisible=false); 1593 | 1594 | QList selectedAxes() const; 1595 | QList selectedLegends() const; 1596 | Q_SLOT void deselectAll(); 1597 | 1598 | bool savePdf(const QString &fileName, bool noCosmeticPen=false, int width=0, int height=0); 1599 | bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1); 1600 | bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1); 1601 | bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0); 1602 | bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1); 1603 | QPixmap toPixmap(int width=0, int height=0, double scale=1.0); 1604 | void toPainter(QCPPainter *painter, int width=0, int height=0); 1605 | Q_SLOT void replot(); 1606 | 1607 | QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; 1608 | QCPLegend *legend; 1609 | 1610 | signals: 1611 | void mouseDoubleClick(QMouseEvent *event); 1612 | void mousePress(QMouseEvent *event); 1613 | void mouseMove(QMouseEvent *event); 1614 | void mouseRelease(QMouseEvent *event); 1615 | void mouseWheel(QWheelEvent *event); 1616 | 1617 | void plottableClick(QCPAbstractPlottable *plottable, QMouseEvent *event); 1618 | void plottableDoubleClick(QCPAbstractPlottable *plottable, QMouseEvent *event); 1619 | void itemClick(QCPAbstractItem *item, QMouseEvent *event); 1620 | void itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event); 1621 | void axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); 1622 | void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); 1623 | void legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); 1624 | void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); 1625 | void titleClick(QMouseEvent *event, QCPPlotTitle *title); 1626 | void titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title); 1627 | 1628 | void selectionChangedByUser(); 1629 | void beforeReplot(); 1630 | void afterReplot(); 1631 | 1632 | protected: 1633 | // property members: 1634 | QRect mViewport; 1635 | QCPLayoutGrid *mPlotLayout; 1636 | bool mAutoAddPlottableToLegend; 1637 | QList mPlottables; 1638 | QList mGraphs; // extra list of plottables also in mPlottables that are of type QCPGraph 1639 | QList mItems; 1640 | QList mLayers; 1641 | QCP::AntialiasedElements mAntialiasedElements, mNotAntialiasedElements; 1642 | QCP::Interactions mInteractions; 1643 | int mSelectionTolerance; 1644 | bool mNoAntialiasingOnDrag; 1645 | QBrush mBackgroundBrush; 1646 | QPixmap mBackgroundPixmap; 1647 | QPixmap mScaledBackgroundPixmap; 1648 | bool mBackgroundScaled; 1649 | Qt::AspectRatioMode mBackgroundScaledMode; 1650 | QCPLayer *mCurrentLayer; 1651 | QCP::PlottingHints mPlottingHints; 1652 | Qt::KeyboardModifier mMultiSelectModifier; 1653 | 1654 | // non-property members: 1655 | QPixmap mPaintBuffer; 1656 | QPoint mMousePressPos; 1657 | QCPLayoutElement *mMouseEventElement; 1658 | bool mReplotting; 1659 | 1660 | // reimplemented virtual methods: 1661 | virtual QSize minimumSizeHint() const; 1662 | virtual QSize sizeHint() const; 1663 | virtual void paintEvent(QPaintEvent *event); 1664 | virtual void resizeEvent(QResizeEvent *event); 1665 | virtual void mouseDoubleClickEvent(QMouseEvent *event); 1666 | virtual void mousePressEvent(QMouseEvent *event); 1667 | virtual void mouseMoveEvent(QMouseEvent *event); 1668 | virtual void mouseReleaseEvent(QMouseEvent *event); 1669 | virtual void wheelEvent(QWheelEvent *event); 1670 | 1671 | // introduced virtual methods: 1672 | virtual void draw(QCPPainter *painter); 1673 | virtual void axisRemoved(QCPAxis *axis); 1674 | virtual void legendRemoved(QCPLegend *legend); 1675 | 1676 | // non-virtual methods: 1677 | void updateLayerIndices() const; 1678 | QCPLayerable *layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=0) const; 1679 | void drawBackground(QCPPainter *painter); 1680 | 1681 | friend class QCPLegend; 1682 | friend class QCPAxis; 1683 | friend class QCPLayer; 1684 | friend class QCPAxisRect; 1685 | }; 1686 | 1687 | 1688 | /*! \file */ 1689 | 1690 | 1691 | 1692 | class QCP_LIB_DECL QCPData 1693 | { 1694 | public: 1695 | QCPData(); 1696 | QCPData(double key, double value); 1697 | double key, value; 1698 | double keyErrorPlus, keyErrorMinus; 1699 | double valueErrorPlus, valueErrorMinus; 1700 | }; 1701 | Q_DECLARE_TYPEINFO(QCPData, Q_MOVABLE_TYPE); 1702 | 1703 | /*! \typedef QCPDataMap 1704 | Container for storing QCPData items in a sorted fashion. The key of the map 1705 | is the key member of the QCPData instance. 1706 | 1707 | This is the container in which QCPGraph holds its data. 1708 | \see QCPData, QCPGraph::setData 1709 | */ 1710 | typedef QMap QCPDataMap; 1711 | typedef QMapIterator QCPDataMapIterator; 1712 | typedef QMutableMapIterator QCPDataMutableMapIterator; 1713 | 1714 | 1715 | class QCP_LIB_DECL QCPGraph : public QCPAbstractPlottable 1716 | { 1717 | Q_OBJECT 1718 | /// \cond INCLUDE_QPROPERTIES 1719 | Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) 1720 | Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) 1721 | Q_PROPERTY(ErrorType errorType READ errorType WRITE setErrorType) 1722 | Q_PROPERTY(QPen errorPen READ errorPen WRITE setErrorPen) 1723 | Q_PROPERTY(double errorBarSize READ errorBarSize WRITE setErrorBarSize) 1724 | Q_PROPERTY(bool errorBarSkipSymbol READ errorBarSkipSymbol WRITE setErrorBarSkipSymbol) 1725 | Q_PROPERTY(QCPGraph* channelFillGraph READ channelFillGraph WRITE setChannelFillGraph) 1726 | /// \endcond 1727 | public: 1728 | /*! 1729 | Defines how the graph's line is represented visually in the plot. The line is drawn with the 1730 | current pen of the graph (\ref setPen). 1731 | \see setLineStyle 1732 | */ 1733 | enum LineStyle { lsNone ///< data points are not connected with any lines (e.g. data only represented 1734 | ///< with symbols according to the scatter style, see \ref setScatterStyle) 1735 | ,lsLine ///< data points are connected by a straight line 1736 | ,lsStepLeft ///< line is drawn as steps where the step height is the value of the left data point 1737 | ,lsStepRight ///< line is drawn as steps where the step height is the value of the right data point 1738 | ,lsStepCenter ///< line is drawn as steps where the step is in between two data points 1739 | ,lsImpulse ///< each data point is represented by a line parallel to the value axis, which reaches from the data point to the zero-value-line 1740 | }; 1741 | Q_ENUMS(LineStyle) 1742 | /*! 1743 | Defines what kind of error bars are drawn for each data point 1744 | */ 1745 | enum ErrorType { etNone ///< No error bars are shown 1746 | ,etKey ///< Error bars for the key dimension of the data point are shown 1747 | ,etValue ///< Error bars for the value dimension of the data point are shown 1748 | ,etBoth ///< Error bars for both key and value dimensions of the data point are shown 1749 | }; 1750 | Q_ENUMS(ErrorType) 1751 | 1752 | explicit QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis); 1753 | virtual ~QCPGraph(); 1754 | 1755 | // getters: 1756 | const QCPDataMap *data() const { return mData; } 1757 | LineStyle lineStyle() const { return mLineStyle; } 1758 | QCPScatterStyle scatterStyle() const { return mScatterStyle; } 1759 | ErrorType errorType() const { return mErrorType; } 1760 | QPen errorPen() const { return mErrorPen; } 1761 | double errorBarSize() const { return mErrorBarSize; } 1762 | bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; } 1763 | QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); } 1764 | 1765 | // setters: 1766 | void setData(QCPDataMap *data, bool copy=false); 1767 | void setData(const QVector &key, const QVector &value); 1768 | void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyError); 1769 | void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus); 1770 | void setDataValueError(const QVector &key, const QVector &value, const QVector &valueError); 1771 | void setDataValueError(const QVector &key, const QVector &value, const QVector &valueErrorMinus, const QVector &valueErrorPlus); 1772 | void setDataBothError(const QVector &key, const QVector &value, const QVector &keyError, const QVector &valueError); 1773 | void setDataBothError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus, const QVector &valueErrorMinus, const QVector &valueErrorPlus); 1774 | void setLineStyle(LineStyle ls); 1775 | void setScatterStyle(const QCPScatterStyle &style); 1776 | void setErrorType(ErrorType errorType); 1777 | void setErrorPen(const QPen &pen); 1778 | void setErrorBarSize(double size); 1779 | void setErrorBarSkipSymbol(bool enabled); 1780 | void setChannelFillGraph(QCPGraph *targetGraph); 1781 | 1782 | // non-property methods: 1783 | void addData(const QCPDataMap &dataMap); 1784 | void addData(const QCPData &data); 1785 | void addData(double key, double value); 1786 | void addData(const QVector &keys, const QVector &values); 1787 | void removeDataBefore(double key); 1788 | void removeDataAfter(double key); 1789 | void removeData(double fromKey, double toKey); 1790 | void removeData(double key); 1791 | 1792 | // reimplemented virtual methods: 1793 | virtual void clearData(); 1794 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 1795 | using QCPAbstractPlottable::rescaleAxes; 1796 | using QCPAbstractPlottable::rescaleKeyAxis; 1797 | using QCPAbstractPlottable::rescaleValueAxis; 1798 | virtual void rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface 1799 | virtual void rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface 1800 | virtual void rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface 1801 | 1802 | protected: 1803 | // property members: 1804 | QCPDataMap *mData; 1805 | QPen mErrorPen; 1806 | LineStyle mLineStyle; 1807 | QCPScatterStyle mScatterStyle; 1808 | ErrorType mErrorType; 1809 | double mErrorBarSize; 1810 | bool mErrorBarSkipSymbol; 1811 | QWeakPointer mChannelFillGraph; 1812 | 1813 | // reimplemented virtual methods: 1814 | virtual void draw(QCPPainter *painter); 1815 | virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; 1816 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 1817 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 1818 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface 1819 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface 1820 | 1821 | // introduced virtual methods: 1822 | virtual void drawFill(QCPPainter *painter, QVector *lineData) const; 1823 | virtual void drawScatterPlot(QCPPainter *painter, QVector *pointData) const; 1824 | virtual void drawLinePlot(QCPPainter *painter, QVector *lineData) const; 1825 | virtual void drawImpulsePlot(QCPPainter *painter, QVector *lineData) const; 1826 | 1827 | // non-virtual methods: 1828 | void getPlotData(QVector *lineData, QVector *pointData) const; 1829 | void getScatterPlotData(QVector *pointData) const; 1830 | void getLinePlotData(QVector *lineData, QVector *pointData) const; 1831 | void getStepLeftPlotData(QVector *lineData, QVector *pointData) const; 1832 | void getStepRightPlotData(QVector *lineData, QVector *pointData) const; 1833 | void getStepCenterPlotData(QVector *lineData, QVector *pointData) const; 1834 | void getImpulsePlotData(QVector *lineData, QVector *pointData) const; 1835 | void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const; 1836 | void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper, int &count) const; 1837 | void addFillBasePoints(QVector *lineData) const; 1838 | void removeFillBasePoints(QVector *lineData) const; 1839 | QPointF lowerFillBasePoint(double lowerKey) const; 1840 | QPointF upperFillBasePoint(double upperKey) const; 1841 | const QPolygonF getChannelFillPolygon(const QVector *lineData) const; 1842 | int findIndexBelowX(const QVector *data, double x) const; 1843 | int findIndexAboveX(const QVector *data, double x) const; 1844 | int findIndexBelowY(const QVector *data, double y) const; 1845 | int findIndexAboveY(const QVector *data, double y) const; 1846 | double pointDistance(const QPointF &pixelPoint) const; 1847 | 1848 | friend class QCustomPlot; 1849 | friend class QCPLegend; 1850 | }; 1851 | 1852 | 1853 | /*! \file */ 1854 | 1855 | 1856 | 1857 | class QCP_LIB_DECL QCPCurveData 1858 | { 1859 | public: 1860 | QCPCurveData(); 1861 | QCPCurveData(double t, double key, double value); 1862 | double t, key, value; 1863 | }; 1864 | Q_DECLARE_TYPEINFO(QCPCurveData, Q_MOVABLE_TYPE); 1865 | 1866 | /*! \typedef QCPCurveDataMap 1867 | Container for storing QCPCurveData items in a sorted fashion. The key of the map 1868 | is the t member of the QCPCurveData instance. 1869 | 1870 | This is the container in which QCPCurve holds its data. 1871 | \see QCPCurveData, QCPCurve::setData 1872 | */ 1873 | 1874 | typedef QMap QCPCurveDataMap; 1875 | typedef QMapIterator QCPCurveDataMapIterator; 1876 | typedef QMutableMapIterator QCPCurveDataMutableMapIterator; 1877 | 1878 | 1879 | class QCP_LIB_DECL QCPCurve : public QCPAbstractPlottable 1880 | { 1881 | Q_OBJECT 1882 | /// \cond INCLUDE_QPROPERTIES 1883 | Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) 1884 | Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) 1885 | /// \endcond 1886 | public: 1887 | /*! 1888 | Defines how the curve's line is represented visually in the plot. The line is drawn with the 1889 | current pen of the curve (\ref setPen). 1890 | \see setLineStyle 1891 | */ 1892 | enum LineStyle { lsNone, ///< No line is drawn between data points (e.g. only scatters) 1893 | lsLine ///< Data points are connected with a straight line 1894 | }; 1895 | explicit QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis); 1896 | virtual ~QCPCurve(); 1897 | 1898 | // getters: 1899 | QCPCurveDataMap *data() const { return mData; } 1900 | QCPScatterStyle scatterStyle() const { return mScatterStyle; } 1901 | LineStyle lineStyle() const { return mLineStyle; } 1902 | 1903 | // setters: 1904 | void setData(QCPCurveDataMap *data, bool copy=false); 1905 | void setData(const QVector &t, const QVector &key, const QVector &value); 1906 | void setData(const QVector &key, const QVector &value); 1907 | void setScatterStyle(const QCPScatterStyle &style); 1908 | void setLineStyle(LineStyle style); 1909 | 1910 | // non-property methods: 1911 | void addData(const QCPCurveDataMap &dataMap); 1912 | void addData(const QCPCurveData &data); 1913 | void addData(double t, double key, double value); 1914 | void addData(double key, double value); 1915 | void addData(const QVector &ts, const QVector &keys, const QVector &values); 1916 | void removeDataBefore(double t); 1917 | void removeDataAfter(double t); 1918 | void removeData(double fromt, double tot); 1919 | void removeData(double t); 1920 | 1921 | // reimplemented virtual methods: 1922 | virtual void clearData(); 1923 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 1924 | 1925 | protected: 1926 | // property members: 1927 | QCPCurveDataMap *mData; 1928 | QCPScatterStyle mScatterStyle; 1929 | LineStyle mLineStyle; 1930 | 1931 | // reimplemented virtual methods: 1932 | virtual void draw(QCPPainter *painter); 1933 | virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; 1934 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 1935 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 1936 | 1937 | // introduced virtual methods: 1938 | virtual void drawScatterPlot(QCPPainter *painter, const QVector *pointData) const; 1939 | 1940 | // non-virtual methods: 1941 | void getCurveData(QVector *lineData) const; 1942 | double pointDistance(const QPointF &pixelPoint) const; 1943 | QPointF outsideCoordsToPixels(double key, double value, int region, QRect axisRect) const; 1944 | 1945 | friend class QCustomPlot; 1946 | friend class QCPLegend; 1947 | }; 1948 | 1949 | 1950 | /*! \file */ 1951 | 1952 | 1953 | 1954 | class QCP_LIB_DECL QCPBarData 1955 | { 1956 | public: 1957 | QCPBarData(); 1958 | QCPBarData(double key, double value); 1959 | double key, value; 1960 | }; 1961 | Q_DECLARE_TYPEINFO(QCPBarData, Q_MOVABLE_TYPE); 1962 | 1963 | /*! \typedef QCPBarDataMap 1964 | Container for storing QCPBarData items in a sorted fashion. The key of the map 1965 | is the key member of the QCPBarData instance. 1966 | 1967 | This is the container in which QCPBars holds its data. 1968 | \see QCPBarData, QCPBars::setData 1969 | */ 1970 | typedef QMap QCPBarDataMap; 1971 | typedef QMapIterator QCPBarDataMapIterator; 1972 | typedef QMutableMapIterator QCPBarDataMutableMapIterator; 1973 | 1974 | 1975 | class QCP_LIB_DECL QCPBars : public QCPAbstractPlottable 1976 | { 1977 | Q_OBJECT 1978 | /// \cond INCLUDE_QPROPERTIES 1979 | Q_PROPERTY(double width READ width WRITE setWidth) 1980 | Q_PROPERTY(QCPBars* barBelow READ barBelow) 1981 | Q_PROPERTY(QCPBars* barAbove READ barAbove) 1982 | /// \endcond 1983 | public: 1984 | explicit QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis); 1985 | virtual ~QCPBars(); 1986 | 1987 | // getters: 1988 | double width() const { return mWidth; } 1989 | QCPBars *barBelow() const { return mBarBelow.data(); } 1990 | QCPBars *barAbove() const { return mBarAbove.data(); } 1991 | QCPBarDataMap *data() const { return mData; } 1992 | 1993 | // setters: 1994 | void setWidth(double width); 1995 | void setData(QCPBarDataMap *data, bool copy=false); 1996 | void setData(const QVector &key, const QVector &value); 1997 | 1998 | // non-property methods: 1999 | void moveBelow(QCPBars *bars); 2000 | void moveAbove(QCPBars *bars); 2001 | void addData(const QCPBarDataMap &dataMap); 2002 | void addData(const QCPBarData &data); 2003 | void addData(double key, double value); 2004 | void addData(const QVector &keys, const QVector &values); 2005 | void removeDataBefore(double key); 2006 | void removeDataAfter(double key); 2007 | void removeData(double fromKey, double toKey); 2008 | void removeData(double key); 2009 | 2010 | // reimplemented virtual methods: 2011 | virtual void clearData(); 2012 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2013 | 2014 | protected: 2015 | // property members: 2016 | QCPBarDataMap *mData; 2017 | double mWidth; 2018 | QWeakPointer mBarBelow, mBarAbove; 2019 | 2020 | // reimplemented virtual methods: 2021 | virtual void draw(QCPPainter *painter); 2022 | virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; 2023 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 2024 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 2025 | 2026 | // non-virtual methods: 2027 | QPolygonF getBarPolygon(double key, double value) const; 2028 | double getBaseValue(double key, bool positive) const; 2029 | static void connectBars(QCPBars* lower, QCPBars* upper); 2030 | 2031 | friend class QCustomPlot; 2032 | friend class QCPLegend; 2033 | }; 2034 | 2035 | 2036 | /*! \file */ 2037 | 2038 | 2039 | 2040 | class QCP_LIB_DECL QCPStatisticalBox : public QCPAbstractPlottable 2041 | { 2042 | Q_OBJECT 2043 | /// \cond INCLUDE_QPROPERTIES 2044 | Q_PROPERTY(double key READ key WRITE setKey) 2045 | Q_PROPERTY(double minimum READ minimum WRITE setMinimum) 2046 | Q_PROPERTY(double lowerQuartile READ lowerQuartile WRITE setLowerQuartile) 2047 | Q_PROPERTY(double median READ median WRITE setMedian) 2048 | Q_PROPERTY(double upperQuartile READ upperQuartile WRITE setUpperQuartile) 2049 | Q_PROPERTY(double maximum READ maximum WRITE setMaximum) 2050 | Q_PROPERTY(QVector outliers READ outliers WRITE setOutliers) 2051 | Q_PROPERTY(double width READ width WRITE setWidth) 2052 | Q_PROPERTY(double whiskerWidth READ whiskerWidth WRITE setWhiskerWidth) 2053 | Q_PROPERTY(QPen whiskerPen READ whiskerPen WRITE setWhiskerPen) 2054 | Q_PROPERTY(QPen whiskerBarPen READ whiskerBarPen WRITE setWhiskerBarPen) 2055 | Q_PROPERTY(QPen medianPen READ medianPen WRITE setMedianPen) 2056 | Q_PROPERTY(QCPScatterStyle outlierStyle READ outlierStyle WRITE setOutlierStyle) 2057 | /// \endcond 2058 | public: 2059 | explicit QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis); 2060 | 2061 | // getters: 2062 | double key() const { return mKey; } 2063 | double minimum() const { return mMinimum; } 2064 | double lowerQuartile() const { return mLowerQuartile; } 2065 | double median() const { return mMedian; } 2066 | double upperQuartile() const { return mUpperQuartile; } 2067 | double maximum() const { return mMaximum; } 2068 | QVector outliers() const { return mOutliers; } 2069 | double width() const { return mWidth; } 2070 | double whiskerWidth() const { return mWhiskerWidth; } 2071 | QPen whiskerPen() const { return mWhiskerPen; } 2072 | QPen whiskerBarPen() const { return mWhiskerBarPen; } 2073 | QPen medianPen() const { return mMedianPen; } 2074 | QCPScatterStyle outlierStyle() const { return mOutlierStyle; } 2075 | 2076 | // setters: 2077 | void setKey(double key); 2078 | void setMinimum(double value); 2079 | void setLowerQuartile(double value); 2080 | void setMedian(double value); 2081 | void setUpperQuartile(double value); 2082 | void setMaximum(double value); 2083 | void setOutliers(const QVector &values); 2084 | void setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum); 2085 | void setWidth(double width); 2086 | void setWhiskerWidth(double width); 2087 | void setWhiskerPen(const QPen &pen); 2088 | void setWhiskerBarPen(const QPen &pen); 2089 | void setMedianPen(const QPen &pen); 2090 | void setOutlierStyle(const QCPScatterStyle &style); 2091 | 2092 | // non-property methods: 2093 | virtual void clearData(); 2094 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2095 | 2096 | protected: 2097 | // property members: 2098 | QVector mOutliers; 2099 | double mKey, mMinimum, mLowerQuartile, mMedian, mUpperQuartile, mMaximum; 2100 | double mWidth; 2101 | double mWhiskerWidth; 2102 | QPen mWhiskerPen, mWhiskerBarPen, mMedianPen; 2103 | QCPScatterStyle mOutlierStyle; 2104 | 2105 | // reimplemented virtual methods: 2106 | virtual void draw(QCPPainter *painter); 2107 | virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; 2108 | virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 2109 | virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const; 2110 | 2111 | // introduced virtual methods: 2112 | virtual void drawQuartileBox(QCPPainter *painter, QRectF *quartileBox=0) const; 2113 | virtual void drawMedian(QCPPainter *painter) const; 2114 | virtual void drawWhiskers(QCPPainter *painter) const; 2115 | virtual void drawOutliers(QCPPainter *painter) const; 2116 | 2117 | friend class QCustomPlot; 2118 | friend class QCPLegend; 2119 | }; 2120 | 2121 | 2122 | class QCP_LIB_DECL QCPItemStraightLine : public QCPAbstractItem 2123 | { 2124 | Q_OBJECT 2125 | /// \cond INCLUDE_QPROPERTIES 2126 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2127 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2128 | /// \endcond 2129 | public: 2130 | QCPItemStraightLine(QCustomPlot *parentPlot); 2131 | virtual ~QCPItemStraightLine(); 2132 | 2133 | // getters: 2134 | QPen pen() const { return mPen; } 2135 | QPen selectedPen() const { return mSelectedPen; } 2136 | 2137 | // setters; 2138 | void setPen(const QPen &pen); 2139 | void setSelectedPen(const QPen &pen); 2140 | 2141 | // reimplemented virtual methods: 2142 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2143 | 2144 | QCPItemPosition * const point1; 2145 | QCPItemPosition * const point2; 2146 | 2147 | protected: 2148 | // property members: 2149 | QPen mPen, mSelectedPen; 2150 | 2151 | // reimplemented virtual methods: 2152 | virtual void draw(QCPPainter *painter); 2153 | 2154 | // non-virtual methods: 2155 | double distToStraightLine(const QVector2D &point1, const QVector2D &vec, const QVector2D &point) const; 2156 | QLineF getRectClippedStraightLine(const QVector2D &point1, const QVector2D &vec, const QRect &rect) const; 2157 | QPen mainPen() const; 2158 | }; 2159 | 2160 | 2161 | class QCP_LIB_DECL QCPItemLine : public QCPAbstractItem 2162 | { 2163 | Q_OBJECT 2164 | /// \cond INCLUDE_QPROPERTIES 2165 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2166 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2167 | Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) 2168 | Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) 2169 | /// \endcond 2170 | public: 2171 | QCPItemLine(QCustomPlot *parentPlot); 2172 | virtual ~QCPItemLine(); 2173 | 2174 | // getters: 2175 | QPen pen() const { return mPen; } 2176 | QPen selectedPen() const { return mSelectedPen; } 2177 | QCPLineEnding head() const { return mHead; } 2178 | QCPLineEnding tail() const { return mTail; } 2179 | 2180 | // setters; 2181 | void setPen(const QPen &pen); 2182 | void setSelectedPen(const QPen &pen); 2183 | void setHead(const QCPLineEnding &head); 2184 | void setTail(const QCPLineEnding &tail); 2185 | 2186 | // reimplemented virtual methods: 2187 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2188 | 2189 | QCPItemPosition * const start; 2190 | QCPItemPosition * const end; 2191 | 2192 | protected: 2193 | // property members: 2194 | QPen mPen, mSelectedPen; 2195 | QCPLineEnding mHead, mTail; 2196 | 2197 | // reimplemented virtual methods: 2198 | virtual void draw(QCPPainter *painter); 2199 | 2200 | // non-virtual methods: 2201 | QLineF getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const; 2202 | QPen mainPen() const; 2203 | }; 2204 | 2205 | 2206 | class QCP_LIB_DECL QCPItemCurve : public QCPAbstractItem 2207 | { 2208 | Q_OBJECT 2209 | /// \cond INCLUDE_QPROPERTIES 2210 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2211 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2212 | Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) 2213 | Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) 2214 | /// \endcond 2215 | public: 2216 | QCPItemCurve(QCustomPlot *parentPlot); 2217 | virtual ~QCPItemCurve(); 2218 | 2219 | // getters: 2220 | QPen pen() const { return mPen; } 2221 | QPen selectedPen() const { return mSelectedPen; } 2222 | QCPLineEnding head() const { return mHead; } 2223 | QCPLineEnding tail() const { return mTail; } 2224 | 2225 | // setters; 2226 | void setPen(const QPen &pen); 2227 | void setSelectedPen(const QPen &pen); 2228 | void setHead(const QCPLineEnding &head); 2229 | void setTail(const QCPLineEnding &tail); 2230 | 2231 | // reimplemented virtual methods: 2232 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2233 | 2234 | QCPItemPosition * const start; 2235 | QCPItemPosition * const startDir; 2236 | QCPItemPosition * const endDir; 2237 | QCPItemPosition * const end; 2238 | 2239 | protected: 2240 | // property members: 2241 | QPen mPen, mSelectedPen; 2242 | QCPLineEnding mHead, mTail; 2243 | 2244 | // reimplemented virtual methods: 2245 | virtual void draw(QCPPainter *painter); 2246 | 2247 | // non-virtual methods: 2248 | QPen mainPen() const; 2249 | }; 2250 | 2251 | 2252 | class QCP_LIB_DECL QCPItemRect : public QCPAbstractItem 2253 | { 2254 | Q_OBJECT 2255 | /// \cond INCLUDE_QPROPERTIES 2256 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2257 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2258 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 2259 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 2260 | /// \endcond 2261 | public: 2262 | QCPItemRect(QCustomPlot *parentPlot); 2263 | virtual ~QCPItemRect(); 2264 | 2265 | // getters: 2266 | QPen pen() const { return mPen; } 2267 | QPen selectedPen() const { return mSelectedPen; } 2268 | QBrush brush() const { return mBrush; } 2269 | QBrush selectedBrush() const { return mSelectedBrush; } 2270 | 2271 | // setters; 2272 | void setPen(const QPen &pen); 2273 | void setSelectedPen(const QPen &pen); 2274 | void setBrush(const QBrush &brush); 2275 | void setSelectedBrush(const QBrush &brush); 2276 | 2277 | // reimplemented virtual methods: 2278 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2279 | 2280 | QCPItemPosition * const topLeft; 2281 | QCPItemPosition * const bottomRight; 2282 | QCPItemAnchor * const top; 2283 | QCPItemAnchor * const topRight; 2284 | QCPItemAnchor * const right; 2285 | QCPItemAnchor * const bottom; 2286 | QCPItemAnchor * const bottomLeft; 2287 | QCPItemAnchor * const left; 2288 | 2289 | protected: 2290 | enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; 2291 | 2292 | // property members: 2293 | QPen mPen, mSelectedPen; 2294 | QBrush mBrush, mSelectedBrush; 2295 | 2296 | // reimplemented virtual methods: 2297 | virtual void draw(QCPPainter *painter); 2298 | virtual QPointF anchorPixelPoint(int anchorId) const; 2299 | 2300 | // non-virtual methods: 2301 | QPen mainPen() const; 2302 | QBrush mainBrush() const; 2303 | }; 2304 | 2305 | 2306 | class QCP_LIB_DECL QCPItemText : public QCPAbstractItem 2307 | { 2308 | Q_OBJECT 2309 | /// \cond INCLUDE_QPROPERTIES 2310 | Q_PROPERTY(QColor color READ color WRITE setColor) 2311 | Q_PROPERTY(QColor selectedColor READ selectedColor WRITE setSelectedColor) 2312 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2313 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2314 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 2315 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 2316 | Q_PROPERTY(QFont font READ font WRITE setFont) 2317 | Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) 2318 | Q_PROPERTY(QString text READ text WRITE setText) 2319 | Q_PROPERTY(Qt::Alignment positionAlignment READ positionAlignment WRITE setPositionAlignment) 2320 | Q_PROPERTY(Qt::Alignment textAlignment READ textAlignment WRITE setTextAlignment) 2321 | Q_PROPERTY(double rotation READ rotation WRITE setRotation) 2322 | Q_PROPERTY(QMargins padding READ padding WRITE setPadding) 2323 | /// \endcond 2324 | public: 2325 | QCPItemText(QCustomPlot *parentPlot); 2326 | virtual ~QCPItemText(); 2327 | 2328 | // getters: 2329 | QColor color() const { return mColor; } 2330 | QColor selectedColor() const { return mSelectedColor; } 2331 | QPen pen() const { return mPen; } 2332 | QPen selectedPen() const { return mSelectedPen; } 2333 | QBrush brush() const { return mBrush; } 2334 | QBrush selectedBrush() const { return mSelectedBrush; } 2335 | QFont font() const { return mFont; } 2336 | QFont selectedFont() const { return mSelectedFont; } 2337 | QString text() const { return mText; } 2338 | Qt::Alignment positionAlignment() const { return mPositionAlignment; } 2339 | Qt::Alignment textAlignment() const { return mTextAlignment; } 2340 | double rotation() const { return mRotation; } 2341 | QMargins padding() const { return mPadding; } 2342 | 2343 | // setters; 2344 | void setColor(const QColor &color); 2345 | void setSelectedColor(const QColor &color); 2346 | void setPen(const QPen &pen); 2347 | void setSelectedPen(const QPen &pen); 2348 | void setBrush(const QBrush &brush); 2349 | void setSelectedBrush(const QBrush &brush); 2350 | void setFont(const QFont &font); 2351 | void setSelectedFont(const QFont &font); 2352 | void setText(const QString &text); 2353 | void setPositionAlignment(Qt::Alignment alignment); 2354 | void setTextAlignment(Qt::Alignment alignment); 2355 | void setRotation(double degrees); 2356 | void setPadding(const QMargins &padding); 2357 | 2358 | // reimplemented virtual methods: 2359 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2360 | 2361 | QCPItemPosition * const position; 2362 | QCPItemAnchor * const topLeft; 2363 | QCPItemAnchor * const top; 2364 | QCPItemAnchor * const topRight; 2365 | QCPItemAnchor * const right; 2366 | QCPItemAnchor * const bottomRight; 2367 | QCPItemAnchor * const bottom; 2368 | QCPItemAnchor * const bottomLeft; 2369 | QCPItemAnchor * const left; 2370 | 2371 | protected: 2372 | enum AnchorIndex {aiTopLeft, aiTop, aiTopRight, aiRight, aiBottomRight, aiBottom, aiBottomLeft, aiLeft}; 2373 | 2374 | // property members: 2375 | QColor mColor, mSelectedColor; 2376 | QPen mPen, mSelectedPen; 2377 | QBrush mBrush, mSelectedBrush; 2378 | QFont mFont, mSelectedFont; 2379 | QString mText; 2380 | Qt::Alignment mPositionAlignment; 2381 | Qt::Alignment mTextAlignment; 2382 | double mRotation; 2383 | QMargins mPadding; 2384 | 2385 | // reimplemented virtual methods: 2386 | virtual void draw(QCPPainter *painter); 2387 | virtual QPointF anchorPixelPoint(int anchorId) const; 2388 | 2389 | // non-virtual methods: 2390 | QPointF getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const; 2391 | QFont mainFont() const; 2392 | QColor mainColor() const; 2393 | QPen mainPen() const; 2394 | QBrush mainBrush() const; 2395 | }; 2396 | 2397 | 2398 | class QCP_LIB_DECL QCPItemEllipse : public QCPAbstractItem 2399 | { 2400 | Q_OBJECT 2401 | /// \cond INCLUDE_QPROPERTIES 2402 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2403 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2404 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 2405 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 2406 | /// \endcond 2407 | public: 2408 | QCPItemEllipse(QCustomPlot *parentPlot); 2409 | virtual ~QCPItemEllipse(); 2410 | 2411 | // getters: 2412 | QPen pen() const { return mPen; } 2413 | QPen selectedPen() const { return mSelectedPen; } 2414 | QBrush brush() const { return mBrush; } 2415 | QBrush selectedBrush() const { return mSelectedBrush; } 2416 | 2417 | // setters; 2418 | void setPen(const QPen &pen); 2419 | void setSelectedPen(const QPen &pen); 2420 | void setBrush(const QBrush &brush); 2421 | void setSelectedBrush(const QBrush &brush); 2422 | 2423 | // reimplemented virtual methods: 2424 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2425 | 2426 | QCPItemPosition * const topLeft; 2427 | QCPItemPosition * const bottomRight; 2428 | QCPItemAnchor * const topLeftRim; 2429 | QCPItemAnchor * const top; 2430 | QCPItemAnchor * const topRightRim; 2431 | QCPItemAnchor * const right; 2432 | QCPItemAnchor * const bottomRightRim; 2433 | QCPItemAnchor * const bottom; 2434 | QCPItemAnchor * const bottomLeftRim; 2435 | QCPItemAnchor * const left; 2436 | QCPItemAnchor * const center; 2437 | 2438 | protected: 2439 | enum AnchorIndex {aiTopLeftRim, aiTop, aiTopRightRim, aiRight, aiBottomRightRim, aiBottom, aiBottomLeftRim, aiLeft, aiCenter}; 2440 | 2441 | // property members: 2442 | QPen mPen, mSelectedPen; 2443 | QBrush mBrush, mSelectedBrush; 2444 | 2445 | // reimplemented virtual methods: 2446 | virtual void draw(QCPPainter *painter); 2447 | virtual QPointF anchorPixelPoint(int anchorId) const; 2448 | 2449 | // non-virtual methods: 2450 | QPen mainPen() const; 2451 | QBrush mainBrush() const; 2452 | }; 2453 | 2454 | 2455 | class QCP_LIB_DECL QCPItemPixmap : public QCPAbstractItem 2456 | { 2457 | Q_OBJECT 2458 | /// \cond INCLUDE_QPROPERTIES 2459 | Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) 2460 | Q_PROPERTY(bool scaled READ scaled WRITE setScaled) 2461 | Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode) 2462 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2463 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2464 | /// \endcond 2465 | public: 2466 | QCPItemPixmap(QCustomPlot *parentPlot); 2467 | virtual ~QCPItemPixmap(); 2468 | 2469 | // getters: 2470 | QPixmap pixmap() const { return mPixmap; } 2471 | bool scaled() const { return mScaled; } 2472 | Qt::AspectRatioMode aspectRatioMode() const { return mAspectRatioMode; } 2473 | QPen pen() const { return mPen; } 2474 | QPen selectedPen() const { return mSelectedPen; } 2475 | 2476 | // setters; 2477 | void setPixmap(const QPixmap &pixmap); 2478 | void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio); 2479 | void setPen(const QPen &pen); 2480 | void setSelectedPen(const QPen &pen); 2481 | 2482 | // reimplemented virtual methods: 2483 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2484 | 2485 | QCPItemPosition * const topLeft; 2486 | QCPItemPosition * const bottomRight; 2487 | QCPItemAnchor * const top; 2488 | QCPItemAnchor * const topRight; 2489 | QCPItemAnchor * const right; 2490 | QCPItemAnchor * const bottom; 2491 | QCPItemAnchor * const bottomLeft; 2492 | QCPItemAnchor * const left; 2493 | 2494 | protected: 2495 | enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; 2496 | 2497 | // property members: 2498 | QPixmap mPixmap; 2499 | QPixmap mScaledPixmap; 2500 | bool mScaled; 2501 | Qt::AspectRatioMode mAspectRatioMode; 2502 | QPen mPen, mSelectedPen; 2503 | 2504 | // reimplemented virtual methods: 2505 | virtual void draw(QCPPainter *painter); 2506 | virtual QPointF anchorPixelPoint(int anchorId) const; 2507 | 2508 | // non-virtual methods: 2509 | void updateScaledPixmap(QRect finalRect=QRect(), bool flipHorz=false, bool flipVert=false); 2510 | QRect getFinalRect(bool *flippedHorz=0, bool *flippedVert=0) const; 2511 | QPen mainPen() const; 2512 | }; 2513 | 2514 | 2515 | class QCP_LIB_DECL QCPItemTracer : public QCPAbstractItem 2516 | { 2517 | Q_OBJECT 2518 | /// \cond INCLUDE_QPROPERTIES 2519 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2520 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2521 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 2522 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 2523 | Q_PROPERTY(double size READ size WRITE setSize) 2524 | Q_PROPERTY(TracerStyle style READ style WRITE setStyle) 2525 | Q_PROPERTY(QCPGraph* graph READ graph WRITE setGraph) 2526 | Q_PROPERTY(double graphKey READ graphKey WRITE setGraphKey) 2527 | Q_PROPERTY(bool interpolating READ interpolating WRITE setInterpolating) 2528 | /// \endcond 2529 | public: 2530 | /*! 2531 | The different visual appearances a tracer item can have. Some styles size may be controlled with \ref setSize. 2532 | 2533 | \see setStyle 2534 | */ 2535 | enum TracerStyle { tsNone ///< The tracer is not visible 2536 | ,tsPlus ///< A plus shaped crosshair with limited size 2537 | ,tsCrosshair ///< A plus shaped crosshair which spans the complete axis rect 2538 | ,tsCircle ///< A circle 2539 | ,tsSquare ///< A square 2540 | }; 2541 | Q_ENUMS(TracerStyle) 2542 | 2543 | QCPItemTracer(QCustomPlot *parentPlot); 2544 | virtual ~QCPItemTracer(); 2545 | 2546 | // getters: 2547 | QPen pen() const { return mPen; } 2548 | QPen selectedPen() const { return mSelectedPen; } 2549 | QBrush brush() const { return mBrush; } 2550 | QBrush selectedBrush() const { return mSelectedBrush; } 2551 | double size() const { return mSize; } 2552 | TracerStyle style() const { return mStyle; } 2553 | QCPGraph *graph() const { return mGraph; } 2554 | double graphKey() const { return mGraphKey; } 2555 | bool interpolating() const { return mInterpolating; } 2556 | 2557 | // setters; 2558 | void setPen(const QPen &pen); 2559 | void setSelectedPen(const QPen &pen); 2560 | void setBrush(const QBrush &brush); 2561 | void setSelectedBrush(const QBrush &brush); 2562 | void setSize(double size); 2563 | void setStyle(TracerStyle style); 2564 | void setGraph(QCPGraph *graph); 2565 | void setGraphKey(double key); 2566 | void setInterpolating(bool enabled); 2567 | 2568 | // reimplemented virtual methods: 2569 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2570 | 2571 | // non-virtual methods: 2572 | void updatePosition(); 2573 | 2574 | QCPItemPosition * const position; 2575 | 2576 | protected: 2577 | // property members: 2578 | QPen mPen, mSelectedPen; 2579 | QBrush mBrush, mSelectedBrush; 2580 | double mSize; 2581 | TracerStyle mStyle; 2582 | QCPGraph *mGraph; 2583 | double mGraphKey; 2584 | bool mInterpolating; 2585 | 2586 | // reimplemented virtual methods: 2587 | virtual void draw(QCPPainter *painter); 2588 | 2589 | // non-virtual methods: 2590 | QPen mainPen() const; 2591 | QBrush mainBrush() const; 2592 | }; 2593 | 2594 | 2595 | class QCP_LIB_DECL QCPItemBracket : public QCPAbstractItem 2596 | { 2597 | Q_OBJECT 2598 | /// \cond INCLUDE_QPROPERTIES 2599 | Q_PROPERTY(QPen pen READ pen WRITE setPen) 2600 | Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) 2601 | Q_PROPERTY(double length READ length WRITE setLength) 2602 | Q_PROPERTY(BracketStyle style READ style WRITE setStyle) 2603 | /// \endcond 2604 | public: 2605 | enum BracketStyle { bsSquare ///< A brace with angled edges 2606 | ,bsRound ///< A brace with round edges 2607 | ,bsCurly ///< A curly brace 2608 | ,bsCalligraphic ///< A curly brace with varying stroke width giving a calligraphic impression 2609 | }; 2610 | 2611 | QCPItemBracket(QCustomPlot *parentPlot); 2612 | virtual ~QCPItemBracket(); 2613 | 2614 | // getters: 2615 | QPen pen() const { return mPen; } 2616 | QPen selectedPen() const { return mSelectedPen; } 2617 | double length() const { return mLength; } 2618 | BracketStyle style() const { return mStyle; } 2619 | 2620 | // setters; 2621 | void setPen(const QPen &pen); 2622 | void setSelectedPen(const QPen &pen); 2623 | void setLength(double length); 2624 | void setStyle(BracketStyle style); 2625 | 2626 | // reimplemented virtual methods: 2627 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2628 | 2629 | QCPItemPosition * const left; 2630 | QCPItemPosition * const right; 2631 | QCPItemAnchor * const center; 2632 | 2633 | protected: 2634 | // property members: 2635 | enum AnchorIndex {aiCenter}; 2636 | QPen mPen, mSelectedPen; 2637 | double mLength; 2638 | BracketStyle mStyle; 2639 | 2640 | // reimplemented virtual methods: 2641 | virtual void draw(QCPPainter *painter); 2642 | virtual QPointF anchorPixelPoint(int anchorId) const; 2643 | 2644 | // non-virtual methods: 2645 | QPen mainPen() const; 2646 | }; 2647 | 2648 | 2649 | class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement 2650 | { 2651 | Q_OBJECT 2652 | /// \cond INCLUDE_QPROPERTIES 2653 | Q_PROPERTY(QPixmap background READ background WRITE setBackground) 2654 | Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) 2655 | Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) 2656 | Q_PROPERTY(Qt::Orientations rangeDrag READ rangeDrag WRITE setRangeDrag) 2657 | Q_PROPERTY(Qt::Orientations rangeZoom READ rangeZoom WRITE setRangeZoom) 2658 | /// \endcond 2659 | public: 2660 | explicit QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes=true); 2661 | virtual ~QCPAxisRect(); 2662 | 2663 | // getters: 2664 | QPixmap background() const { return mBackgroundPixmap; } 2665 | bool backgroundScaled() const { return mBackgroundScaled; } 2666 | Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } 2667 | Qt::Orientations rangeDrag() const { return mRangeDrag; } 2668 | Qt::Orientations rangeZoom() const { return mRangeZoom; } 2669 | QCPAxis *rangeDragAxis(Qt::Orientation orientation); 2670 | QCPAxis *rangeZoomAxis(Qt::Orientation orientation); 2671 | double rangeZoomFactor(Qt::Orientation orientation); 2672 | 2673 | // setters: 2674 | void setBackground(const QPixmap &pm); 2675 | void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); 2676 | void setBackground(const QBrush &brush); 2677 | void setBackgroundScaled(bool scaled); 2678 | void setBackgroundScaledMode(Qt::AspectRatioMode mode); 2679 | void setRangeDrag(Qt::Orientations orientations); 2680 | void setRangeZoom(Qt::Orientations orientations); 2681 | void setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical); 2682 | void setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical); 2683 | void setRangeZoomFactor(double horizontalFactor, double verticalFactor); 2684 | void setRangeZoomFactor(double factor); 2685 | 2686 | // non-property methods: 2687 | int axisCount(QCPAxis::AxisType type) const; 2688 | QCPAxis *axis(QCPAxis::AxisType type, int index=0) const; 2689 | QList axes(QCPAxis::AxisTypes types) const; 2690 | QList axes() const; 2691 | QCPAxis *addAxis(QCPAxis::AxisType type); 2692 | QList addAxes(QCPAxis::AxisTypes types); 2693 | bool removeAxis(QCPAxis *axis); 2694 | QCPLayoutInset *insetLayout() const { return mInsetLayout; } 2695 | 2696 | void setupFullAxesBox(bool connectRanges=false); 2697 | QList plottables() const; 2698 | QList graphs() const; 2699 | QList items() const; 2700 | 2701 | // read-only interface imitating a QRect: 2702 | int left() const { return mRect.left(); } 2703 | int right() const { return mRect.right(); } 2704 | int top() const { return mRect.top(); } 2705 | int bottom() const { return mRect.bottom(); } 2706 | int width() const { return mRect.width(); } 2707 | int height() const { return mRect.height(); } 2708 | QSize size() const { return mRect.size(); } 2709 | QPoint topLeft() const { return mRect.topLeft(); } 2710 | QPoint topRight() const { return mRect.topRight(); } 2711 | QPoint bottomLeft() const { return mRect.bottomLeft(); } 2712 | QPoint bottomRight() const { return mRect.bottomRight(); } 2713 | QPoint center() const { return mRect.center(); } 2714 | 2715 | // reimplemented virtual methods: 2716 | virtual void update(); 2717 | virtual QList elements(bool recursive) const; 2718 | 2719 | protected: 2720 | // property members: 2721 | QBrush mBackgroundBrush; 2722 | QPixmap mBackgroundPixmap; 2723 | QPixmap mScaledBackgroundPixmap; 2724 | bool mBackgroundScaled; 2725 | Qt::AspectRatioMode mBackgroundScaledMode; 2726 | QCPLayoutInset *mInsetLayout; 2727 | Qt::Orientations mRangeDrag, mRangeZoom; 2728 | QWeakPointer mRangeDragHorzAxis, mRangeDragVertAxis, mRangeZoomHorzAxis, mRangeZoomVertAxis; 2729 | double mRangeZoomFactorHorz, mRangeZoomFactorVert; 2730 | // non-property members: 2731 | QCPRange mDragStartHorzRange, mDragStartVertRange; 2732 | QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; 2733 | QPoint mDragStart; 2734 | bool mDragging; 2735 | QHash > mAxes; 2736 | 2737 | // reimplemented virtual methods: 2738 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 2739 | virtual void draw(QCPPainter *painter); 2740 | virtual int calculateAutoMargin(QCP::MarginSide side); 2741 | // events: 2742 | virtual void mousePressEvent(QMouseEvent *event); 2743 | virtual void mouseMoveEvent(QMouseEvent *event); 2744 | virtual void mouseReleaseEvent(QMouseEvent *event); 2745 | virtual void wheelEvent(QWheelEvent *event); 2746 | 2747 | // non-property methods: 2748 | void drawBackground(QCPPainter *painter); 2749 | void updateAxesOffset(QCPAxis::AxisType type); 2750 | 2751 | private: 2752 | Q_DISABLE_COPY(QCPAxisRect) 2753 | 2754 | friend class QCustomPlot; 2755 | }; 2756 | 2757 | 2758 | class QCP_LIB_DECL QCPAbstractLegendItem : public QCPLayoutElement 2759 | { 2760 | Q_OBJECT 2761 | /// \cond INCLUDE_QPROPERTIES 2762 | Q_PROPERTY(QCPLegend* parentLegend READ parentLegend) 2763 | Q_PROPERTY(QFont font READ font WRITE setFont) 2764 | Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) 2765 | Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) 2766 | Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) 2767 | Q_PROPERTY(bool selectable READ selectable WRITE setSelectable) 2768 | Q_PROPERTY(bool selected READ selected WRITE setSelected) 2769 | /// \endcond 2770 | public: 2771 | explicit QCPAbstractLegendItem(QCPLegend *parent); 2772 | 2773 | // getters: 2774 | QCPLegend *parentLegend() const { return mParentLegend; } 2775 | QFont font() const { return mFont; } 2776 | QColor textColor() const { return mTextColor; } 2777 | QFont selectedFont() const { return mSelectedFont; } 2778 | QColor selectedTextColor() const { return mSelectedTextColor; } 2779 | bool selectable() const { return mSelectable; } 2780 | bool selected() const { return mSelected; } 2781 | 2782 | // setters: 2783 | void setFont(const QFont &font); 2784 | void setTextColor(const QColor &color); 2785 | void setSelectedFont(const QFont &font); 2786 | void setSelectedTextColor(const QColor &color); 2787 | void setSelectable(bool selectable); 2788 | void setSelected(bool selected); 2789 | 2790 | // reimplemented virtual methods: 2791 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2792 | 2793 | signals: 2794 | void selectionChanged(bool selected); 2795 | 2796 | protected: 2797 | // property members: 2798 | QCPLegend *mParentLegend; 2799 | QFont mFont; 2800 | QColor mTextColor; 2801 | QFont mSelectedFont; 2802 | QColor mSelectedTextColor; 2803 | bool mSelectable, mSelected; 2804 | 2805 | // reimplemented virtual methods: 2806 | virtual QCP::Interaction selectionCategory() const; 2807 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 2808 | virtual QRect clipRect() const; 2809 | virtual void draw(QCPPainter *painter) = 0; 2810 | // events: 2811 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 2812 | virtual void deselectEvent(bool *selectionStateChanged); 2813 | 2814 | private: 2815 | Q_DISABLE_COPY(QCPAbstractLegendItem) 2816 | 2817 | friend class QCPLegend; 2818 | }; 2819 | 2820 | 2821 | class QCP_LIB_DECL QCPPlottableLegendItem : public QCPAbstractLegendItem 2822 | { 2823 | Q_OBJECT 2824 | public: 2825 | QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable); 2826 | 2827 | // getters: 2828 | QCPAbstractPlottable *plottable() { return mPlottable; } 2829 | 2830 | protected: 2831 | // property members: 2832 | QCPAbstractPlottable *mPlottable; 2833 | 2834 | // reimplemented virtual methods: 2835 | virtual void draw(QCPPainter *painter); 2836 | virtual QSize minimumSizeHint() const; 2837 | 2838 | // non-virtual methods: 2839 | QPen getIconBorderPen() const; 2840 | QColor getTextColor() const; 2841 | QFont getFont() const; 2842 | }; 2843 | 2844 | 2845 | class QCP_LIB_DECL QCPLegend : public QCPLayoutGrid 2846 | { 2847 | Q_OBJECT 2848 | /// \cond INCLUDE_QPROPERTIES 2849 | Q_PROPERTY(QPen borderPen READ borderPen WRITE setBorderPen) 2850 | Q_PROPERTY(QBrush brush READ brush WRITE setBrush) 2851 | Q_PROPERTY(QFont font READ font WRITE setFont) 2852 | Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) 2853 | Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) 2854 | Q_PROPERTY(int iconTextPadding READ iconTextPadding WRITE setIconTextPadding) 2855 | Q_PROPERTY(QPen iconBorderPen READ iconBorderPen WRITE setIconBorderPen) 2856 | Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE setSelectableParts) 2857 | Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE setSelectedParts) 2858 | Q_PROPERTY(QPen selectedBorderPen READ selectedBorderPen WRITE setSelectedBorderPen) 2859 | Q_PROPERTY(QPen selectedIconBorderPen READ selectedIconBorderPen WRITE setSelectedIconBorderPen) 2860 | Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) 2861 | Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) 2862 | Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) 2863 | /// \endcond 2864 | public: 2865 | /*! 2866 | Defines the selectable parts of a legend 2867 | 2868 | \see setSelectedParts, setSelectableParts 2869 | */ 2870 | enum SelectablePart { spNone = 0x000 ///< 0x000 None 2871 | ,spLegendBox = 0x001 ///< 0x001 The legend box (frame) 2872 | ,spItems = 0x002 ///< 0x002 Legend items individually (see \ref selectedItems) 2873 | }; 2874 | Q_FLAGS(SelectablePart SelectableParts) 2875 | Q_DECLARE_FLAGS(SelectableParts, SelectablePart) 2876 | 2877 | explicit QCPLegend(); 2878 | virtual ~QCPLegend(); 2879 | 2880 | // getters: 2881 | QPen borderPen() const { return mBorderPen; } 2882 | QBrush brush() const { return mBrush; } 2883 | QFont font() const { return mFont; } 2884 | QColor textColor() const { return mTextColor; } 2885 | QSize iconSize() const { return mIconSize; } 2886 | int iconTextPadding() const { return mIconTextPadding; } 2887 | QPen iconBorderPen() const { return mIconBorderPen; } 2888 | SelectableParts selectableParts() const { return mSelectableParts; } 2889 | SelectableParts selectedParts() const; 2890 | QPen selectedBorderPen() const { return mSelectedBorderPen; } 2891 | QPen selectedIconBorderPen() const { return mSelectedIconBorderPen; } 2892 | QBrush selectedBrush() const { return mSelectedBrush; } 2893 | QFont selectedFont() const { return mSelectedFont; } 2894 | QColor selectedTextColor() const { return mSelectedTextColor; } 2895 | 2896 | // setters: 2897 | void setBorderPen(const QPen &pen); 2898 | void setBrush(const QBrush &brush); 2899 | void setFont(const QFont &font); 2900 | void setTextColor(const QColor &color); 2901 | void setIconSize(const QSize &size); 2902 | void setIconSize(int width, int height); 2903 | void setIconTextPadding(int padding); 2904 | void setIconBorderPen(const QPen &pen); 2905 | void setSelectableParts(const SelectableParts &selectableParts); 2906 | void setSelectedParts(const SelectableParts &selectedParts); 2907 | void setSelectedBorderPen(const QPen &pen); 2908 | void setSelectedIconBorderPen(const QPen &pen); 2909 | void setSelectedBrush(const QBrush &brush); 2910 | void setSelectedFont(const QFont &font); 2911 | void setSelectedTextColor(const QColor &color); 2912 | 2913 | // reimplemented virtual methods: 2914 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 2915 | 2916 | // non-virtual methods: 2917 | QCPAbstractLegendItem *item(int index) const; 2918 | QCPPlottableLegendItem *itemWithPlottable(const QCPAbstractPlottable *plottable) const; 2919 | int itemCount() const; 2920 | bool hasItem(QCPAbstractLegendItem *item) const; 2921 | bool hasItemWithPlottable(const QCPAbstractPlottable *plottable) const; 2922 | bool addItem(QCPAbstractLegendItem *item); 2923 | bool removeItem(int index); 2924 | bool removeItem(QCPAbstractLegendItem *item); 2925 | void clearItems(); 2926 | QList selectedItems() const; 2927 | 2928 | signals: 2929 | void selectionChanged(QCPLegend::SelectableParts selection); 2930 | 2931 | protected: 2932 | // property members: 2933 | QPen mBorderPen, mIconBorderPen; 2934 | QBrush mBrush; 2935 | QFont mFont; 2936 | QColor mTextColor; 2937 | QSize mIconSize; 2938 | int mIconTextPadding; 2939 | SelectableParts mSelectedParts, mSelectableParts; 2940 | QPen mSelectedBorderPen, mSelectedIconBorderPen; 2941 | QBrush mSelectedBrush; 2942 | QFont mSelectedFont; 2943 | QColor mSelectedTextColor; 2944 | 2945 | // reimplemented virtual methods: 2946 | virtual void parentPlotInitialized(QCustomPlot *parentPlot); 2947 | virtual QCP::Interaction selectionCategory() const; 2948 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 2949 | virtual void draw(QCPPainter *painter); 2950 | // events: 2951 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 2952 | virtual void deselectEvent(bool *selectionStateChanged); 2953 | 2954 | // non-virtual methods: 2955 | QPen getBorderPen() const; 2956 | QBrush getBrush() const; 2957 | 2958 | private: 2959 | Q_DISABLE_COPY(QCPLegend) 2960 | 2961 | friend class QCustomPlot; 2962 | friend class QCPAbstractLegendItem; 2963 | }; 2964 | Q_DECLARE_OPERATORS_FOR_FLAGS(QCPLegend::SelectableParts) 2965 | Q_DECLARE_METATYPE(QCPLegend::SelectablePart) 2966 | 2967 | 2968 | class QCP_LIB_DECL QCPPlotTitle : public QCPLayoutElement 2969 | { 2970 | Q_OBJECT 2971 | /// \cond INCLUDE_QPROPERTIES 2972 | Q_PROPERTY(QString text READ text WRITE setText) 2973 | Q_PROPERTY(QFont font READ font WRITE setFont) 2974 | Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) 2975 | Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) 2976 | Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) 2977 | Q_PROPERTY(bool selectable READ selectable WRITE setSelectable) 2978 | Q_PROPERTY(bool selected READ selected WRITE setSelected) 2979 | /// \endcond 2980 | public: 2981 | explicit QCPPlotTitle(QCustomPlot *parentPlot); 2982 | explicit QCPPlotTitle(QCustomPlot *parentPlot, const QString &text); 2983 | 2984 | // getters: 2985 | QString text() const { return mText; } 2986 | QFont font() const { return mFont; } 2987 | QColor textColor() const { return mTextColor; } 2988 | QFont selectedFont() const { return mSelectedFont; } 2989 | QColor selectedTextColor() const { return mSelectedTextColor; } 2990 | bool selectable() const { return mSelectable; } 2991 | bool selected() const { return mSelected; } 2992 | 2993 | // setters: 2994 | void setText(const QString &text); 2995 | void setFont(const QFont &font); 2996 | void setTextColor(const QColor &color); 2997 | void setSelectedFont(const QFont &font); 2998 | void setSelectedTextColor(const QColor &color); 2999 | void setSelectable(bool selectable); 3000 | void setSelected(bool selected); 3001 | 3002 | // reimplemented virtual methods: 3003 | virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; 3004 | 3005 | signals: 3006 | void selectionChanged(bool selected); 3007 | 3008 | protected: 3009 | // property members: 3010 | QString mText; 3011 | QFont mFont; 3012 | QColor mTextColor; 3013 | QFont mSelectedFont; 3014 | QColor mSelectedTextColor; 3015 | QRect mTextBoundingRect; 3016 | bool mSelectable, mSelected; 3017 | 3018 | // reimplemented virtual methods: 3019 | virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; 3020 | virtual void draw(QCPPainter *painter); 3021 | virtual QSize minimumSizeHint() const; 3022 | virtual QSize maximumSizeHint() const; 3023 | // events: 3024 | virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); 3025 | virtual void deselectEvent(bool *selectionStateChanged); 3026 | 3027 | // non-virtual methods: 3028 | QFont mainFont() const; 3029 | QColor mainTextColor() const; 3030 | 3031 | private: 3032 | Q_DISABLE_COPY(QCPPlotTitle) 3033 | }; 3034 | 3035 | #endif // QCUSTOMPLOT_H 3036 | 3037 | --------------------------------------------------------------------------------