2018-05-03 05:08:45 +00:00
/* gGraphView Implementation
2014-04-09 21:01:57 +00:00
*
2018-03-28 07:10:52 +00:00
* Copyright ( c ) 2011 - 2018 Mark Watkins < mark @ jedimark . net >
2014-04-09 21:01:57 +00:00
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of the Linux
* distribution for more details . */
2011-11-26 04:00:31 +00:00
2014-04-23 17:20:38 +00:00
# include "Graphs/gGraphView.h"
2011-11-27 16:07:28 +00:00
# include <QDir>
2014-04-23 17:20:38 +00:00
# include <QFontMetrics>
# include <QLabel>
2013-01-17 18:26:11 +00:00
# include <QPixmapCache>
2014-04-23 17:20:38 +00:00
# include <QTimer>
2014-05-10 00:50:35 +00:00
# include <QFontMetrics>
2014-08-23 06:21:50 +00:00
# include <QWidgetAction>
2014-08-26 17:26:13 +00:00
# include <QGridLayout>
2018-05-03 05:08:45 +00:00
# include <QVBoxLayout>
# include <QDockWidget>
# include <QMainWindow>
2014-04-10 17:33:20 +00:00
# include <QWindow>
2018-05-05 07:14:44 +00:00
2011-12-01 15:40:32 +00:00
2012-01-05 06:54:07 +00:00
# ifdef DEBUG_EFFICIENCY
2014-04-10 17:33:20 +00:00
# include <QElapsedTimer>
2012-01-05 06:54:07 +00:00
# endif
2014-04-23 17:20:38 +00:00
# include <cmath>
2014-04-10 17:33:20 +00:00
# include "mainwindow.h"
2014-04-23 17:20:38 +00:00
# include "Graphs/glcommon.h"
# include "Graphs/gLineChart.h"
2014-08-27 09:13:14 +00:00
# include "Graphs/gSummaryChart.h"
2014-09-04 02:17:59 +00:00
# include "Graphs/gSessionTimesChart.h"
2014-04-23 17:20:38 +00:00
# include "Graphs/gYAxis.h"
# include "Graphs/gFlagsLine.h"
# include "SleepLib/profiles.h"
2014-04-10 17:33:20 +00:00
2015-08-27 09:46:05 +00:00
2014-04-10 17:33:20 +00:00
extern MainWindow * mainwin ;
2011-09-28 11:46:32 +00:00
2014-08-17 12:56:05 +00:00
# include <QApplication>
2014-08-27 09:00:55 +00:00
MyLabel : : MyLabel ( QWidget * parent )
: QWidget ( parent ) {
2014-08-17 12:56:05 +00:00
m_font = QApplication : : font ( ) ;
2014-08-27 09:00:55 +00:00
time . start ( ) ;
2014-08-17 12:56:05 +00:00
}
MyLabel : : ~ MyLabel ( )
{
}
void MyLabel : : setText ( QString text ) {
m_text = text ;
2014-08-27 09:00:55 +00:00
update ( ) ;
2014-08-17 12:56:05 +00:00
}
void MyLabel : : setFont ( QFont & font )
{
m_font = font ;
}
2014-08-27 09:00:55 +00:00
void MyLabel : : doRedraw ( )
{
update ( ) ;
}
2014-08-17 12:56:05 +00:00
void MyLabel : : setAlignment ( Qt : : Alignment alignment ) {
m_alignment = alignment ;
2014-08-27 09:00:55 +00:00
doRedraw ( ) ;
2014-08-17 12:56:05 +00:00
}
2014-08-27 09:00:55 +00:00
void MyLabel : : paintEvent ( QPaintEvent * /*event*/ )
2014-08-17 12:56:05 +00:00
{
QPainter painter ( this ) ;
painter . setFont ( m_font ) ;
2014-08-27 09:00:55 +00:00
painter . drawText ( rect ( ) , m_alignment , m_text ) ;
2014-08-17 12:56:05 +00:00
}
2014-04-17 05:21:50 +00:00
gToolTip : : gToolTip ( gGraphView * graphview )
: m_graphview ( graphview )
2011-09-05 10:28:41 +00:00
{
m_pos . setX ( 0 ) ;
m_pos . setY ( 0 ) ;
2014-04-17 05:21:50 +00:00
m_visible = false ;
2014-08-06 05:30:15 +00:00
m_alignment = TT_AlignCenter ;
2014-04-17 05:21:50 +00:00
m_spacer = 8 ; // pixels around text area
timer = new QTimer ( graphview ) ;
connect ( timer , SIGNAL ( timeout ( ) ) , SLOT ( timerDone ( ) ) ) ;
2011-09-05 10:28:41 +00:00
}
gToolTip : : ~ gToolTip ( )
{
2014-04-17 05:21:50 +00:00
disconnect ( timer , 0 , 0 , 0 ) ;
2011-09-05 10:28:41 +00:00
delete timer ;
}
2011-12-05 15:03:16 +00:00
//void gToolTip::calcSize(QString text,int &w, int &h)
//{
2014-04-17 05:21:50 +00:00
/*GetTextExtent(text,w,h);
w + = m_spacer * 2 ;
h + = m_spacer * 2 ; */
2011-12-05 15:03:16 +00:00
//}
2011-09-05 10:28:41 +00:00
2014-08-06 05:30:15 +00:00
void gToolTip : : display ( QString text , int x , int y , ToolTipAlignment align , int timeout )
2011-09-05 10:28:41 +00:00
{
2014-04-17 05:21:50 +00:00
if ( timeout < = 0 ) {
2018-04-22 12:06:48 +00:00
timeout = AppSetting - > tooltipTimeout ( ) ;
2014-04-17 05:21:50 +00:00
}
2014-08-06 05:30:15 +00:00
m_alignment = align ;
2013-10-26 13:59:37 +00:00
2014-04-17 05:21:50 +00:00
m_text = text ;
m_visible = true ;
2011-09-05 10:28:41 +00:00
// TODO: split multiline here
2011-12-05 08:32:46 +00:00
//calcSize(m_text,tw,th);
m_pos . setX ( x ) ;
m_pos . setY ( y ) ;
//tw+=m_spacer*2;
//th+=m_spacer*2;
2011-09-18 14:43:15 +00:00
//th*=2;
2011-09-05 10:28:41 +00:00
if ( timer - > isActive ( ) ) {
timer - > stop ( ) ;
}
2014-04-17 05:21:50 +00:00
2011-09-05 10:28:41 +00:00
timer - > setSingleShot ( true ) ;
timer - > start ( timeout ) ;
2014-04-17 05:21:50 +00:00
m_invalidate = true ;
2011-09-05 10:28:41 +00:00
}
void gToolTip : : cancel ( )
{
2014-04-17 05:21:50 +00:00
m_visible = false ;
2011-09-05 10:28:41 +00:00
timer - > stop ( ) ;
}
2014-05-07 19:52:59 +00:00
void gToolTip : : paint ( QPainter & painter ) //actually paints it.
2011-09-05 10:28:41 +00:00
{
2014-04-17 05:21:50 +00:00
if ( ! m_visible ) { return ; }
2013-01-18 10:03:10 +00:00
2014-04-17 05:21:50 +00:00
int x = m_pos . x ( ) ;
int y = m_pos . y ( ) ;
2011-09-05 10:28:41 +00:00
2014-04-23 17:20:38 +00:00
QRect rect ( x , y , 0 , 0 ) ;
2014-08-06 05:30:15 +00:00
2014-04-23 17:20:38 +00:00
painter . setFont ( * defaultfont ) ;
2013-10-25 15:25:13 +00:00
2014-04-23 17:20:38 +00:00
rect = painter . boundingRect ( rect , Qt : : AlignCenter , m_text ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
int w = rect . width ( ) + m_spacer * 2 ;
int xx = rect . x ( ) - m_spacer ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
if ( xx < 0 ) { xx = 0 ; }
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
rect . setLeft ( xx ) ;
2014-09-11 14:23:08 +00:00
rect . setTop ( rect . y ( ) - 15 ) ;
2014-04-23 17:20:38 +00:00
rect . setWidth ( w ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
int z = rect . x ( ) + rect . width ( ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
if ( z > m_graphview - > width ( ) - 10 ) {
rect . setLeft ( m_graphview - > width ( ) - 2 - rect . width ( ) ) ;
rect . setRight ( m_graphview - > width ( ) - 2 ) ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
int h = rect . height ( ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
if ( rect . y ( ) < 0 ) {
rect . setY ( 0 ) ;
rect . setHeight ( h ) ;
2014-04-17 05:21:50 +00:00
}
2014-08-06 05:30:15 +00:00
if ( m_alignment = = TT_AlignRight ) {
rect . moveTopRight ( m_pos ) ;
if ( ( x - w ) < 0 ) {
rect . moveLeft ( 0 ) ;
}
} else if ( m_alignment = = TT_AlignLeft ) {
rect . moveTopLeft ( m_pos ) ;
}
2014-04-23 17:20:38 +00:00
QBrush brush ( QColor ( 255 , 255 , 128 , 230 ) ) ;
brush . setStyle ( Qt : : SolidPattern ) ;
painter . setBrush ( brush ) ;
painter . setPen ( QColor ( 0 , 0 , 0 , 255 ) ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
painter . drawRoundedRect ( rect , 5 , 5 ) ;
painter . setBrush ( Qt : : black ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
painter . setFont ( * defaultfont ) ;
painter . drawText ( rect , Qt : : AlignCenter , m_text ) ;
2011-08-25 06:11:44 +00:00
}
2014-04-23 17:20:38 +00:00
void gToolTip : : timerDone ( )
2013-10-25 15:25:13 +00:00
{
2014-04-23 17:20:38 +00:00
m_visible = false ;
m_graphview - > redraw ( ) ;
2014-08-06 16:12:55 +00:00
m_graphview - > resetMouse ( ) ;
2014-04-23 17:20:38 +00:00
}
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
# ifdef ENABLE_THREADED_DRAWING
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
gThread : : gThread ( gGraphView * g )
{
graphview = g ;
mutex . lock ( ) ;
}
gThread : : ~ gThread ( )
{
if ( isRunning ( ) ) {
m_running = false ;
mutex . unlock ( ) ;
wait ( ) ;
terminate ( ) ;
2013-10-25 15:25:13 +00:00
}
}
2014-04-23 17:20:38 +00:00
void gThread : : run ( )
2013-10-25 15:25:13 +00:00
{
2014-04-23 17:20:38 +00:00
m_running = true ;
gGraph * g ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
while ( m_running ) {
mutex . lock ( ) ;
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
//mutex.unlock();
if ( ! m_running ) { break ; }
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
do {
g = graphview - > popGraph ( ) ;
if ( g ) {
2014-05-13 17:47:33 +00:00
g - > paint ( QRegion ( g - > m_lastbounds ) ) ;
2014-04-23 17:20:38 +00:00
//int i=0;
} else {
//mutex.lock();
graphview - > masterlock - > release ( 1 ) ; // This thread gives up for now..
2014-04-17 05:21:50 +00:00
}
2014-04-23 17:20:38 +00:00
} while ( g ) ;
2013-10-25 15:25:13 +00:00
}
2011-09-01 07:12:25 +00:00
}
2014-04-23 17:20:38 +00:00
# endif // ENABLE_THREADED_DRAWING
void gGraphView : : queGraph ( gGraph * g , int left , int top , int width , int height )
2011-09-01 07:12:25 +00:00
{
2014-04-23 17:20:38 +00:00
g - > m_rect = QRect ( left , top , width , height ) ;
# ifdef ENABLED_THREADED_DRAWING
dl_mutex . lock ( ) ;
# endif
m_drawlist . push_back ( g ) ;
# ifdef ENABLED_THREADED_DRAWING
dl_mutex . unlock ( ) ;
# endif
2011-09-01 07:12:25 +00:00
}
2014-05-07 19:52:59 +00:00
2014-09-11 14:23:08 +00:00
void gGraphView : : trashGraphs ( bool destroy )
2011-09-03 12:59:08 +00:00
{
2014-09-11 14:23:08 +00:00
if ( destroy ) {
for ( int i = 0 ; i < m_graphs . size ( ) ; + + i ) {
delete m_graphs [ i ] ;
}
}
2014-05-07 19:52:59 +00:00
// Don't actually want to delete them here.. we are just borrowing the graphs
2014-04-23 17:20:38 +00:00
m_graphs . clear ( ) ;
2014-07-16 17:12:52 +00:00
m_graphsbyname . clear ( ) ;
2011-09-03 12:59:08 +00:00
}
2014-05-07 19:52:59 +00:00
// Take the next graph to render from the drawing list
2014-04-23 17:20:38 +00:00
gGraph * gGraphView : : popGraph ( )
2011-12-27 13:21:10 +00:00
{
2014-04-23 17:20:38 +00:00
gGraph * g ;
# ifdef ENABLED_THREADED_DRAWING
dl_mutex . lock ( ) ;
# endif
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
if ( ! m_drawlist . isEmpty ( ) ) {
g = m_drawlist . at ( 0 ) ;
m_drawlist . pop_front ( ) ;
} else { g = nullptr ; }
2014-04-17 05:21:50 +00:00
2014-04-23 17:20:38 +00:00
# ifdef ENABLED_THREADED_DRAWING
dl_mutex . unlock ( ) ;
# endif
return g ;
2011-12-27 13:21:10 +00:00
}
2014-04-23 17:20:38 +00:00
gGraphView : : gGraphView ( QWidget * parent , gGraphView * shared )
2014-05-16 14:08:16 +00:00
# ifdef BROKEN_OPENGL_BUILD
2014-05-16 14:18:39 +00:00
: QWidget ( parent ) ,
2015-08-27 01:37:10 +00:00
# elif QT_VERSION < QT_VERSION_CHECK(5,4,0)
2014-05-16 14:08:16 +00:00
: QGLWidget ( QGLFormat ( QGL : : DoubleBuffer | QGL : : DirectRendering | QGL : : HasOverlay | QGL : : Rgba ) , parent , shared ) ,
2015-08-27 01:37:10 +00:00
# else
: QOpenGLWidget ( parent ) ,
2014-05-16 14:08:16 +00:00
# endif
2014-08-11 04:52:14 +00:00
m_offsetY ( 0 ) , m_offsetX ( 0 ) , m_scaleY ( 0.0 ) , m_scrollbar ( nullptr )
2011-08-25 06:11:44 +00:00
{
2015-08-27 09:46:05 +00:00
// this->grabGesture(Qt::SwipeGesture);
// this->grabGesture(Qt::PanGesture);
// this->grabGesture(Qt::TapGesture);
// this->grabGesture(Qt::TapAndHoldGesture);
// this->grabGesture(Qt::CustomGesture);
this - > grabGesture ( Qt : : PinchGesture ) ;
this - > setAttribute ( Qt : : WA_AcceptTouchEvents ) ;
// this->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
2014-04-17 05:21:50 +00:00
m_shared = shared ;
m_sizer_index = m_graph_index = 0 ;
2014-07-19 12:17:32 +00:00
m_metaselect = m_button_down = m_graph_dragging = m_sizer_dragging = false ;
2014-04-17 05:21:50 +00:00
m_lastypos = m_lastxpos = 0 ;
m_horiz_travel = 0 ;
m_minx = m_maxx = 0 ;
2014-04-23 13:19:56 +00:00
m_day = nullptr ;
m_selected_graph = nullptr ;
2014-05-25 07:07:08 +00:00
m_scrollbar = nullptr ;
2014-07-19 12:17:32 +00:00
m_point_released = m_point_clicked = QPoint ( 0 , 0 ) ;
2014-09-11 14:23:08 +00:00
m_showAuthorMessage = true ;
2013-01-18 20:18:25 +00:00
2013-11-09 00:59:35 +00:00
horizScrollTime . start ( ) ;
vertScrollTime . start ( ) ;
2011-08-25 06:11:44 +00:00
this - > setMouseTracking ( true ) ;
2014-08-21 08:04:25 +00:00
m_emptytext = STR_Empty_NoData ;
2014-04-23 17:20:38 +00:00
InitGraphGlobals ( ) ; // FIXME: sstangl: handle error return.
2011-10-30 07:08:18 +00:00
# ifdef ENABLE_THREADED_DRAWING
2014-04-17 05:21:50 +00:00
m_idealthreads = QThread : : idealThreadCount ( ) ;
if ( m_idealthreads < = 0 ) { m_idealthreads = 1 ; }
masterlock = new QSemaphore ( m_idealthreads ) ;
2011-10-30 07:08:18 +00:00
# endif
2014-04-17 05:21:50 +00:00
m_tooltip = new gToolTip ( this ) ;
2011-09-07 14:26:00 +00:00
/*for (int i=0;i<m_idealthreads;i++) {
2011-09-05 02:30:10 +00:00
gThread * gt = new gThread ( this ) ;
m_threads . push_back ( gt ) ;
2011-09-07 14:26:00 +00:00
//gt->start();
} */
2011-09-05 02:30:10 +00:00
2011-09-07 09:15:33 +00:00
setFocusPolicy ( Qt : : StrongFocus ) ;
2014-04-17 05:21:50 +00:00
m_showsplitter = true ;
timer = new QTimer ( this ) ;
connect ( timer , SIGNAL ( timeout ( ) ) , SLOT ( refreshTimeout ( ) ) ) ;
print_scaleY = print_scaleX = 1.0 ;
2011-12-19 18:49:35 +00:00
2014-04-17 05:21:50 +00:00
redrawtimer = new QTimer ( this ) ;
2014-05-16 14:08:16 +00:00
connect ( redrawtimer , SIGNAL ( timeout ( ) ) , SLOT ( redraw ( ) ) ) ;
2011-12-20 05:51:22 +00:00
2014-04-17 05:21:50 +00:00
m_fadingOut = false ;
m_fadingIn = false ;
m_inAnimation = false ;
m_limbo = false ;
m_fadedir = false ;
m_blockUpdates = false ;
2018-04-22 12:06:48 +00:00
use_pixmap_cache = AppSetting - > usePixmapCaching ( ) ;
2013-11-04 06:49:48 +00:00
2014-08-17 12:56:05 +00:00
pin_graph = nullptr ;
2018-05-03 05:08:45 +00:00
popout_graph = nullptr ;
2014-05-10 00:50:35 +00:00
// pixmapcache.setCacheLimit(10240*2);
2014-05-16 13:38:28 +00:00
m_dpr = devicePixelRatio ( ) ;
2018-05-05 07:14:44 +00:00
m_dpr = 1 ; // meh???
2014-05-16 13:38:28 +00:00
2014-05-16 14:08:16 +00:00
# ifndef BROKEN_OPENGL_BUILD
2014-05-16 13:38:28 +00:00
setAutoFillBackground ( false ) ;
2015-08-27 01:37:10 +00:00
# if QT_VERSION < QT_VERSION_CHECK(5,4,0)
// happens no matter what in 5.4+
2014-05-16 13:38:28 +00:00
setAutoBufferSwap ( false ) ;
2015-08-27 01:37:10 +00:00
# endif
2014-05-16 14:08:16 +00:00
# endif
2014-08-17 12:56:05 +00:00
context_menu = new QMenu ( this ) ;
pin_action = context_menu - > addAction ( QString ( ) , this , SLOT ( togglePin ( ) ) ) ;
pin_icon = QPixmap ( " :/icons/pushpin.png " ) ;
2014-08-27 13:42:10 +00:00
2018-05-03 05:08:45 +00:00
popout_action = context_menu - > addAction ( QObject : : tr ( " Pop out Graph " ) , this , SLOT ( popoutGraph ( ) ) ) ;
2014-08-27 13:42:10 +00:00
snap_action = context_menu - > addAction ( QString ( ) , this , SLOT ( onSnapshotGraphToggle ( ) ) ) ;
2014-08-17 12:56:05 +00:00
context_menu - > addSeparator ( ) ;
2014-08-27 09:55:31 +00:00
2014-08-27 15:00:55 +00:00
zoom100_action = context_menu - > addAction ( tr ( " 100% zoom level " ) , this , SLOT ( resetZoom ( ) ) ) ;
zoom100_action - > setToolTip ( tr ( " Restore X-axis zoom too 100% to view entire days data. " ) ) ;
QAction * action = context_menu - > addAction ( tr ( " Reset Graph Layout " ) , this , SLOT ( resetLayout ( ) ) ) ;
2014-08-27 09:55:31 +00:00
action - > setToolTip ( tr ( " Resets all graphs to a uniform height and default order. " ) ) ;
2014-08-17 12:56:05 +00:00
context_menu - > addSeparator ( ) ;
2014-08-26 17:26:13 +00:00
limits_menu = context_menu - > addMenu ( tr ( " Y-Axis " ) ) ;
2014-08-17 12:56:05 +00:00
plots_menu = context_menu - > addMenu ( tr ( " Plots " ) ) ;
connect ( plots_menu , SIGNAL ( triggered ( QAction * ) ) , this , SLOT ( onPlotsClicked ( QAction * ) ) ) ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
// overlay_menu = context_menu->addMenu("Overlays");
2014-08-20 18:36:44 +00:00
2014-08-23 06:21:50 +00:00
cpap_menu = context_menu - > addMenu ( tr ( " CPAP Overlays " ) ) ;
2014-08-20 18:36:44 +00:00
connect ( cpap_menu , SIGNAL ( triggered ( QAction * ) ) , this , SLOT ( onOverlaysClicked ( QAction * ) ) ) ;
2014-08-23 06:21:50 +00:00
oximeter_menu = context_menu - > addMenu ( tr ( " Oximeter Overlays " ) ) ;
2014-08-20 18:36:44 +00:00
connect ( oximeter_menu , SIGNAL ( triggered ( QAction * ) ) , this , SLOT ( onOverlaysClicked ( QAction * ) ) ) ;
2014-08-20 11:30:42 +00:00
2014-08-17 12:56:05 +00:00
lines_menu = context_menu - > addMenu ( tr ( " Dotted Lines " ) ) ;
connect ( lines_menu , SIGNAL ( triggered ( QAction * ) ) , this , SLOT ( onLinesClicked ( QAction * ) ) ) ;
2014-08-26 15:05:59 +00:00
2014-08-27 04:36:40 +00:00
# if !defined(Q_OS_MAC)
2014-08-26 18:23:27 +00:00
context_menu - > setStyleSheet ( " QMenu { \
2014-08-26 18:43:01 +00:00
background - color : # f0f0f0 ; /* sets background of the menu */ \
2014-08-26 18:23:27 +00:00
border : 1 px solid black ; \
} \
QMenu : : item { \
/* sets background of menu item. set this to something non-transparent\
if you want menu color and menu item color to be different */ \
2014-08-26 18:43:01 +00:00
background - color : # f0f0f0 ; \
2014-08-26 18:23:27 +00:00
} \
QMenu : : item : selected { /* when user selects item using mouse or keyboard */ \
background - color : # ABCDEF ; \
} " );
2014-08-27 04:36:40 +00:00
# else
context_menu - > setStyleSheet ( " QMenu::item:selected { /* when user selects item using mouse or keyboard */ \
background - color : # ABCDEF ; \
} " );
# endif
2014-08-17 12:56:05 +00:00
}
2018-05-03 05:08:45 +00:00
void MyDockWindow : : closeEvent ( QCloseEvent * event )
{
gGraphView : : dock - > deleteLater ( ) ;
gGraphView : : dock = nullptr ;
QMainWindow : : closeEvent ( event ) ;
}
MyDockWindow * gGraphView : : dock = nullptr ;
void gGraphView : : popoutGraph ( )
{
if ( popout_graph ) {
if ( dock = = nullptr ) {
dock = new MyDockWindow ( mainwin - > getDaily ( ) , Qt : : Window ) ;
dock - > resize ( width ( ) , 0 ) ;
// QScrollArea
}
QDockWidget * widget = new QDockWidget ( dock ) ;
widget - > setSizePolicy ( QSizePolicy : : Preferred , QSizePolicy : : Preferred ) ;
widget - > setMouseTracking ( true ) ;
int h = dock - > height ( ) + popout_graph - > height ( ) + 30 ;
if ( h > height ( ) ) h = height ( ) ;
dock - > resize ( dock - > width ( ) , h ) ;
widget - > resize ( width ( ) , popout_graph - > height ( ) + 30 ) ;
gGraphView * gv = new gGraphView ( widget , this ) ;
widget - > setWidget ( gv ) ;
gv - > setMouseTracking ( true ) ;
gv - > setDay ( this - > day ( ) ) ;
dock - > addDockWidget ( Qt : : BottomDockWidgetArea , widget , Qt : : Vertical ) ;
/////// Fix some resize glitches ///////
// https://stackoverflow.com/questions/26286646/create-a-qdockwidget-that-resizes-to-its-contents?rq=1
QDockWidget * dummy = new QDockWidget ;
dock - > addDockWidget ( Qt : : BottomDockWidgetArea , dummy ) ;
dock - > removeDockWidget ( dummy ) ;
QPoint mousePos = dock - > mapFromGlobal ( QCursor : : pos ( ) ) ;
mousePos . setY ( dock - > rect ( ) . bottom ( ) + 2 ) ;
QCursor : : setPos ( dock - > mapToGlobal ( mousePos ) ) ;
QMouseEvent * grabSeparatorEvent =
new QMouseEvent ( QMouseEvent : : MouseButtonPress , mousePos , Qt : : LeftButton , Qt : : LeftButton , Qt : : NoModifier ) ;
qApp - > postEvent ( dock , grabSeparatorEvent ) ;
/////////////////////////////////////////
// dock->updateGeometry();
if ( ! dock - > isVisible ( ) ) dock - > show ( ) ;
gGraph * graph = popout_graph ;
QString basename = graph - > title ( ) + " - " ;
if ( graph - > m_day ) {
// append the date of the graph's left edge to the snapshot name
// so the user knows what day the snapshot starts
// because the name is displayed to the user, use local time
QDateTime date = QDateTime : : fromMSecsSinceEpoch ( graph - > min_x , Qt : : LocalTime ) ;
basename + = date . date ( ) . toString ( Qt : : SystemLocaleLongDate ) ;
}
QString newname = basename ;
// Find a new name.. How many snapshots for each graph counts as stupid?
QString newtitle = graph - > title ( ) ;
widget - > setWindowTitle ( newname ) ;
gGraph * newgraph = new gGraph ( newname , nullptr , newtitle , graph - > units ( ) , graph - > height ( ) , graph - > group ( ) ) ;
newgraph - > setHeight ( graph - > height ( ) ) ;
short group = 0 ;
gv - > m_graphs . insert ( m_graphs . indexOf ( graph ) + 1 , newgraph ) ;
gv - > m_graphsbyname [ newname ] = newgraph ;
newgraph - > m_graphview = gv ;
for ( int i = 0 ; i < graph - > m_layers . size ( ) ; + + i ) {
Layer * layer = graph - > m_layers . at ( i ) - > Clone ( ) ;
if ( layer ) {
newgraph - > m_layers . append ( layer ) ;
}
}
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
gGraph * g = m_graphs . at ( i ) ;
group = qMax ( g - > group ( ) , group ) ;
}
newgraph - > setGroup ( group + 1 ) ;
//newgraph->setMinHeight(pm.height());
newgraph - > setDay ( graph - > m_day ) ;
if ( graph - > m_day ) {
graph - > m_day - > incUseCounter ( ) ;
}
newgraph - > min_x = graph - > min_x ;
newgraph - > max_x = graph - > max_x ;
newgraph - > setBlockSelect ( false ) ;
newgraph - > setZoomY ( graph - > zoomY ( ) ) ;
newgraph - > setSnapshot ( false ) ;
newgraph - > setShowTitle ( true ) ;
gv - > resetLayout ( ) ;
gv - > timedRedraw ( 0 ) ;
//widget->setUpdatesEnabled(true);
}
}
2014-08-17 12:56:05 +00:00
void gGraphView : : togglePin ( )
{
if ( pin_graph ) {
pin_graph - > setPinned ( ! pin_graph - > isPinned ( ) ) ;
timedRedraw ( 0 ) ;
}
2011-08-25 06:11:44 +00:00
}
2014-06-02 11:22:45 +00:00
2014-05-15 18:15:32 +00:00
void gGraphView : : closeEvent ( QCloseEvent * event )
2011-08-25 06:11:44 +00:00
{
2014-06-02 11:22:45 +00:00
2014-04-25 05:28:10 +00:00
timer - > stop ( ) ;
redrawtimer - > stop ( ) ;
disconnect ( redrawtimer , 0 , 0 , 0 ) ;
disconnect ( timer , 0 , 0 , 0 ) ;
2014-05-15 18:15:32 +00:00
timer - > deleteLater ( ) ;
redrawtimer - > deleteLater ( ) ;
pixmapcache . clear ( ) ;
if ( m_scrollbar ) {
this - > disconnect ( m_scrollbar , SIGNAL ( sliderMoved ( int ) ) , 0 , 0 ) ;
}
2014-06-02 11:22:45 +00:00
# ifdef BROKEN_OPENGL_BUILD
QWidget : : closeEvent ( event ) ;
2015-08-27 01:37:10 +00:00
# elif QT_VERSION < QT_VERSION_CHECK(5,4,0)
2014-06-02 11:22:45 +00:00
QGLWidget : : closeEvent ( event ) ;
2015-08-27 01:37:10 +00:00
# else
QOpenGLWidget : : closeEvent ( event ) ;
2014-06-02 11:22:45 +00:00
# endif
2014-05-15 18:15:32 +00:00
}
gGraphView : : ~ gGraphView ( )
{
2014-05-16 14:08:16 +00:00
# ifndef BROKEN_OPENGL_BUILD
doneCurrent ( ) ;
# endif
2014-04-25 05:28:10 +00:00
2011-10-30 07:08:18 +00:00
# ifdef ENABLE_THREADED_DRAWING
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_threads . size ( ) ; i + + ) {
2011-09-05 02:30:10 +00:00
delete m_threads [ i ] ;
}
2014-04-17 05:21:50 +00:00
2011-10-30 07:08:18 +00:00
delete masterlock ;
# endif
2013-09-09 15:56:02 +00:00
// Note: This will cause a crash if two graphs accidentally have the same name
2014-08-27 13:42:10 +00:00
for ( QList < gGraph * > : : iterator g = m_graphs . begin ( ) ; g ! = m_graphs . end ( ) ; + + g ) {
gGraph * graph = * g ;
delete graph ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-09-05 10:28:41 +00:00
delete m_tooltip ;
2011-08-25 06:11:44 +00:00
m_graphs . clear ( ) ;
}
2013-01-17 18:26:11 +00:00
2015-08-27 09:46:05 +00:00
bool gGraphView : : event ( QEvent * event )
{
if ( event - > type ( ) = = QEvent : : Gesture ) {
return gestureEvent ( static_cast < QGestureEvent * > ( event ) ) ;
}
return QWidget : : event ( event ) ;
}
bool gGraphView : : gestureEvent ( QGestureEvent * event )
{
if ( QGesture * pinch = event - > gesture ( Qt : : PinchGesture ) )
pinchTriggered ( static_cast < QPinchGesture * > ( pinch ) ) ;
return true ;
}
bool gGraphView : : pinchTriggered ( QPinchGesture * gesture )
{
gGraph * graph = nullptr ;
int group = 0 ;
if ( ! graph ) {
// just pick any graph then
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( ! m_graphs [ i ] ) continue ;
if ( ! m_graphs [ i ] - > isEmpty ( ) ) {
graph = m_graphs [ i ] ;
group = graph - > group ( ) ;
break ;
}
}
} else group = graph - > group ( ) ;
if ( ! graph ) { return true ; }
2018-03-28 06:22:42 +00:00
Q_UNUSED ( group )
2015-08-27 09:46:05 +00:00
//qDebug() << gesture << gesture->scaleFactor();
if ( gesture - > state ( ) = = Qt : : GestureStarted ) {
pinch_min = m_minx ;
pinch_max = m_maxx ;
}
int origin_px = gesture - > centerPoint ( ) . x ( ) - titleWidth ;
// could use this instead, and have it more dynamic
// graph->ZoomX(gesture->scaleFactor(), x);
static const double zoom_hard_limit = 500.0 ;
qint64 min = pinch_min ;
qint64 max = pinch_max ;
int width = graph - > m_rect . width ( ) - graph - > left - graph - > right ;
double hardspan = graph - > rmax_x - graph - > rmin_x ;
double span = max - min ;
double ww = double ( origin_px ) / double ( width ) ;
double origin = ww * span ;
double q = span * gesture - > scaleFactor ( ) ;
if ( q > hardspan ) { q = hardspan ; }
if ( q < hardspan / zoom_hard_limit ) { q = hardspan / zoom_hard_limit ; }
min = min + origin - ( q * ww ) ;
max = min + q ;
if ( min < graph - > rmin_x ) {
min = graph - > rmin_x ;
max = min + q ;
}
if ( max > graph - > rmax_x ) {
max = graph - > rmax_x ;
min = max - q ;
}
//extern const int max_history;
SetXBounds ( min , max , graph - > m_group ) ;
return true ;
}
2014-07-21 16:14:07 +00:00
void gGraphView : : dumpInfo ( )
{
2014-08-05 11:17:03 +00:00
QDate date = mainwin - > getDaily ( ) - > getDate ( ) ;
QString text = " ==================== CPAP Information Dump ==================== " ;
2014-07-21 16:14:07 +00:00
mainwin - > log ( text ) ;
2014-08-05 11:17:03 +00:00
Day * day = p_profile - > GetGoodDay ( date , MT_CPAP ) ;
if ( day ) {
2015-08-11 20:01:24 +00:00
QDateTime dt = QDateTime : : fromMSecsSinceEpoch ( day - > first ( ) , Qt : : UTC ) ;
2014-08-05 11:17:03 +00:00
mainwin - > log ( QString ( " Available Channels for %1 " ) . arg ( dt . toString ( " MMM dd yyyy " ) ) ) ;
QHash < schema : : ChanType , QList < schema : : Channel * > > list ;
for ( int i = 0 ; i < day - > size ( ) ; + + i ) {
Session * sess = day - > sessions . at ( i ) ;
QHash < ChannelID , QVector < EventList * > > : : iterator it ;
for ( it = sess - > eventlist . begin ( ) ; it ! = sess - > eventlist . end ( ) ; + + it ) {
ChannelID code = it . key ( ) ;
schema : : Channel * chan = & schema : : channel [ code ] ;
list [ chan - > type ( ) ] . append ( chan ) ;
}
}
QHash < schema : : ChanType , QList < schema : : Channel * > > : : iterator lit ;
for ( lit = list . begin ( ) ; lit ! = list . end ( ) ; + + lit ) {
switch ( lit . key ( ) ) {
case schema : : DATA :
text = " DATA: " ;
break ;
case schema : : SETTING :
text = " SETTING: " ;
break ;
case schema : : FLAG :
text = " FLAG: " ;
break ;
case schema : : MINOR_FLAG :
text = " MINOR_FLAG: " ;
break ;
case schema : : SPAN :
text = " SPAN: " ;
break ;
case schema : : WAVEFORM :
text = " WAVEFORM: " ;
break ;
2014-08-07 20:27:23 +00:00
case schema : : UNKNOWN :
text = " UNKNOWN: " ;
break ;
default :
break ;
2014-08-05 11:17:03 +00:00
}
QStringList str ;
for ( int i = 0 ; i < lit . value ( ) . size ( ) ; + + i ) {
str . append ( lit . value ( ) . at ( i ) - > code ( ) ) ;
}
str . sort ( ) ;
text . append ( str . join ( " , " ) ) ;
mainwin - > log ( text ) ;
}
2014-07-21 16:14:07 +00:00
}
2014-08-05 11:17:03 +00:00
// for (int i=0;i<m_graphs.size();i++) {
// m_graphs[i]->dumpInfo();
// }
2014-07-21 16:14:07 +00:00
}
2013-01-18 08:37:17 +00:00
bool gGraphView : : usePixmapCache ( )
{
//use_pixmap_cache is an overide setting
2018-04-22 12:06:48 +00:00
return AppSetting - > usePixmapCaching ( ) ;
2013-01-18 08:37:17 +00:00
}
2014-05-10 00:50:35 +00:00
# define CACHE_DRAWTEXT
# ifndef CACHE_DRAWTEXT
2014-05-07 19:52:59 +00:00
// Render all qued text via QPainter method
void gGraphView : : DrawTextQue ( QPainter & painter )
{
int w , h ;
2014-05-10 00:50:35 +00:00
// not sure if global antialiasing would be better..
2018-04-22 12:06:48 +00:00
//painter.setRenderHint(QPainter::TextAntialiasing, AppSetting->antiAliasing());
2014-08-12 10:44:05 +00:00
int items = m_textque . size ( ) ;
for ( int i = 0 ; i < items ; + + i ) {
2014-05-07 19:52:59 +00:00
TextQue & q = m_textque [ i ] ;
painter . setPen ( q . color ) ;
painter . setRenderHint ( QPainter : : TextAntialiasing , q . antialias ) ;
QFont font = * q . font ;
painter . setFont ( font ) ;
if ( q . angle = = 0 ) { // normal text
painter . drawText ( q . x , q . y , q . text ) ;
} else { // rotated text
w = painter . fontMetrics ( ) . width ( q . text ) ;
h = painter . fontMetrics ( ) . xHeight ( ) + 2 ;
2013-01-18 08:37:17 +00:00
2014-05-07 19:52:59 +00:00
painter . translate ( q . x , q . y ) ;
painter . rotate ( - q . angle ) ;
painter . drawText ( floor ( - w / 2.0 ) , floor ( - h / 2.0 ) , q . text ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - q . x , - q . y ) ;
}
2014-05-10 00:50:35 +00:00
strings_drawn_this_frame + + ;
2014-05-07 19:52:59 +00:00
q . text . clear ( ) ;
}
2014-05-10 00:50:35 +00:00
m_textque . clear ( ) ;
2014-08-12 10:44:05 +00:00
items = m_textqueRect . size ( ) ;
for ( int i = 0 ; i < items ; + + i ) {
TextQueRect & q = m_textqueRect [ i ] ;
painter . setPen ( q . color ) ;
painter . setRenderHint ( QPainter : : TextAntialiasing , q . antialias ) ;
QFont font = * q . font ;
painter . setFont ( font ) ;
if ( q . angle = = 0 ) { // normal text
painter . drawText ( q . rect , q . flags , q . text ) ;
} else { // rotated text
int x = q . rect . x ( ) ;
int y = q . rect . y ( ) ;
w = painter . fontMetrics ( ) . width ( q . text ) ;
h = painter . fontMetrics ( ) . xHeight ( ) + 2 ;
painter . translate ( x , y ) ;
painter . rotate ( - q . angle ) ;
painter . drawText ( floor ( - w / 2.0 ) , floor ( - h / 2.0 ) , q . text ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - x , - y ) ;
}
strings_drawn_this_frame + + ;
q . text . clear ( ) ;
}
m_textqueRect . clear ( ) ;
2014-05-07 19:52:59 +00:00
}
2014-05-10 00:50:35 +00:00
# else
2014-05-07 19:52:59 +00:00
// Render graphs with QPainter or pixmap caching, depending on preferences
2014-05-10 00:50:35 +00:00
void gGraphView : : DrawTextQue ( QPainter & painter )
2011-08-26 01:14:49 +00:00
{
2014-08-17 12:56:05 +00:00
{
// process the text drawing queue
int m_textque_items = m_textque . size ( ) ;
2013-11-04 03:40:08 +00:00
2014-08-17 12:56:05 +00:00
int h , w ;
2013-01-17 18:26:11 +00:00
2014-08-17 12:56:05 +00:00
for ( int i = 0 ; i < m_textque_items ; + + i ) {
const TextQue & q = m_textque . at ( i ) ;
2014-04-17 05:21:50 +00:00
2014-08-17 12:56:05 +00:00
// can do antialiased text via texture cache fine on mac
if ( usePixmapCache ( ) ) {
// Generate the pixmap cache "key"
QString hstr = QString ( " %1:%2:%3 " ) .
arg ( q . text ) .
arg ( q . color . name ( ) ) .
arg ( q . font - > pointSize ( ) ) ;
2013-01-17 18:26:11 +00:00
2014-08-17 12:56:05 +00:00
QPixmap pm ;
const int buf = 8 ;
if ( ! QPixmapCache : : find ( hstr , & pm ) ) {
2013-01-18 15:27:44 +00:00
2014-08-17 12:56:05 +00:00
QFontMetrics fm ( * q . font ) ;
// QRect rect=fm.tightBoundingRect(q.text);
w = fm . width ( q . text ) ;
h = fm . height ( ) + buf ;
2013-01-17 18:26:11 +00:00
2014-08-17 12:56:05 +00:00
pm = QPixmap ( w , h ) ;
pm . fill ( Qt : : transparent ) ;
2013-01-17 19:11:10 +00:00
2014-08-17 12:56:05 +00:00
QPainter imgpainter ( & pm ) ;
2014-04-17 05:21:50 +00:00
2014-08-17 12:56:05 +00:00
imgpainter . setPen ( q . color ) ;
2013-01-18 15:27:44 +00:00
2014-08-17 12:56:05 +00:00
imgpainter . setFont ( * q . font ) ;
2013-01-17 18:26:11 +00:00
2014-08-17 12:56:05 +00:00
imgpainter . setRenderHint ( QPainter : : TextAntialiasing , q . antialias ) ;
imgpainter . drawText ( 0 , h - buf , q . text ) ;
imgpainter . end ( ) ;
2013-01-17 18:26:11 +00:00
2014-08-17 12:56:05 +00:00
QPixmapCache : : insert ( hstr , pm ) ;
strings_drawn_this_frame + + ;
} else {
//cached
strings_cached_this_frame + + ;
}
2013-11-04 03:40:08 +00:00
2014-08-17 12:56:05 +00:00
h = pm . height ( ) ;
w = pm . width ( ) ;
if ( q . angle ! = 0 ) {
float xxx = q . x - h - ( h / 2 ) ;
float yyy = q . y + w / 2 ; // + buf / 2;
2013-11-04 03:40:08 +00:00
2014-08-17 12:56:05 +00:00
xxx + = 4 ;
yyy + = 4 ;
2011-09-11 13:58:26 +00:00
2014-08-17 12:56:05 +00:00
painter . translate ( xxx , yyy ) ;
painter . rotate ( - q . angle ) ;
painter . drawPixmap ( QRect ( 0 , h / 2 , w , h ) , pm ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - xxx , - yyy ) ;
} else {
QRect r1 ( q . x - buf / 2 + 4 , q . y - h + buf , w , h ) ;
painter . drawPixmap ( r1 , pm ) ;
}
2013-01-17 18:26:11 +00:00
} else {
2014-08-17 12:56:05 +00:00
// Just draw the fonts..
painter . setPen ( QColor ( q . color ) ) ;
2013-01-17 18:26:11 +00:00
painter . setFont ( * q . font ) ;
2013-11-04 03:40:08 +00:00
2014-08-17 12:56:05 +00:00
if ( q . angle = = 0 ) {
painter . drawText ( q . x , q . y , q . text ) ;
} else {
painter . setFont ( * q . font ) ;
w = painter . fontMetrics ( ) . width ( q . text ) ;
h = painter . fontMetrics ( ) . xHeight ( ) + 2 ;
painter . translate ( q . x , q . y ) ;
painter . rotate ( - q . angle ) ;
painter . drawText ( floor ( - w / 2.0 ) - 6 , floor ( - h / 2.0 ) , q . text ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - q . x , - q . y ) ;
}
strings_drawn_this_frame + + ;
2013-01-17 18:26:11 +00:00
2014-04-17 05:21:50 +00:00
}
2014-05-10 00:50:35 +00:00
2014-08-17 12:56:05 +00:00
//q.text.clear();
//q.text.squeeze();
2011-08-26 01:14:49 +00:00
}
2014-04-17 05:21:50 +00:00
2014-08-17 12:56:05 +00:00
m_textque . clear ( ) ;
2011-08-26 01:14:49 +00:00
}
2014-08-12 10:44:05 +00:00
////////////////////////////////////////////////////////////////////////
// Text Rectangle Queues..
////////////////////////////////////////////////////////////////////////
int items = m_textqueRect . size ( ) ;
float ww , hh ;
for ( int i = 0 ; i < items ; + + i ) {
2014-08-17 12:56:05 +00:00
const TextQueRect & q = m_textqueRect . at ( i ) ;
2014-08-12 10:44:05 +00:00
// can do antialiased text via texture cache fine on mac
if ( usePixmapCache ( ) ) {
// Generate the pixmap cache "key"
QString hstr = QString ( " %1:%2:%3 " ) .
arg ( q . text ) .
arg ( q . color . name ( ) ) .
arg ( q . font - > pointSize ( ) ) ;
QPixmap pm ;
if ( ! QPixmapCache : : find ( hstr , & pm ) ) {
ww = q . rect . width ( ) ;
hh = q . rect . height ( ) ;
pm = QPixmap ( ww , hh ) ;
2014-08-17 12:56:05 +00:00
2014-08-29 06:08:36 +00:00
//int aaw1 = pm.width();
2014-08-12 10:44:05 +00:00
pm . fill ( Qt : : transparent ) ;
QPainter imgpainter ( & pm ) ;
2014-08-29 06:08:36 +00:00
//int aaw2 = pm.width();
2014-08-12 10:44:05 +00:00
imgpainter . setPen ( q . color ) ;
imgpainter . setFont ( * q . font ) ;
imgpainter . setRenderHint ( QPainter : : Antialiasing , true ) ;
imgpainter . setRenderHint ( QPainter : : TextAntialiasing , true ) ;
QRectF rect ( 0 , 0 , ww , hh ) ;
imgpainter . drawText ( rect , q . flags , q . text ) ;
2014-08-29 06:08:36 +00:00
//int aaw3 = pm.width();
2014-08-12 10:44:05 +00:00
imgpainter . end ( ) ;
QPixmapCache : : insert ( hstr , pm ) ;
2014-08-29 06:08:36 +00:00
//int aaw4 = pm.width();
2014-08-12 10:44:05 +00:00
strings_drawn_this_frame + + ;
} else {
//cached
strings_cached_this_frame + + ;
}
hh = pm . height ( ) ;
ww = pm . width ( ) ;
if ( q . angle ! = 0 ) {
float xxx = q . rect . x ( ) - hh - ( hh / 2 ) ;
float yyy = q . rect . y ( ) + ww / 2 ; // + buf / 2;
xxx + = 4 ;
yyy + = 4 ;
painter . translate ( xxx , yyy ) ;
painter . rotate ( - q . angle ) ;
painter . drawPixmap ( QRect ( 0 , hh / 2 , ww , hh ) , pm ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - xxx , - yyy ) ;
} else {
2014-08-17 12:56:05 +00:00
//painter.drawPixmap(QPoint(q.rect.x(), q.rect.y()), pm);
painter . drawPixmap ( q . rect , pm , QRect ( 0 , 0 , ww , hh ) ) ;
2014-08-12 10:44:05 +00:00
}
} else {
// Just draw the fonts..
2014-09-30 10:16:33 +00:00
2014-08-12 10:44:05 +00:00
painter . setPen ( QColor ( q . color ) ) ;
painter . setFont ( * q . font ) ;
if ( q . angle = = 0 ) {
painter . drawText ( q . rect , q . flags , q . text ) ;
} else {
painter . setFont ( * q . font ) ;
2014-08-17 12:56:05 +00:00
ww = painter . fontMetrics ( ) . width ( q . text ) ;
hh = painter . fontMetrics ( ) . xHeight ( ) + 2 ;
2014-08-12 10:44:05 +00:00
painter . translate ( q . rect . x ( ) , q . rect . y ( ) ) ;
painter . rotate ( - q . angle ) ;
painter . drawText ( floor ( - ww / 2.0 ) , floor ( - hh / 2.0 ) , q . text ) ;
painter . rotate ( + q . angle ) ;
painter . translate ( - q . rect . x ( ) , - q . rect . y ( ) ) ;
}
strings_drawn_this_frame + + ;
}
//q.text.clear();
//q.text.squeeze();
}
m_textqueRect . clear ( ) ;
2011-08-26 01:14:49 +00:00
}
2014-05-10 00:50:35 +00:00
# endif
2011-08-26 01:14:49 +00:00
2014-08-17 12:56:05 +00:00
void gGraphView : : AddTextQue ( const QString & text , QRectF rect , quint32 flags , float angle , QColor color , QFont * font , bool antialias )
2014-08-12 10:44:05 +00:00
{
# ifdef ENABLED_THREADED_DRAWING
text_mutex . lock ( ) ;
# endif
m_textqueRect . append ( TextQueRect ( rect , flags , text , angle , color , font , antialias ) ) ;
# ifdef ENABLED_THREADED_DRAWING
text_mutex . unlock ( ) ;
# endif
}
void gGraphView : : AddTextQue ( const QString & text , short x , short y , float angle , QColor color , QFont * font , bool antialias )
2011-08-26 01:14:49 +00:00
{
2011-10-30 07:08:18 +00:00
# ifdef ENABLED_THREADED_DRAWING
2011-08-31 14:28:19 +00:00
text_mutex . lock ( ) ;
2011-10-30 07:08:18 +00:00
# endif
2014-05-10 00:50:35 +00:00
m_textque . append ( TextQue ( x , y , angle , text , color , font , antialias ) ) ;
2011-10-30 07:08:18 +00:00
# ifdef ENABLED_THREADED_DRAWING
2011-08-31 14:28:19 +00:00
text_mutex . unlock ( ) ;
2011-10-30 07:08:18 +00:00
# endif
2011-08-30 17:22:54 +00:00
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : addGraph ( gGraph * g , short group )
2011-08-25 06:11:44 +00:00
{
2011-09-10 16:27:07 +00:00
if ( ! g ) {
qDebug ( ) < < " Attempted to add an empty graph! " ;
return ;
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
if ( ! m_graphs . contains ( g ) ) {
2011-08-26 03:26:53 +00:00
g - > setGroup ( group ) ;
2011-08-25 06:11:44 +00:00
m_graphs . push_back ( g ) ;
2014-04-17 05:21:50 +00:00
2014-07-16 17:12:52 +00:00
if ( ! m_graphsbyname . contains ( g - > name ( ) ) ) {
m_graphsbyname [ g - > name ( ) ] = g ;
2011-11-27 16:07:28 +00:00
} else {
2014-08-11 04:52:14 +00:00
qDebug ( ) < < " Can't have two graphs with the same code string in the same GraphView!! " ;
2011-11-27 16:07:28 +00:00
}
2014-04-17 05:21:50 +00:00
// updateScrollBar();
2011-08-25 06:11:44 +00:00
}
}
2014-05-07 19:52:59 +00:00
// Calculate total height of all graphs including spacers
2011-08-25 06:11:44 +00:00
float gGraphView : : totalHeight ( )
{
2014-04-17 05:21:50 +00:00
float th = 0 ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-11 04:52:14 +00:00
gGraph * g = m_graphs [ i ] ;
if ( g - > isEmpty ( ) | | ( ! g - > visible ( ) ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
th + = g - > height ( ) + graphSpacer ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
return ceil ( th ) ;
}
2014-05-07 19:52:59 +00:00
2014-04-17 05:21:50 +00:00
float gGraphView : : findTop ( gGraph * graph )
2011-08-25 06:11:44 +00:00
{
2014-04-17 05:21:50 +00:00
float th = - m_offsetY ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( m_graphs [ i ] = = graph ) { break ; }
if ( m_graphs [ i ] - > isEmpty ( ) | | ( ! m_graphs [ i ] - > visible ( ) ) ) { continue ; }
th + = m_graphs [ i ] - > height ( ) * m_scaleY + graphSpacer ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
return ceil ( th ) ;
}
2014-05-07 19:52:59 +00:00
2011-08-25 06:11:44 +00:00
float gGraphView : : scaleHeight ( )
{
2014-04-17 05:21:50 +00:00
float th = 0 ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( m_graphs [ i ] - > isEmpty ( ) | | ( ! m_graphs [ i ] - > visible ( ) ) ) { continue ; }
2011-08-25 06:11:44 +00:00
th + = m_graphs [ i ] - > height ( ) * m_scaleY + graphSpacer ;
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
return ceil ( th ) ;
}
2014-05-07 19:52:59 +00:00
2014-05-26 03:48:22 +00:00
void gGraphView : : updateScale ( )
{
2014-08-11 04:52:14 +00:00
if ( ! isVisible ( ) ) {
m_scaleY = 0.0 ;
return ;
}
2014-05-26 03:48:22 +00:00
float th = totalHeight ( ) ; // height of all graphs
float h = height ( ) ; // height of main widget
2014-08-11 04:52:14 +00:00
2014-05-26 03:48:22 +00:00
if ( th < h ) {
2014-09-11 14:23:08 +00:00
th - = graphSpacer ;
// th -= visibleGraphs() * graphSpacer; // compensate for spacer height
2014-05-26 03:48:22 +00:00
m_scaleY = h / th ; // less graphs than fits on screen, so scale to fit
} else {
m_scaleY = 1.0 ;
}
updateScrollBar ( ) ;
}
2011-08-25 06:11:44 +00:00
void gGraphView : : resizeEvent ( QResizeEvent * e )
{
2018-05-05 07:14:44 +00:00
# if (QT_VERSION >= QT_VERSION_CHECK(5,4,0)) && !defined(BROKEN_OPENGL_BUILD)
2015-08-27 01:37:10 +00:00
// This ques a needed redraw event..
QOpenGLWidget : : resizeEvent ( e ) ;
# endif
2011-08-25 06:11:44 +00:00
updateScale ( ) ;
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( m_scaleY > 0.0001 ) {
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
m_graphs [ i ] - > resize ( e - > size ( ) . width ( ) , m_graphs [ i ] - > height ( ) * m_scaleY ) ;
}
2011-08-25 06:11:44 +00:00
}
2014-08-11 04:52:14 +00:00
e - > accept ( ) ;
2011-08-25 06:11:44 +00:00
}
2014-05-07 19:52:59 +00:00
2011-08-25 06:11:44 +00:00
void gGraphView : : scrollbarValueChanged ( int val )
{
//qDebug() << "Scrollbar Changed" << val;
2014-04-17 05:21:50 +00:00
if ( m_offsetY ! = val ) {
m_offsetY = val ;
2015-08-27 01:37:10 +00:00
# if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
update ( ) ;
# else
2014-08-29 04:02:16 +00:00
timedRedraw ( ) ; // do this on a timer?
2015-08-27 01:37:10 +00:00
# endif
2011-08-26 04:15:15 +00:00
}
2011-08-25 06:11:44 +00:00
}
2011-12-27 13:21:10 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : GetRXBounds ( qint64 & st , qint64 & et )
2012-01-03 16:29:35 +00:00
{
2012-01-06 16:07:54 +00:00
//qint64 m1=0,m2=0;
2014-04-23 13:19:56 +00:00
gGraph * g = nullptr ;
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
g = m_graphs [ i ] ;
if ( g - > group ( ) = = 0 ) {
2012-01-03 16:29:35 +00:00
break ;
2014-04-17 05:21:50 +00:00
}
2012-01-03 16:29:35 +00:00
}
2018-03-28 06:22:42 +00:00
if ( g ) {
st = g - > rmin_x ;
et = g - > rmax_x ;
}
2012-01-03 16:29:35 +00:00
}
2014-05-07 19:52:59 +00:00
2011-09-03 15:54:27 +00:00
void gGraphView : : ResetBounds ( bool refresh ) //short group)
2011-08-25 06:11:44 +00:00
{
2014-09-11 14:23:08 +00:00
if ( m_graphs . size ( ) = = 0 ) return ;
2011-10-21 05:50:31 +00:00
Q_UNUSED ( refresh )
2014-04-17 05:21:50 +00:00
qint64 m1 = 0 , m2 = 0 ;
2014-04-23 13:19:56 +00:00
gGraph * g = nullptr ;
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2011-10-07 05:28:35 +00:00
m_graphs [ i ] - > ResetBounds ( ) ;
2014-04-17 05:21:50 +00:00
if ( ! m_graphs [ i ] - > min_x ) { continue ; }
g = m_graphs [ i ] ;
if ( ! m1 | | m_graphs [ i ] - > min_x < m1 ) { m1 = m_graphs [ i ] - > min_x ; }
if ( ! m2 | | m_graphs [ i ] - > max_x > m2 ) { m2 = m_graphs [ i ] - > max_x ; }
2011-10-07 05:28:35 +00:00
}
2014-08-28 08:01:25 +00:00
// if (p_profile->general->linkGroups()) {
// for (int i = 0; i < m_graphs.size(); i++) {
// m_graphs[i]->SetMinX(m1);
// m_graphs[i]->SetMaxX(m2);
// }
// }
2011-11-27 23:10:16 +00:00
2014-09-11 14:23:08 +00:00
if ( ! g ) {
g = m_graphs [ 0 ] ;
}
2014-04-17 05:21:50 +00:00
m_minx = g - > min_x ;
m_maxx = g - > max_x ;
2011-12-02 11:40:47 +00:00
2011-08-25 06:11:44 +00:00
updateScale ( ) ;
}
2014-05-07 19:52:59 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : GetXBounds ( qint64 & st , qint64 & et )
2011-12-02 11:40:47 +00:00
{
2014-04-17 05:21:50 +00:00
st = m_minx ;
et = m_maxx ;
2011-12-02 11:40:47 +00:00
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : SetXBounds ( qint64 minx , qint64 maxx , short group , bool refresh )
2011-08-25 06:11:44 +00:00
{
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-28 08:01:25 +00:00
if ( ( m_graphs [ i ] - > group ( ) = = group ) ) {
2014-04-17 05:21:50 +00:00
m_graphs [ i ] - > SetXBounds ( minx , maxx ) ;
2011-10-07 05:28:35 +00:00
}
2011-08-25 06:11:44 +00:00
}
2011-12-02 11:40:47 +00:00
2014-04-17 05:21:50 +00:00
m_minx = minx ;
m_maxx = maxx ;
2014-09-11 14:23:08 +00:00
if ( refresh ) { timedRedraw ( 0 ) ; }
2011-08-25 06:11:44 +00:00
}
2014-05-07 19:52:59 +00:00
2011-08-25 06:11:44 +00:00
void gGraphView : : updateScrollBar ( )
{
2014-04-26 09:54:08 +00:00
if ( ! m_scrollbar | | ( m_graphs . size ( ) = = 0 ) ) {
return ;
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
float th = scaleHeight ( ) ; // height of all graphs
float h = height ( ) ; // height of main widget
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
float vis = 0 ;
2011-08-25 06:11:44 +00:00
2014-04-26 09:54:08 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
vis + = ( m_graphs [ i ] - > isEmpty ( ) | | ! m_graphs [ i ] - > visible ( ) ) ? 0 : 1 ;
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( th < h ) { // less graphs than fits on screen
2011-08-25 06:11:44 +00:00
m_scrollbar - > setMaximum ( 0 ) ; // turn scrollbar off.
} else { // more graphs than fit on screen
//m_scaleY=1.0;
2014-04-17 05:21:50 +00:00
float avgheight = th / vis ;
2011-08-25 06:11:44 +00:00
m_scrollbar - > setPageStep ( avgheight ) ;
2014-04-17 05:21:50 +00:00
m_scrollbar - > setSingleStep ( avgheight / 8.0 ) ;
m_scrollbar - > setMaximum ( th - height ( ) ) ;
if ( m_offsetY > th - height ( ) ) {
m_offsetY = th - height ( ) ;
2011-08-25 06:11:44 +00:00
}
}
}
void gGraphView : : setScrollBar ( MyScrollBar * sb )
{
2014-04-17 05:21:50 +00:00
m_scrollbar = sb ;
2011-08-25 06:11:44 +00:00
m_scrollbar - > setMinimum ( 0 ) ;
updateScrollBar ( ) ;
2014-04-17 05:21:50 +00:00
this - > connect ( m_scrollbar , SIGNAL ( valueChanged ( int ) ) , SLOT ( scrollbarValueChanged ( int ) ) ) ;
2011-08-25 06:11:44 +00:00
}
2011-12-19 17:51:25 +00:00
2014-05-07 19:52:59 +00:00
bool gGraphView : : renderGraphs ( QPainter & painter )
2011-08-25 06:11:44 +00:00
{
2014-04-17 05:21:50 +00:00
float px = m_offsetX ;
float py = - m_offsetY ;
int numgraphs = 0 ;
float h , w ;
2011-08-25 06:11:44 +00:00
//ax=px;//-m_offsetX;
2011-10-21 05:50:31 +00:00
//bool threaded;
2011-09-01 09:03:23 +00:00
// Tempory hack using this pref..
2014-04-17 05:21:50 +00:00
//#ifdef ENABLED_THREADED_DRAWING
2011-12-21 12:47:47 +00:00
/*if (profile->session->multithreading()) { // && (m_idealthreads>1)) {
2011-08-31 11:44:53 +00:00
threaded = true ;
2011-09-07 14:26:00 +00:00
for ( int i = 0 ; i < m_idealthreads ; i + + ) {
2011-09-05 02:30:10 +00:00
if ( ! m_threads [ i ] - > isRunning ( ) )
m_threads [ i ] - > start ( ) ;
2011-09-07 14:26:00 +00:00
}
} else threaded = false ; */
2011-10-30 07:08:18 +00:00
//#endif
2011-10-21 05:50:31 +00:00
//threaded=false;
2014-08-11 04:52:14 +00:00
if ( height ( ) < 40 ) return false ;
2014-04-05 01:28:07 +00:00
2014-08-11 04:52:14 +00:00
if ( m_scaleY < 0.0000001 ) {
updateScale ( ) ;
}
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
lines_drawn_this_frame = 0 ;
quads_drawn_this_frame = 0 ;
2014-04-05 01:28:07 +00:00
// Calculate the height of pinned graphs
2014-04-17 05:21:50 +00:00
float pinned_height = 0 ; // pixel height total
int pinned_graphs = 0 ; // count
2014-08-11 04:52:14 +00:00
gGraph * g = nullptr ;
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-11 04:52:14 +00:00
g = m_graphs [ i ] ;
int minh = g - > minHeight ( ) ;
if ( g - > height ( ) < minh ) {
g - > setHeight ( minh ) ;
2014-08-09 17:12:37 +00:00
}
2014-08-11 04:52:14 +00:00
if ( g - > isEmpty ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( ! g - > visible ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( ! g - > isPinned ( ) ) { continue ; }
2014-04-05 01:28:07 +00:00
2014-08-11 04:52:14 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-17 05:21:50 +00:00
pinned_height + = h + graphSpacer ;
2014-04-05 01:28:07 +00:00
pinned_graphs + + ;
}
2014-04-17 05:21:50 +00:00
py + = pinned_height ; // start drawing at the end of pinned space
2014-04-05 01:28:07 +00:00
// Draw non pinned graphs
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-11 04:52:14 +00:00
g = m_graphs [ i ] ;
if ( g - > isEmpty ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( ! g - > visible ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( g - > isPinned ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2011-08-29 07:13:58 +00:00
numgraphs + + ;
2014-08-11 04:52:14 +00:00
h = g - > height ( ) * m_scaleY ;
2011-08-25 06:11:44 +00:00
// set clipping?
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2011-08-25 06:11:44 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
2014-04-17 05:21:50 +00:00
w = width ( ) ;
2014-08-27 13:42:10 +00:00
int tw = 0 ; // (g->showTitle() ? titleWidth : 0);
2011-12-25 05:05:12 +00:00
2014-08-11 04:52:14 +00:00
queGraph ( g , px + tw , py , width ( ) - tw , h ) ;
2011-08-30 17:22:54 +00:00
2014-05-25 16:20:33 +00:00
if ( ( m_graphs . size ( ) > 1 ) & & m_showsplitter ) {
2011-09-10 14:17:45 +00:00
// draw the splitter handle
2014-07-30 17:14:28 +00:00
2014-05-17 12:20:06 +00:00
painter . setPen ( QColor ( 220 , 220 , 220 , 255 ) ) ;
2014-07-30 17:14:28 +00:00
painter . drawLine ( 0 , py + h , w , py + h ) ;
painter . setPen ( QColor ( 158 , 158 , 158 , 255 ) ) ;
2014-05-07 19:52:59 +00:00
painter . drawLine ( 0 , py + h + 1 , w , py + h + 1 ) ;
2014-07-30 17:14:28 +00:00
painter . setPen ( QColor ( 240 , 240 , 240 , 255 ) ) ;
2014-05-07 19:52:59 +00:00
painter . drawLine ( 0 , py + h + 2 , w , py + h + 2 ) ;
2014-07-30 17:14:28 +00:00
2011-09-10 14:17:45 +00:00
}
2011-09-01 09:03:23 +00:00
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
py = ceil ( py + h + graphSpacer ) ;
2011-08-25 06:11:44 +00:00
}
2011-09-05 02:30:10 +00:00
2014-04-05 01:28:07 +00:00
// Physically draw the unpinned graphs
2014-04-17 05:21:50 +00:00
int s = m_drawlist . size ( ) ;
for ( int i = 0 ; i < s ; i + + ) {
2014-08-11 04:52:14 +00:00
g = m_drawlist . at ( 0 ) ;
2014-04-05 01:28:07 +00:00
m_drawlist . pop_front ( ) ;
2014-05-13 17:47:33 +00:00
g - > paint ( painter , QRegion ( g - > m_rect ) ) ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
if ( m_graphs . size ( ) > 1 ) {
2014-05-07 19:52:59 +00:00
DrawTextQue ( painter ) ;
2014-04-05 01:28:07 +00:00
2014-04-05 02:30:08 +00:00
// Draw a gradient behind pinned graphs
2014-05-07 19:52:59 +00:00
QLinearGradient linearGrad ( QPointF ( 100 , 100 ) , QPointF ( width ( ) / 2 , 100 ) ) ;
linearGrad . setColorAt ( 0 , QColor ( 216 , 216 , 255 ) ) ;
linearGrad . setColorAt ( 1 , Qt : : white ) ;
painter . fillRect ( 0 , 0 , width ( ) , pinned_height , QBrush ( linearGrad ) ) ;
2014-04-05 02:30:08 +00:00
}
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
py = 0 ; // start drawing at top...
2014-04-05 01:28:07 +00:00
// Draw Pinned graphs
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-11 04:52:14 +00:00
g = m_graphs [ i ] ;
if ( g - > isEmpty ( ) ) { continue ; }
2014-04-07 10:18:18 +00:00
2014-08-11 04:52:14 +00:00
if ( ! g - > visible ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( ! g - > isPinned ( ) ) { continue ; }
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-05 01:28:07 +00:00
numgraphs + + ;
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2014-04-05 01:28:07 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
2014-04-17 05:21:50 +00:00
w = width ( ) ;
2014-08-27 13:42:10 +00:00
int tw = 0 ; //(g->showTitle() ? titleWidth : 0);
2014-04-05 01:28:07 +00:00
2014-08-11 04:52:14 +00:00
queGraph ( g , px + tw , py , width ( ) - tw , h ) ;
2014-04-05 01:28:07 +00:00
2014-05-25 16:20:33 +00:00
if ( ( m_graphs . size ( ) > 1 ) & & m_showsplitter ) {
2014-04-05 01:28:07 +00:00
// draw the splitter handle
2014-05-17 12:20:06 +00:00
painter . setPen ( QColor ( 220 , 220 , 220 , 255 ) ) ;
2014-05-07 19:52:59 +00:00
painter . drawLine ( 0 , py + h , w , py + h ) ;
2014-05-17 12:20:06 +00:00
painter . setPen ( QColor ( 128 , 128 , 128 , 255 ) ) ;
2014-05-07 19:52:59 +00:00
painter . drawLine ( 0 , py + h + 1 , w , py + h + 1 ) ;
2014-05-17 12:20:06 +00:00
painter . setPen ( QColor ( 190 , 190 , 190 , 255 ) ) ;
2014-05-07 19:52:59 +00:00
painter . drawLine ( 0 , py + h + 2 , w , py + h + 2 ) ;
2014-04-05 01:28:07 +00:00
}
}
2014-04-17 05:21:50 +00:00
py = ceil ( py + h + graphSpacer ) ;
2014-04-05 01:28:07 +00:00
}
2011-09-05 02:30:10 +00:00
//int thr=m_idealthreads;
2011-10-30 07:08:18 +00:00
# ifdef ENABLED_THREADED_DRAWING
2014-04-26 09:54:08 +00:00
if ( threaded ) {
for ( int i = 0 ; i < m_idealthreads ; i + + ) {
masterlock - > acquire ( 1 ) ;
m_threads [ i ] - > mutex . unlock ( ) ;
}
2011-09-05 02:30:10 +00:00
2014-04-26 09:54:08 +00:00
// wait till all the threads are done
// ask for all the CPU's back..
masterlock - > acquire ( m_idealthreads ) ;
masterlock - > release ( m_idealthreads ) ;
} else {
2011-10-30 07:08:18 +00:00
# endif
2014-04-26 09:54:08 +00:00
s = m_drawlist . size ( ) ;
2014-04-17 05:21:50 +00:00
2014-04-26 09:54:08 +00:00
for ( int i = 0 ; i < s ; i + + ) {
2014-08-11 04:52:14 +00:00
g = m_drawlist . at ( 0 ) ;
2014-04-26 09:54:08 +00:00
m_drawlist . pop_front ( ) ;
2014-05-13 17:47:33 +00:00
g - > paint ( painter , QRegion ( g - > m_rect ) ) ;
2014-04-26 09:54:08 +00:00
}
2014-04-17 05:21:50 +00:00
# ifdef ENABLED_THREADED_DRAWING
2014-04-26 09:54:08 +00:00
}
2011-10-30 07:08:18 +00:00
# endif
2014-04-26 09:54:08 +00:00
//int elapsed=time.elapsed();
//QColor col=Qt::black;
2011-09-01 09:03:23 +00:00
2014-04-26 09:54:08 +00:00
// lines->setSize(linesize);
2011-12-20 07:17:09 +00:00
2014-05-08 01:04:37 +00:00
DrawTextQue ( painter ) ;
2014-04-26 09:54:08 +00:00
//glDisable(GL_TEXTURE_2D);
//glDisable(GL_DEPTH_TEST);
2011-12-20 07:17:09 +00:00
2014-04-26 09:54:08 +00:00
return numgraphs > 0 ;
2011-12-20 07:17:09 +00:00
}
2011-12-20 11:12:52 +00:00
2014-08-21 08:04:25 +00:00
# include "version.h"
2014-05-16 14:18:39 +00:00
# ifdef BROKEN_OPENGL_BUILD
void gGraphView : : paintEvent ( QPaintEvent * )
# else
2014-05-16 13:38:28 +00:00
void gGraphView : : paintGL ( )
2014-05-16 14:18:39 +00:00
# endif
2011-12-20 07:17:09 +00:00
{
2014-08-11 04:52:14 +00:00
if ( ! isVisible ( ) ) {
// wtf is this even getting CALLED??
return ;
}
2012-01-05 06:54:07 +00:00
# ifdef DEBUG_EFFICIENCY
QElapsedTimer time ;
2011-12-20 07:17:09 +00:00
time . start ( ) ;
2012-01-05 06:54:07 +00:00
# endif
2011-12-20 07:17:09 +00:00
if ( redrawtimer - > isActive ( ) ) {
redrawtimer - > stop ( ) ;
}
2011-12-20 11:12:52 +00:00
2014-07-11 12:09:38 +00:00
bool render_cube = false ; //p_profile->appearance->animations(); // do something to
2014-05-08 05:02:03 +00:00
2014-04-17 05:21:50 +00:00
if ( width ( ) < = 0 ) { return ; }
if ( height ( ) < = 0 ) { return ; }
2014-08-19 14:04:29 +00:00
2014-05-07 19:52:59 +00:00
// Create QPainter object, note this is only valid from paintGL events!
QPainter painter ( this ) ;
2015-08-27 04:00:58 +00:00
painter . setRenderHint ( QPainter : : HighQualityAntialiasing , true ) ;
2014-04-17 05:21:50 +00:00
2014-08-19 14:04:29 +00:00
painter . setRenderHint ( QPainter : : TextAntialiasing , true ) ;
2014-05-07 19:52:59 +00:00
QRect bgrect ( 0 , 0 , width ( ) , height ( ) ) ;
painter . fillRect ( bgrect , QBrush ( QColor ( 255 , 255 , 255 ) ) ) ;
2011-12-20 07:17:09 +00:00
2014-05-07 19:52:59 +00:00
bool graphs_drawn = true ;
2012-01-09 17:06:03 +00:00
2014-05-10 00:50:35 +00:00
lines_drawn_this_frame = 0 ;
quads_drawn_this_frame = 0 ;
strings_drawn_this_frame = 0 ;
strings_cached_this_frame = 0 ;
2014-05-07 19:52:59 +00:00
graphs_drawn = renderGraphs ( painter ) ;
2012-01-09 17:06:03 +00:00
2014-08-21 08:04:25 +00:00
if ( ! graphs_drawn ) { // No graphs drawn? show something useful :)
2014-09-11 14:23:08 +00:00
QString txt ;
if ( m_showAuthorMessage ) {
if ( emptyText ( ) = = STR_Empty_Brick ) {
2018-05-03 05:08:45 +00:00
txt = QObject : : tr ( " \n I'm very sorry your machine doesn't record useful data to graph in Daily View :( " ) ;
2014-09-11 14:23:08 +00:00
} else {
// not proud of telling them their machine is a Brick.. ;)
txt = QObject : : tr ( " SleepyHead is proudly brought to you by JediMark. " ) ;
}
2014-09-04 02:17:59 +00:00
}
2014-08-21 14:16:23 +00:00
// int x2, y2;
// GetTextExtent(m_emptytext, x2, y2, bigfont);
// int tp2, tp1;
2011-12-20 07:17:09 +00:00
2014-08-21 08:04:25 +00:00
if ( ! m_emptyimage . isNull ( ) ) {
painter . drawPixmap ( width ( ) / 2 - m_emptyimage . width ( ) / 2 , height ( ) / 2 - m_emptyimage . height ( ) / 2 , m_emptyimage ) ;
2014-08-21 14:16:23 +00:00
// tp2 = height() /2 + m_emptyimage.height()/2 + y2;
2011-12-20 17:22:02 +00:00
2014-08-21 14:16:23 +00:00
} /*else {
2014-04-17 05:21:50 +00:00
2014-08-21 08:04:25 +00:00
tp2 = height ( ) / 2 + y2 ;
2014-08-21 14:16:23 +00:00
} */
2014-05-07 19:52:59 +00:00
QColor col = Qt : : black ;
2014-08-21 08:04:25 +00:00
painter . setPen ( col ) ;
2014-08-21 14:16:23 +00:00
// painter.setFont(*bigfont);
// painter.drawText((width() / 2) - x2 / 2, tp2, m_emptytext);
2014-08-21 08:04:25 +00:00
QRectF rec ( 0 , 0 , width ( ) , 0 ) ;
painter . setFont ( * defaultfont ) ;
rec = painter . boundingRect ( rec , Qt : : AlignHCenter | Qt : : AlignBottom , txt ) ;
rec . moveBottom ( height ( ) - 5 ) ;
painter . drawText ( rec , Qt : : AlignHCenter | Qt : : AlignBottom , txt ) ;
2014-08-21 14:16:23 +00:00
}
2018-04-22 12:06:48 +00:00
if ( AppSetting - > lineCursorMode ( ) ) {
2014-08-27 09:00:55 +00:00
emit updateCurrentTime ( graphs_drawn ? m_currenttime : 0.0F ) ;
2014-08-21 14:16:23 +00:00
} else {
2014-08-27 09:00:55 +00:00
emit updateRange ( graphs_drawn ? m_minx : 0.0F , m_maxx ) ;
2011-12-20 07:17:09 +00:00
}
2014-05-07 19:52:59 +00:00
DrawTextQue ( painter ) ;
2014-04-17 05:21:50 +00:00
2014-05-07 19:52:59 +00:00
m_tooltip - > paint ( painter ) ;
2011-12-20 07:17:09 +00:00
2012-01-05 06:54:07 +00:00
# ifdef DEBUG_EFFICIENCY
2014-04-17 05:21:50 +00:00
const int rs = 10 ;
static double ring [ rs ] = { 0 } ;
static int rp = 0 ;
2012-01-05 15:17:50 +00:00
2011-12-20 07:17:09 +00:00
// Show FPS and draw time
2018-04-22 12:06:48 +00:00
if ( m_showsplitter & & AppSetting - > showPerformance ( ) ) {
2011-09-03 05:01:55 +00:00
QString ss ;
2014-04-17 05:21:50 +00:00
qint64 ela = time . nsecsElapsed ( ) ;
double ms = double ( ela ) / 1000000.0 ;
ring [ rp + + ] = 1000.0 / ms ;
2012-01-05 15:17:50 +00:00
rp % = rs ;
2014-04-17 05:21:50 +00:00
double v = 0 ;
for ( int i = 0 ; i < rs ; i + + ) {
v + = ring [ i ] ;
2012-01-05 15:17:50 +00:00
}
2014-04-17 05:21:50 +00:00
double fps = v / double ( rs ) ;
2014-05-10 00:50:35 +00:00
ss = " Debug Mode " + QString : : number ( fps , ' f ' , 1 ) + " fps "
+ QString : : number ( lines_drawn_this_frame , ' f ' , 0 ) + " lines "
// + QString::number(quads_drawn_this_frame, 'f', 0) + " quads "
+ QString : : number ( strings_drawn_this_frame , ' f ' , 0 ) + " strings "
+ QString : : number ( strings_cached_this_frame , ' f ' , 0 ) + " cached " ;
2014-04-23 17:20:38 +00:00
2014-04-17 05:21:50 +00:00
int w , h ;
2014-05-07 19:52:59 +00:00
// this uses tightBoundingRect, which is different on Mac than it is on Windows & Linux.
GetTextExtent ( ss , w , h ) ;
2014-04-17 05:21:50 +00:00
QColor col = Qt : : white ;
2013-01-18 08:37:17 +00:00
2014-05-25 07:07:08 +00:00
if ( m_graphs . size ( ) > 0 ) {
painter . fillRect ( width ( ) - m_graphs [ 0 ] - > marginRight ( ) , 0 , m_graphs [ 0 ] - > marginRight ( ) , w , QBrush ( col ) ) ;
}
2013-01-17 20:57:17 +00:00
# ifndef Q_OS_MAC
2014-04-17 05:21:50 +00:00
// if (usePixmapCache()) xx+=4; else xx-=3;
2013-01-17 20:57:17 +00:00
# endif
2014-05-07 19:52:59 +00:00
AddTextQue ( ss , width ( ) , w / 2 , 90 , QColor ( Qt : : black ) , defaultfont ) ;
DrawTextQue ( painter ) ;
2011-09-03 05:01:55 +00:00
}
2014-05-17 11:33:33 +00:00
// painter.setPen(Qt::lightGray);
// painter.drawLine(0, 0, 0, height());
// painter.drawLine(0, 0, width(), 0);
// painter.setPen(Qt::darkGray);
//painter.drawLine(width(), 0, width(), height());
2014-04-17 05:21:50 +00:00
2012-01-05 06:54:07 +00:00
# endif
2014-05-17 11:33:33 +00:00
2014-05-16 09:30:11 +00:00
painter . end ( ) ;
2014-05-16 14:18:39 +00:00
# ifndef BROKEN_OPENGL_BUILD
2015-08-27 01:37:10 +00:00
# if QT_VERSION < QT_VERSION_CHECK(5,4,0)
2014-05-16 13:38:28 +00:00
swapBuffers ( ) ;
2015-08-27 01:37:10 +00:00
# endif
2014-05-16 14:18:39 +00:00
# endif
2014-05-07 19:52:59 +00:00
if ( this - > isVisible ( ) & & ! graphs_drawn & & render_cube ) { // keep the cube spinning
redrawtimer - > setInterval ( 1000.0 / 50 ) ; // 50 FPS
redrawtimer - > setSingleShot ( true ) ;
redrawtimer - > start ( ) ;
2011-12-20 07:17:09 +00:00
}
2014-08-17 12:56:05 +00:00
}
QString gGraphView : : getRangeString ( )
{
2015-08-11 20:38:09 +00:00
// a note about time zone usage here
// even though this string will be displayed to the user
// the graph is drawn using UTC times, so no conversion
// is needed to format the date and time for the user
// i.e. if the graph says the cursor is at 5pm, then that
// is what we should display.
// passing in UTC below is necessary to prevent QT
// from automatically converting the time to local time
2014-08-17 12:56:05 +00:00
QString fmt ;
qint64 diff = m_maxx - m_minx ;
if ( diff > 86400000 ) {
2014-08-28 15:45:46 +00:00
int days = ceil ( double ( m_maxx - m_minx ) / 86400000.0 ) ;
qint64 minx = floor ( double ( m_minx ) / 86400000.0 ) ;
minx * = 86400000L ;
qint64 maxx = minx + 86400000L * qint64 ( days ) - 1 ;
2015-08-11 20:01:24 +00:00
QDateTime st = QDateTime : : fromMSecsSinceEpoch ( minx , Qt : : UTC ) ;
QDateTime et = QDateTime : : fromMSecsSinceEpoch ( maxx , Qt : : UTC ) ;
2014-08-28 15:45:46 +00:00
QString txt = st . toString ( " d MMM " ) + " - " + et . addDays ( - 1 ) . toString ( " d MMM yyyy " ) ;
return txt ;
2014-08-17 12:56:05 +00:00
} else if ( diff > 60000 ) {
fmt = " HH:mm:ss " ;
} else {
fmt = " HH:mm:ss:zzz " ;
}
2015-08-11 20:01:24 +00:00
QDateTime st = QDateTime : : fromMSecsSinceEpoch ( m_minx , Qt : : UTC ) ;
QDateTime et = QDateTime : : fromMSecsSinceEpoch ( m_maxx , Qt : : UTC ) ;
2014-08-17 12:56:05 +00:00
QString txt = st . toString ( QObject : : tr ( " d MMM [ %1 - %2 ] " ) . arg ( fmt ) . arg ( et . toString ( fmt ) ) ) ;
return txt ;
2011-08-25 06:11:44 +00:00
}
2014-07-20 18:24:03 +00:00
void gGraphView : : leaveEvent ( QEvent * event )
{
Q_UNUSED ( event ) ;
2014-07-21 08:33:04 +00:00
if ( m_metaselect ) {
m_metaselect = false ;
timedRedraw ( 0 ) ;
}
2014-07-20 18:24:03 +00:00
releaseKeyboard ( ) ;
}
2011-08-25 06:11:44 +00:00
// For manual scrolling
void gGraphView : : setOffsetY ( int offsetY )
{
2014-04-17 05:21:50 +00:00
if ( m_offsetY ! = offsetY ) {
m_offsetY = offsetY ;
2011-12-20 11:12:52 +00:00
redraw ( ) ; //issue full redraw..
2011-08-26 04:15:15 +00:00
}
2011-08-25 06:11:44 +00:00
}
// For manual X scrolling (not really needed)
void gGraphView : : setOffsetX ( int offsetX )
{
2014-04-17 05:21:50 +00:00
if ( m_offsetX ! = offsetX ) {
m_offsetX = offsetX ;
2011-12-20 11:12:52 +00:00
redraw ( ) ; //issue redraw
2011-08-26 04:15:15 +00:00
}
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
void gGraphView : : mouseMoveEvent ( QMouseEvent * event )
2011-08-25 06:11:44 +00:00
{
2014-07-20 09:28:58 +00:00
grabKeyboard ( ) ;
2014-07-20 09:22:31 +00:00
2014-04-17 05:21:50 +00:00
int x = event - > x ( ) ;
int y = event - > y ( ) ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
m_mouse = QPoint ( x , y ) ;
2012-01-05 15:17:50 +00:00
2011-08-25 06:11:44 +00:00
if ( m_sizer_dragging ) { // Resize handle being dragged
2014-04-17 05:21:50 +00:00
float my = y - m_sizer_point . y ( ) ;
2011-08-25 06:11:44 +00:00
//qDebug() << "Sizer moved vertically" << m_sizer_index << my*m_scaleY;
2014-04-17 05:21:50 +00:00
float h = m_graphs [ m_sizer_index ] - > height ( ) ;
h + = my / m_scaleY ;
2011-08-25 06:11:44 +00:00
if ( h > m_graphs [ m_sizer_index ] - > minHeight ( ) ) {
m_graphs [ m_sizer_index ] - > setHeight ( h ) ;
m_sizer_point . setX ( x ) ;
m_sizer_point . setY ( y ) ;
updateScrollBar ( ) ;
2014-08-29 04:02:16 +00:00
timedRedraw ( ) ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
return ;
}
if ( m_graph_dragging ) { // Title bar being dragged to reorder
gGraph * p ;
2014-04-17 05:21:50 +00:00
int yy = m_sizer_point . y ( ) ;
2011-08-25 06:11:44 +00:00
bool empty ;
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
if ( y < yy ) {
2014-04-17 05:21:50 +00:00
for ( int i = m_graph_index - 1 ; i > = 0 ; i - - ) {
if ( m_graphs [ i ] - > isPinned ( ) ! = m_graphs [ m_graph_index ] - > isPinned ( ) ) {
2014-04-05 01:28:07 +00:00
// fix cursor
2014-04-05 09:00:06 +00:00
continue ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
empty = m_graphs [ i ] - > isEmpty ( ) | | ( ! m_graphs [ i ] - > visible ( ) ) ;
2011-08-25 06:11:44 +00:00
// swapping upwards.
2014-04-17 05:21:50 +00:00
int yy2 = yy - graphSpacer - m_graphs [ i ] - > height ( ) * m_scaleY ;
yy2 + = m_graphs [ m_graph_index ] - > height ( ) * m_scaleY ;
if ( y < yy2 ) {
2011-08-26 04:15:15 +00:00
//qDebug() << "Graph Reorder" << m_graph_index;
2014-04-17 05:21:50 +00:00
p = m_graphs [ m_graph_index ] ;
m_graphs [ m_graph_index ] = m_graphs [ i ] ;
m_graphs [ i ] = p ;
2011-08-25 06:11:44 +00:00
if ( ! empty ) {
2014-04-17 05:21:50 +00:00
m_sizer_point . setY ( yy - graphSpacer - m_graphs [ m_graph_index ] - > height ( ) * m_scaleY ) ;
2011-12-20 11:12:52 +00:00
redraw ( ) ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
m_graph_index - - ;
}
2014-04-17 05:21:50 +00:00
if ( ! empty ) { break ; }
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
} else if ( y > yy + graphSpacer + m_graphs [ m_graph_index ] - > height ( ) * m_scaleY ) {
2011-08-25 06:11:44 +00:00
// swapping downwards
2011-08-26 04:15:15 +00:00
//qDebug() << "Graph Reorder" << m_graph_index;
2014-04-17 05:21:50 +00:00
for ( int i = m_graph_index + 1 ; i < m_graphs . size ( ) ; i + + ) {
if ( m_graphs [ i ] - > isPinned ( ) ! = m_graphs [ m_graph_index ] - > isPinned ( ) ) {
2014-04-05 09:00:06 +00:00
//m_graph_dragging=false;
2014-04-05 01:28:07 +00:00
// fix cursor
2014-04-05 09:00:06 +00:00
continue ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
empty = m_graphs [ i ] - > isEmpty ( ) | | ( ! m_graphs [ i ] - > visible ( ) ) ;
p = m_graphs [ m_graph_index ] ;
m_graphs [ m_graph_index ] = m_graphs [ i ] ;
m_graphs [ i ] = p ;
2011-08-25 06:11:44 +00:00
if ( ! empty ) {
2014-04-17 05:21:50 +00:00
m_sizer_point . setY ( yy + graphSpacer + m_graphs [ m_graph_index ] - > height ( ) * m_scaleY ) ;
2014-08-29 04:02:16 +00:00
timedRedraw ( ) ;
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
m_graph_index + + ;
2014-04-17 05:21:50 +00:00
if ( ! empty ) { break ; }
2011-08-25 06:11:44 +00:00
}
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
return ;
}
2014-04-17 05:21:50 +00:00
float py = 0 , pinned_height = 0 , h ;
bool done = false ;
2014-04-05 01:28:07 +00:00
// Do pinned graphs first
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( m_graphs [ i ] - > isEmpty ( ) | | ! m_graphs [ i ] - > visible ( ) | | ! m_graphs [ i ] - > isPinned ( ) ) {
2014-04-05 01:28:07 +00:00
continue ;
2014-04-17 05:21:50 +00:00
}
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
h = m_graphs [ i ] - > height ( ) * m_scaleY ;
2014-04-05 01:28:07 +00:00
pinned_height + = h + graphSpacer ;
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( ! ( ( y > = py + m_graphs [ i ] - > top ) & & ( y < py + h - m_graphs [ i ] - > bottom ) ) ) {
2014-04-05 01:28:07 +00:00
if ( m_graphs [ i ] - > isSelected ( ) ) {
m_graphs [ i ] - > deselect ( ) ;
timedRedraw ( 150 ) ;
}
}
// Update Mouse Cursor shape
2014-04-17 05:21:50 +00:00
if ( ( y > = py + h - 1 ) & & ( y < ( py + h + graphSpacer ) ) ) {
2014-04-05 01:28:07 +00:00
this - > setCursor ( Qt : : SplitVCursor ) ;
2014-04-17 05:21:50 +00:00
done = true ;
} else if ( ( y > = py + 1 ) & & ( y < py + h ) ) {
if ( x > = titleWidth + 10 ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
} else {
2014-08-10 00:34:15 +00:00
m_tooltip - > display ( " Double click title to pin / unpin \n Click and drag to reorder graphs " , x + 10 , y , TT_AlignLeft ) ;
2014-08-17 12:56:05 +00:00
timedRedraw ( 0 ) ;
2014-08-10 00:34:15 +00:00
2014-04-17 05:21:50 +00:00
this - > setCursor ( Qt : : OpenHandCursor ) ;
}
m_horiz_travel + = qAbs ( x - m_lastxpos ) + qAbs ( y - m_lastypos ) ;
m_lastxpos = x ;
m_lastypos = y ;
// QPoint p(x,y);
// QMouseEvent e(event->type(),p,event->button(),event->buttons(),event->modifiers());
2014-07-19 12:51:17 +00:00
2014-04-17 05:21:50 +00:00
m_graphs [ i ] - > mouseMoveEvent ( event ) ;
done = true ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
2014-04-05 01:28:07 +00:00
py + = h + graphSpacer ;
}
py = - m_offsetY ;
py + = pinned_height ;
2011-08-25 06:11:44 +00:00
2013-10-25 10:39:30 +00:00
// Propagate mouseMove events to relevant graphs
2014-04-05 01:28:07 +00:00
if ( ! done )
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( m_graphs [ i ] - > isEmpty ( ) | | ! m_graphs [ i ] - > visible ( ) | | m_graphs [ i ] - > isPinned ( ) ) {
continue ;
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
h = m_graphs [ i ] - > height ( ) * m_scaleY ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
2012-01-03 07:15:02 +00:00
}
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
if ( ! ( ( y > = py + m_graphs [ i ] - > top ) & & ( y < py + h - m_graphs [ i ] - > bottom ) ) ) {
if ( m_graphs [ i ] - > isSelected ( ) ) {
m_graphs [ i ] - > deselect ( ) ;
timedRedraw ( 150 ) ;
}
}
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
// Update Mouse Cursor shape
if ( ( y > = py + h - 1 ) & & ( y < ( py + h + graphSpacer ) ) ) {
this - > setCursor ( Qt : : SplitVCursor ) ;
} else if ( ( y > = py + 1 ) & & ( y < py + h ) ) {
if ( x > = titleWidth + 10 ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
} else {
2014-08-10 00:34:15 +00:00
m_tooltip - > display ( " Double click title to pin / unpin \n Click and drag to reorder graphs " , x + 10 , y , TT_AlignLeft ) ;
2014-08-17 12:56:05 +00:00
timedRedraw ( 0 ) ;
2014-08-10 00:28:02 +00:00
2014-04-17 05:21:50 +00:00
this - > setCursor ( Qt : : OpenHandCursor ) ;
}
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
m_horiz_travel + = qAbs ( x - m_lastxpos ) + qAbs ( y - m_lastypos ) ;
m_lastxpos = x ;
m_lastypos = y ;
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( g ) {
g - > mouseMoveEvent ( event ) ;
}
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
}
/* else if (!m_button_down && (y >= py) && (y < py+m_graphs[i]->top)) {
// Mouse cursor is in top graph margin.
} else if ( ! m_button_down & & ( y > = py + h - m_graphs [ i ] - > bottom ) & & ( y < = py + h ) ) {
// Mouse cursor is in bottom grpah margin.
} else if ( m_button_down | | ( ( y > = py + m_graphs [ i ] - > top ) & & ( y < py + h - m_graphs [ i ] - > bottom ) ) ) {
if ( m_button_down | | ( x > = titleWidth + 10 ) ) { //(gYAxis::Margin-5)
this - > setCursor ( Qt : : ArrowCursor ) ;
m_horiz_travel + = qAbs ( x - m_lastxpos ) + qAbs ( y - m_lastypos ) ;
m_lastxpos = x ;
m_lastypos = y ;
QPoint p ( x - titleWidth , y - py ) ;
QMouseEvent e ( event - > type ( ) , p , event - > button ( ) , event - > buttons ( ) , event - > modifiers ( ) ) ;
m_graphs [ i ] - > mouseMoveEvent ( & e ) ;
if ( ! m_button_down & & ( x < = titleWidth + ( gYAxis : : Margin - 5 ) ) ) {
//qDebug() << "Hovering over" << m_graphs[i]->title();
if ( m_graphsbytitle [ STR_TR_EventFlags ] = = m_graphs [ i ] ) {
QVector < Layer * > & layers = m_graphs [ i ] - > layers ( ) ;
gFlagsGroup * fg ;
for ( int i = 0 ; i < layers . size ( ) ; i + + ) {
2014-04-23 13:19:56 +00:00
if ( ( fg = dynamic_cast < gFlagsGroup * > ( layers [ i ] ) ) ! = nullptr ) {
2014-04-17 05:21:50 +00:00
float bh = fg - > barHeight ( ) ;
int count = fg - > count ( ) ;
float yp = py + m_graphs [ i ] - > marginTop ( ) ;
yp = y - yp ;
float th = ( float ( count ) * bh ) ;
if ( yp > = 0 & & yp < th ) {
int i = yp / bh ;
if ( i < count ) {
ChannelID code = fg - > visibleLayers ( ) [ i ] - > code ( ) ;
QString ttip = schema : : channel [ code ] . description ( ) ;
2018-04-22 12:06:48 +00:00
m_tooltip - > display ( ttip , x , y - 20 , AppSetting - > tooltipTimeout ( ) ) ;
2014-04-17 05:21:50 +00:00
redraw ( ) ;
//qDebug() << code << ttip;
}
}
break ;
}
}
} else {
if ( ! m_graphs [ i ] - > units ( ) . isEmpty ( ) ) {
2018-04-22 12:06:48 +00:00
m_tooltip - > display ( m_graphs [ i ] - > units ( ) , x , y - 20 , AppSetting - > tooltipTimeout ( ) ) ;
2011-12-20 11:12:52 +00:00
redraw ( ) ;
2011-12-05 11:01:11 +00:00
}
2011-12-05 10:50:58 +00:00
}
2011-12-05 11:01:11 +00:00
}
2014-04-17 05:21:50 +00:00
} else {
2011-12-05 11:01:11 +00:00
2014-04-17 05:21:50 +00:00
this - > setCursor ( Qt : : OpenHandCursor ) ;
}
2011-12-05 08:32:46 +00:00
2014-04-17 05:21:50 +00:00
} */
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
// }
py + = h + graphSpacer ;
}
2011-08-25 06:11:44 +00:00
}
2014-08-17 12:56:05 +00:00
Layer * gGraphView : : findLayer ( gGraph * graph , LayerType type )
{
for ( int i = 0 ; i < graph - > layers ( ) . size ( ) ; i + + ) {
Layer * l = graph - > layers ( ) [ i ] ;
if ( l - > layerType ( ) = = type ) {
return l ;
}
}
return nullptr ;
}
2014-08-23 06:21:50 +00:00
class MyWidgetAction : public QWidgetAction
{
public :
MyWidgetAction ( ChannelID code , QObject * parent = nullptr ) : QWidgetAction ( parent ) , code ( code ) { chbox = nullptr ; }
protected :
2014-10-02 07:56:57 +00:00
virtual QWidget * createWidget ( QWidget * /*parent*/ ) {
2014-08-23 06:21:50 +00:00
connect ( chbox , SIGNAL ( toggled ( bool ) ) , this , SLOT ( setChecked ( bool ) ) ) ;
connect ( chbox , SIGNAL ( clicked ( ) ) , this , SLOT ( trigger ( ) ) ) ;
return chbox ;
}
QCheckBox * chbox ;
ChannelID code ;
} ;
2014-08-26 17:26:13 +00:00
MinMaxWidget : : MinMaxWidget ( gGraph * graph , QWidget * parent )
: QWidget ( parent ) , graph ( graph )
2014-08-26 15:05:59 +00:00
{
2014-08-27 09:55:31 +00:00
step = 1 ;
2014-08-26 15:05:59 +00:00
createLayout ( ) ;
}
void MinMaxWidget : : onMinChanged ( double d )
{
graph - > rec_miny = d ;
graph - > timedRedraw ( 0 ) ;
}
void MinMaxWidget : : onMaxChanged ( double d )
{
graph - > rec_maxy = d ;
graph - > timedRedraw ( 0 ) ;
}
2014-08-27 04:36:40 +00:00
void MinMaxWidget : : onResetClicked ( )
{
2014-08-27 09:55:31 +00:00
int tmp = graph - > zoomY ( ) ;
graph - > setZoomY ( 0 ) ;
2014-08-27 04:36:40 +00:00
EventDataType miny = graph - > MinY ( ) ,
maxy = graph - > MaxY ( ) ;
graph - > roundY ( miny , maxy ) ;
setMin ( graph - > rec_miny = miny ) ;
setMax ( graph - > rec_maxy = maxy ) ;
2014-08-27 09:55:31 +00:00
float r = maxy - miny ;
if ( r > 400 ) {
step = 50 ;
} else if ( r > 100 ) {
step = 10 ;
} else if ( r > 50 ) {
step = 5 ;
} else {
step = 1 ;
}
graph - > setZoomY ( tmp ) ;
2014-08-27 04:36:40 +00:00
}
2014-08-26 17:26:13 +00:00
void MinMaxWidget : : onComboChanged ( int idx )
{
minbox - > setEnabled ( idx = = 2 ) ;
maxbox - > setEnabled ( idx = = 2 ) ;
2014-08-27 04:36:40 +00:00
reset - > setEnabled ( idx = = 2 ) ;
2014-08-26 17:26:13 +00:00
graph - > setZoomY ( idx ) ;
if ( idx = = 2 ) {
2014-08-27 04:36:40 +00:00
if ( qAbs ( graph - > rec_maxy - graph - > rec_miny ) < 0.0001 ) {
onResetClicked ( ) ;
2014-08-26 17:26:13 +00:00
}
}
}
2014-08-26 15:05:59 +00:00
void MinMaxWidget : : createLayout ( )
{
2014-08-26 18:23:27 +00:00
2014-08-26 17:26:13 +00:00
QGridLayout * layout = new QGridLayout ;
2014-08-26 15:05:59 +00:00
layout - > setMargin ( 4 ) ;
layout - > setSpacing ( 4 ) ;
2014-08-26 17:26:13 +00:00
combobox = new QComboBox ( this ) ;
combobox - > addItem ( tr ( " Auto-Fit " ) , 0 ) ;
combobox - > addItem ( tr ( " Defaults " ) , 1 ) ;
combobox - > addItem ( tr ( " Override " ) , 2 ) ;
2014-08-27 09:55:31 +00:00
combobox - > setToolTip ( tr ( " The Y-Axis scaling mode, 'Auto-Fit' for automatic scaling, 'Defaults' for settings according to manufacturer, and 'Override' to choose your own. " ) ) ;
2014-08-26 17:26:13 +00:00
connect ( combobox , SIGNAL ( activated ( int ) ) , this , SLOT ( onComboChanged ( int ) ) ) ;
2014-08-26 15:05:59 +00:00
minbox = new QDoubleSpinBox ( this ) ;
maxbox = new QDoubleSpinBox ( this ) ;
2014-08-26 17:26:13 +00:00
2014-08-27 09:55:31 +00:00
minbox - > setToolTip ( tr ( " The Minimum Y-Axis value.. Note this can be a negative number if you wish. " ) ) ;
maxbox - > setToolTip ( tr ( " The Maximum Y-Axis value.. Must be greater than Minimum to work. " ) ) ;
2014-08-26 17:26:13 +00:00
int idx = graph - > zoomY ( ) ;
combobox - > setCurrentIndex ( idx ) ;
minbox - > setEnabled ( idx = = 2 ) ;
maxbox - > setEnabled ( idx = = 2 ) ;
minbox - > setAlignment ( Qt : : AlignRight ) ;
maxbox - > setAlignment ( Qt : : AlignRight ) ;
2014-08-27 04:36:40 +00:00
minbox - > setMinimum ( - 9999.0 ) ;
maxbox - > setMinimum ( - 9999.0 ) ;
2014-08-26 17:26:13 +00:00
minbox - > setMaximum ( 9999.99 ) ;
maxbox - > setMaximum ( 9999.99 ) ;
2014-08-27 04:36:40 +00:00
setMin ( graph - > rec_miny ) ;
setMax ( graph - > rec_maxy ) ;
2014-08-27 09:55:31 +00:00
float r = graph - > rec_maxy - graph - > rec_miny ;
if ( r > 400 ) {
step = 50 ;
} else if ( r > 100 ) {
step = 10 ;
} else if ( r > 50 ) {
step = 5 ;
} else {
step = 1 ;
}
minbox - > setSingleStep ( step ) ;
maxbox - > setSingleStep ( step ) ;
2014-08-26 17:26:13 +00:00
connect ( minbox , SIGNAL ( valueChanged ( double ) ) , this , SLOT ( onMinChanged ( double ) ) ) ;
connect ( maxbox , SIGNAL ( valueChanged ( double ) ) , this , SLOT ( onMaxChanged ( double ) ) ) ;
QLabel * label = new QLabel ( tr ( " Scaling Mode " ) ) ;
QFont font = label - > font ( ) ;
font . setBold ( true ) ;
label - > setFont ( font ) ;
label - > setAlignment ( Qt : : AlignCenter ) ;
layout - > addWidget ( label , 0 , 0 ) ;
layout - > addWidget ( combobox , 1 , 0 ) ;
label = new QLabel ( STR_TR_Min ) ;
label - > setFont ( font ) ;
label - > setAlignment ( Qt : : AlignCenter ) ;
layout - > addWidget ( label , 0 , 1 ) ;
layout - > addWidget ( minbox , 1 , 1 ) ;
label = new QLabel ( STR_TR_Max ) ;
label - > setFont ( font ) ;
label - > setAlignment ( Qt : : AlignCenter ) ;
layout - > addWidget ( label , 0 , 2 ) ;
layout - > addWidget ( maxbox , 1 , 2 ) ;
2014-08-27 04:36:40 +00:00
reset = new QToolButton ( this ) ;
reset - > setIcon ( QIcon ( " :/icons/refresh.png " ) ) ;
2014-08-27 09:55:31 +00:00
reset - > setToolTip ( tr ( " This button resets the Min and Max to match the Auto-Fit " ) ) ;
2014-08-27 04:36:40 +00:00
reset - > setEnabled ( idx = = 2 ) ;
layout - > addWidget ( reset , 1 , 3 ) ;
connect ( reset , SIGNAL ( clicked ( ) ) , this , SLOT ( onResetClicked ( ) ) ) ;
2014-08-26 15:05:59 +00:00
this - > setLayout ( layout ) ;
}
2014-08-23 06:21:50 +00:00
2014-08-17 12:56:05 +00:00
void gGraphView : : populateMenu ( gGraph * graph )
{
2014-08-23 07:11:50 +00:00
QAction * action ;
2014-08-27 15:00:55 +00:00
2014-08-27 13:42:10 +00:00
if ( graph - > isSnapshot ( ) ) {
2014-08-28 08:01:25 +00:00
snap_action - > setText ( tr ( " Remove Clone " ) ) ;
2014-08-27 13:42:10 +00:00
snap_action - > setData ( graph - > name ( ) + " |remove " ) ;
2014-08-27 15:00:55 +00:00
// zoom100_action->setVisible(false);
2014-08-27 13:42:10 +00:00
} else {
2014-08-28 08:01:25 +00:00
snap_action - > setText ( tr ( " Clone %1 Graph " ) . arg ( graph - > title ( ) ) ) ;
2014-08-27 13:42:10 +00:00
snap_action - > setData ( graph - > name ( ) + " |snapshot " ) ;
2014-08-27 15:00:55 +00:00
// zoom100_action->setVisible(true);
2014-08-27 13:42:10 +00:00
}
2014-08-23 07:11:50 +00:00
// Menu title fonts
QFont font = QApplication : : font ( ) ;
font . setBold ( true ) ;
font . setPointSize ( font . pointSize ( ) + 3 ) ;
2014-08-27 09:13:14 +00:00
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( graph , LT_LineChart ) ) ;
SummaryChart * sc = dynamic_cast < SummaryChart * > ( findLayer ( graph , LT_SummaryChart ) ) ;
2014-09-11 14:23:08 +00:00
gSummaryChart * stg = dynamic_cast < gSummaryChart * > ( findLayer ( graph , LT_Overview ) ) ;
2014-09-04 02:17:59 +00:00
2014-08-26 15:05:59 +00:00
2014-08-27 09:13:14 +00:00
limits_menu - > clear ( ) ;
2014-09-04 02:17:59 +00:00
if ( lc | | sc | | stg ) {
2014-08-27 09:13:14 +00:00
QWidgetAction * widget = new QWidgetAction ( this ) ;
MinMaxWidget * minmax = new MinMaxWidget ( graph , this ) ;
2014-08-26 15:05:59 +00:00
2014-08-27 09:13:14 +00:00
widget - > setDefaultWidget ( minmax ) ;
2014-08-26 15:05:59 +00:00
2014-08-27 09:13:14 +00:00
limits_menu - > addAction ( widget ) ;
limits_menu - > menuAction ( ) - > setVisible ( true ) ;
} else {
limits_menu - > menuAction ( ) - > setVisible ( false ) ;
}
2014-08-26 15:05:59 +00:00
2014-08-17 12:56:05 +00:00
// First check for any linechart for this graph..
if ( lc ) {
lines_menu - > clear ( ) ;
for ( int i = 0 ; i < lc - > m_dotlines . size ( ) ; i + + ) {
DottedLine & dot = lc - > m_dotlines [ i ] ;
2014-08-17 15:36:53 +00:00
if ( ! lc - > m_enabled [ dot . code ] ) continue ;
2014-08-17 12:56:05 +00:00
schema : : Channel & chan = schema : : channel [ dot . code ] ;
if ( dot . available ) {
2014-08-23 07:11:50 +00:00
QWidgetAction * widget = new QWidgetAction ( context_menu ) ;
QCheckBox * chbox = new QCheckBox ( chan . calc [ dot . type ] . label ( ) , context_menu ) ;
chbox - > setMouseTracking ( true ) ;
2014-08-24 02:26:53 +00:00
chbox - > setStyleSheet ( QString ( " QCheckBox:hover { background: %1; } " ) . arg ( QApplication : : palette ( ) . highlight ( ) . color ( ) . name ( ) ) ) ;
2014-08-23 07:11:50 +00:00
widget - > setDefaultWidget ( chbox ) ;
widget - > setCheckable ( true ) ;
widget - > setData ( QString ( " %1|%2 " ) . arg ( graph - > name ( ) ) . arg ( i ) ) ;
connect ( chbox , SIGNAL ( toggled ( bool ) ) , widget , SLOT ( setChecked ( bool ) ) ) ;
connect ( chbox , SIGNAL ( clicked ( ) ) , widget , SLOT ( trigger ( ) ) ) ;
2014-08-23 09:24:22 +00:00
bool b = lc - > m_dot_enabled [ dot . code ] [ dot . type ] ; //chan.calc[dot.type].enabled;
2014-08-23 07:11:50 +00:00
chbox - > setChecked ( b ) ;
lines_menu - > addAction ( widget ) ;
// QAction *action = lines_menu->addAction(chan.calc[dot.type].label());
// action->setData(graph->name());
// action->setCheckable(true);
// action->setChecked(chan.calc[dot.type].enabled);
2014-08-17 12:56:05 +00:00
}
}
2014-08-23 07:11:50 +00:00
2014-08-23 09:24:22 +00:00
lines_menu - > menuAction ( ) - > setVisible ( lines_menu - > actions ( ) . size ( ) > 0 ) ;
2014-08-23 07:11:50 +00:00
if ( lines_menu - > actions ( ) . size ( ) > 0 ) {
lines_menu - > insertSeparator ( lines_menu - > actions ( ) [ 0 ] ) ;
action = new QAction ( QObject : : tr ( " %1 " ) . arg ( graph - > title ( ) ) , lines_menu ) ;
lines_menu - > insertAction ( lines_menu - > actions ( ) [ 0 ] , action ) ;
action - > setFont ( font ) ;
action - > setData ( QString ( " " ) ) ;
action - > setEnabled ( false ) ;
}
//////////////////////////////////////////////////////////////////////////////////////
// Populate Plots Menus
//////////////////////////////////////////////////////////////////////////////////////
2014-08-23 06:35:02 +00:00
2014-08-17 12:56:05 +00:00
plots_menu - > clear ( ) ;
2014-08-23 06:35:02 +00:00
2014-08-23 09:24:22 +00:00
if ( lc - > m_codes . size ( ) > 1 ) {
2014-08-23 06:35:02 +00:00
for ( int i = 0 ; i < lc - > m_codes . size ( ) ; + + i ) {
ChannelID code = lc - > m_codes [ i ] ;
if ( lc - > m_day & & ! lc - > m_day - > channelHasData ( code ) ) continue ;
2014-08-23 07:11:50 +00:00
QWidgetAction * widget = new QWidgetAction ( context_menu ) ;
QCheckBox * chbox = new QCheckBox ( schema : : channel [ code ] . label ( ) , context_menu ) ;
chbox - > setMouseTracking ( true ) ;
chbox - > setToolTip ( schema : : channel [ code ] . description ( ) ) ;
2014-08-24 02:26:53 +00:00
chbox - > setStyleSheet ( QString ( " QCheckBox:hover { background: %1; } " ) . arg ( QApplication : : palette ( ) . highlight ( ) . color ( ) . name ( ) ) ) ;
2014-08-23 07:11:50 +00:00
widget - > setDefaultWidget ( chbox ) ;
widget - > setCheckable ( true ) ;
widget - > setData ( QString ( " %1|%2 " ) . arg ( graph - > name ( ) ) . arg ( code ) ) ;
connect ( chbox , SIGNAL ( toggled ( bool ) ) , widget , SLOT ( setChecked ( bool ) ) ) ;
connect ( chbox , SIGNAL ( clicked ( ) ) , widget , SLOT ( trigger ( ) ) ) ;
bool b = lc - > m_enabled [ code ] ;
chbox - > setChecked ( b ) ;
plots_menu - > addAction ( widget ) ;
// QAction * action = plots_menu->addAction(schema::channel[code].label());
// action->setData(QString("%1|%2").arg(graph->name()).arg(code));
// action->setCheckable(true);
// action->setChecked(lc->m_enabled[code]);
2014-08-23 06:35:02 +00:00
}
2014-08-17 12:56:05 +00:00
}
2014-08-23 07:11:50 +00:00
2014-08-23 09:24:22 +00:00
plots_menu - > menuAction ( ) - > setVisible ( ( plots_menu - > actions ( ) . size ( ) > 1 ) ) ;
2014-08-23 07:11:50 +00:00
if ( plots_menu - > actions ( ) . size ( ) > 0 ) {
plots_menu - > insertSeparator ( plots_menu - > actions ( ) [ 0 ] ) ;
action = new QAction ( QObject : : tr ( " %1 " ) . arg ( graph - > title ( ) ) , plots_menu ) ;
plots_menu - > insertAction ( plots_menu - > actions ( ) [ 0 ] , action ) ;
action - > setFont ( font ) ;
action - > setData ( QString ( " " ) ) ;
action - > setEnabled ( false ) ;
}
2014-08-20 11:30:42 +00:00
2014-08-23 07:11:50 +00:00
//////////////////////////////////////////////////////////////////////////////////////
// Populate Event Menus
//////////////////////////////////////////////////////////////////////////////////////
2014-08-20 18:36:44 +00:00
oximeter_menu - > clear ( ) ;
2014-08-23 06:21:50 +00:00
cpap_menu - > clear ( ) ;
2014-08-20 11:30:42 +00:00
using namespace schema ;
2014-08-23 06:21:50 +00:00
quint32 showflags = schema : : FLAG | schema : : MINOR_FLAG | schema : : SPAN ;
if ( p_profile - > general - > showUnknownFlags ( ) ) showflags | = schema : : UNKNOWN ;
QList < ChannelID > chans = lc - > m_day - > getSortedMachineChannels ( showflags ) ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
QHash < MachineType , int > Vis ;
2014-08-20 11:30:42 +00:00
for ( int i = 0 ; i < chans . size ( ) ; + + i ) {
ChannelID code = chans . at ( i ) ;
2014-08-23 06:21:50 +00:00
schema : : Channel & chan = schema : : channel [ code ] ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
QWidgetAction * widget = new QWidgetAction ( context_menu ) ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
QCheckBox * chbox = new QCheckBox ( schema : : channel [ code ] . fullname ( ) , context_menu ) ;
2014-08-24 02:26:53 +00:00
chbox - > setPalette ( context_menu - > palette ( ) ) ;
2014-08-23 06:21:50 +00:00
chbox - > setMouseTracking ( true ) ;
chbox - > setToolTip ( schema : : channel [ code ] . description ( ) ) ;
2014-08-24 02:26:53 +00:00
chbox - > setStyleSheet ( QString ( " QCheckBox:hover { background: %1; } " ) . arg ( QApplication : : palette ( ) . highlight ( ) . color ( ) . name ( ) ) ) ;
2014-08-20 18:36:44 +00:00
2014-08-23 06:21:50 +00:00
widget - > setDefaultWidget ( chbox ) ;
2014-08-20 18:36:44 +00:00
2014-08-23 06:21:50 +00:00
widget - > setCheckable ( true ) ;
widget - > setData ( QString ( " %1|%2 " ) . arg ( graph - > name ( ) ) . arg ( code ) ) ;
connect ( chbox , SIGNAL ( toggled ( bool ) ) , widget , SLOT ( setChecked ( bool ) ) ) ;
connect ( chbox , SIGNAL ( clicked ( ) ) , widget , SLOT ( trigger ( ) ) ) ;
bool b = lc - > m_flags_enabled [ code ] ;
chbox - > setChecked ( b ) ;
Vis [ chan . machtype ( ) ] + = b ? 1 : 0 ;
action = nullptr ;
if ( chan . machtype ( ) = = MT_OXIMETER ) {
oximeter_menu - > insertAction ( nullptr , widget ) ;
} else if ( chan . machtype ( ) = = MT_CPAP ) {
cpap_menu - > insertAction ( nullptr , widget ) ;
}
2014-08-20 18:36:44 +00:00
}
2014-08-23 06:21:50 +00:00
QString HideAllEvents = QObject : : tr ( " Hide All Events " ) ;
QString ShowAllEvents = QObject : : tr ( " Show All Events " ) ;
2014-08-23 07:11:50 +00:00
2014-08-23 09:24:22 +00:00
oximeter_menu - > menuAction ( ) - > setVisible ( oximeter_menu - > actions ( ) . size ( ) > 0 ) ;
cpap_menu - > menuAction ( ) - > setVisible ( cpap_menu - > actions ( ) . size ( ) > 0 ) ;
2014-08-23 07:11:50 +00:00
2014-08-20 18:36:44 +00:00
if ( cpap_menu - > actions ( ) . size ( ) > 0 ) {
2014-08-23 06:21:50 +00:00
cpap_menu - > addSeparator ( ) ;
if ( Vis [ MT_CPAP ] > 0 ) {
action = cpap_menu - > addAction ( HideAllEvents ) ;
action - > setData ( QString ( " %1|HideAll:CPAP " ) . arg ( graph - > name ( ) ) ) ;
} else {
action = cpap_menu - > addAction ( ShowAllEvents ) ;
action - > setData ( QString ( " %1|ShowAll:CPAP " ) . arg ( graph - > name ( ) ) ) ;
}
2014-08-23 06:35:02 +00:00
2014-08-23 07:11:50 +00:00
// Show CPAP Events menu Header...
2014-08-23 06:35:02 +00:00
cpap_menu - > insertSeparator ( cpap_menu - > actions ( ) [ 0 ] ) ;
2014-08-23 07:11:50 +00:00
action = new QAction ( QObject : : tr ( " %1 " ) . arg ( graph - > title ( ) ) , cpap_menu ) ;
2014-08-23 06:35:02 +00:00
cpap_menu - > insertAction ( cpap_menu - > actions ( ) [ 0 ] , action ) ;
action - > setFont ( font ) ;
action - > setData ( QString ( " " ) ) ;
action - > setEnabled ( false ) ;
2014-08-23 06:21:50 +00:00
}
if ( oximeter_menu - > actions ( ) . size ( ) > 0 ) {
oximeter_menu - > addSeparator ( ) ;
if ( Vis [ MT_OXIMETER ] > 0 ) {
action = oximeter_menu - > addAction ( HideAllEvents ) ;
action - > setData ( QString ( " %1|HideAll:OXI " ) . arg ( graph - > name ( ) ) ) ;
} else {
action = oximeter_menu - > addAction ( ShowAllEvents ) ;
action - > setData ( QString ( " %1|ShowAll:OXI " ) . arg ( graph - > name ( ) ) ) ;
}
2014-08-23 06:35:02 +00:00
oximeter_menu - > insertSeparator ( oximeter_menu - > actions ( ) [ 0 ] ) ;
2014-08-23 07:11:50 +00:00
action = new QAction ( QObject : : tr ( " %1 " ) . arg ( graph - > title ( ) ) , oximeter_menu ) ;
2014-08-23 06:35:02 +00:00
oximeter_menu - > insertAction ( oximeter_menu - > actions ( ) [ 0 ] , action ) ;
action - > setFont ( font ) ;
action - > setData ( QString ( " " ) ) ;
action - > setEnabled ( false ) ;
2014-08-20 18:36:44 +00:00
}
2014-08-20 11:30:42 +00:00
2014-08-17 12:56:05 +00:00
} else {
lines_menu - > clear ( ) ;
lines_menu - > menuAction ( ) - > setVisible ( false ) ;
plots_menu - > clear ( ) ;
plots_menu - > menuAction ( ) - > setVisible ( false ) ;
2014-08-20 18:36:44 +00:00
oximeter_menu - > clear ( ) ;
oximeter_menu - > menuAction ( ) - > setVisible ( false ) ;
cpap_menu - > clear ( ) ;
cpap_menu - > menuAction ( ) - > setVisible ( false ) ;
2014-08-17 12:56:05 +00:00
}
}
2014-08-27 13:42:10 +00:00
void gGraphView : : onSnapshotGraphToggle ( )
{
QString name = snap_action - > data ( ) . toString ( ) . section ( " | " , 0 , 0 ) ;
QString cmd = snap_action - > data ( ) . toString ( ) . section ( " | " , - 1 ) . toLower ( ) ;
QHash < QString , gGraph * > : : iterator it = m_graphsbyname . find ( name ) ;
if ( it = = m_graphsbyname . end ( ) ) return ;
gGraph * graph = it . value ( ) ;
if ( cmd = = " snapshot " ) {
2014-08-28 08:01:25 +00:00
QString basename = name + " ; " ;
if ( graph - > m_day ) {
2015-08-11 20:22:25 +00:00
// append the date of the graph's left edge to the snapshot name
// so the user knows what day the snapshot starts
// because the name is displayed to the user, use local time
QDateTime date = QDateTime : : fromMSecsSinceEpoch ( graph - > min_x , Qt : : LocalTime ) ;
2014-08-28 08:01:25 +00:00
basename + = date . date ( ) . toString ( Qt : : SystemLocaleLongDate ) ;
2014-08-27 13:42:10 +00:00
}
2014-08-28 08:01:25 +00:00
QString newname ;
2014-08-27 13:42:10 +00:00
2014-08-28 08:01:25 +00:00
// Find a new name.. How many snapshots for each graph counts as stupid?
for ( int i = 1 ; i < 100 ; i + + ) {
newname = basename + " ( " + QString : : number ( i ) + " ) " ;
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
it = m_graphsbyname . find ( newname ) ;
if ( it = = m_graphsbyname . end ( ) ) {
break ;
}
}
2014-08-27 17:30:53 +00:00
2014-08-29 10:38:46 +00:00
QString newtitle ;
bool fnd = false ;
// someday, some clown will keep adding new graphs to break this..
for ( int i = 1 ; i < 100 ; i + + ) {
newtitle = graph - > title ( ) + " - " + QString : : number ( i ) ;
fnd = false ;
for ( int j = 0 ; j < m_graphs . size ( ) ; + + j ) {
if ( m_graphs [ j ] - > title ( ) = = newtitle ) {
fnd = true ;
break ;
}
}
if ( ! fnd ) break ;
}
if ( fnd ) {
// holy crap.. what patience. but not what I meant by as many as you like ;)
return ;
}
gGraph * newgraph = new gGraph ( newname , nullptr , newtitle , graph - > units ( ) , graph - > height ( ) , graph - > group ( ) ) ;
2014-08-28 08:01:25 +00:00
// newgraph->setBlockSelect(true);
newgraph - > setHeight ( graph - > height ( ) ) ;
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
short group = 0 ;
m_graphs . insert ( m_graphs . indexOf ( graph ) + 1 , newgraph ) ;
m_graphsbyname [ newname ] = newgraph ;
newgraph - > m_graphview = this ;
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
for ( int i = 0 ; i < graph - > m_layers . size ( ) ; + + i ) {
Layer * layer = graph - > m_layers . at ( i ) - > Clone ( ) ;
if ( layer ) {
newgraph - > m_layers . append ( layer ) ;
}
}
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
gGraph * g = m_graphs . at ( i ) ;
group = qMax ( g - > group ( ) , group ) ;
2014-08-27 17:30:53 +00:00
}
2014-08-28 08:01:25 +00:00
newgraph - > setGroup ( group + 1 ) ;
//newgraph->setMinHeight(pm.height());
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
newgraph - > setDay ( graph - > m_day ) ;
if ( graph - > m_day ) {
graph - > m_day - > incUseCounter ( ) ;
}
newgraph - > min_x = graph - > min_x ;
newgraph - > max_x = graph - > max_x ;
if ( graph - > blockZoom ( ) ) {
newgraph - > setBlockZoom ( graph - > blockZoom ( ) ) ;
newgraph - > setBlockSelect ( true ) ;
}
if ( graph - > blockSelect ( ) ) {
newgraph - > setBlockSelect ( true ) ;
}
2014-08-28 13:01:16 +00:00
newgraph - > setZoomY ( graph - > zoomY ( ) ) ;
2014-08-27 17:30:53 +00:00
2014-08-28 08:01:25 +00:00
newgraph - > setSnapshot ( true ) ;
2014-08-27 13:42:10 +00:00
2014-08-29 11:34:21 +00:00
emit GraphsChanged ( ) ;
2014-08-27 13:42:10 +00:00
// addGraph(newgraph);
updateScale ( ) ;
2014-08-27 13:50:41 +00:00
timedRedraw ( 0 ) ;
2014-08-27 13:42:10 +00:00
} else if ( cmd = = " remove " ) {
2014-08-28 08:01:25 +00:00
if ( graph - > m_day ) {
graph - > m_day - > decUseCounter ( ) ;
if ( graph - > m_day - > useCounter ( ) = = 0 ) {
}
}
2014-08-27 13:42:10 +00:00
m_graphsbyname . remove ( graph - > name ( ) ) ;
m_graphs . removeAll ( it . value ( ) ) ;
delete graph ;
2014-08-28 08:01:25 +00:00
2014-08-27 13:50:41 +00:00
updateScale ( ) ;
timedRedraw ( 0 ) ;
2014-08-29 11:34:21 +00:00
emit GraphsChanged ( ) ;
2014-08-27 13:42:10 +00:00
}
qDebug ( ) < < cmd < < name ;
}
2014-08-28 08:01:25 +00:00
bool gGraphView : : hasSnapshots ( )
{
int size = m_graphs . size ( ) ;
bool snap = false ;
for ( int i = 0 ; i < size ; + + i ) {
gGraph * graph = m_graphs . at ( i ) ;
if ( graph - > isSnapshot ( ) ) {
snap = true ;
break ;
}
}
return snap ;
}
2014-08-17 12:56:05 +00:00
void gGraphView : : onPlotsClicked ( QAction * action )
{
QString name = action - > data ( ) . toString ( ) . section ( " | " , 0 , 0 ) ;
ChannelID code = action - > data ( ) . toString ( ) . section ( " | " , - 1 ) . toInt ( ) ;
QHash < QString , gGraph * > : : iterator it = m_graphsbyname . find ( name ) ;
if ( it = = m_graphsbyname . end ( ) ) return ;
gGraph * graph = it . value ( ) ;
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( graph , LT_LineChart ) ) ;
if ( ! lc ) return ;
lc - > m_enabled [ code ] = ! lc - > m_enabled [ code ] ;
graph - > min_y = graph - > MinY ( ) ;
graph - > max_y = graph - > MaxY ( ) ;
2014-08-23 07:11:50 +00:00
graph - > timedRedraw ( 0 ) ;
2014-08-17 12:56:05 +00:00
// lc->Miny();
// lc->Maxy();
}
2014-08-20 11:30:42 +00:00
void gGraphView : : onOverlaysClicked ( QAction * action )
{
QString name = action - > data ( ) . toString ( ) . section ( " | " , 0 , 0 ) ;
2014-08-23 06:21:50 +00:00
QString data = action - > data ( ) . toString ( ) . section ( " | " , - 1 ) ;
QHash < QString , gGraph * > : : iterator it = m_graphsbyname . find ( name ) ;
if ( it = = m_graphsbyname . end ( ) ) return ;
gGraph * graph = it . value ( ) ;
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( graph , LT_LineChart ) ) ;
if ( ! lc ) return ;
bool ok ;
ChannelID code = data . toInt ( & ok ) ;
if ( ok ) {
// Just toggling a flag on/off
bool b = ! lc - > m_flags_enabled [ code ] ;
lc - > m_flags_enabled [ code ] = b ;
QWidgetAction * widget = qobject_cast < QWidgetAction * > ( action ) ;
if ( widget ) {
widget - > setChecked ( b ) ;
}
timedRedraw ( 0 ) ;
return ;
}
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
QString hideall = data . section ( " : " , 0 , 0 ) ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
if ( ( hideall = = " HideAll " ) | | ( hideall = = " ShowAll " ) ) {
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
bool value = ( hideall = = " HideAll " ) ? false : true ;
QString group = data . section ( " : " , - 1 ) . toUpper ( ) ;
MachineType mtype ;
if ( group = = " CPAP " ) mtype = MT_CPAP ;
else if ( group = = " OXI " ) mtype = MT_OXIMETER ;
else mtype = MT_UNKNOWN ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
QHash < ChannelID , bool > : : iterator it ;
QHash < ChannelID , bool > : : iterator mfe = lc - > m_flags_enabled . end ( ) ;
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
// First toggle the actual flag bits
for ( it = lc - > m_flags_enabled . begin ( ) ; it ! = mfe ; + + it ) {
if ( schema : : channel [ it . key ( ) ] . machtype ( ) = = mtype ) {
lc - > m_flags_enabled [ it . key ( ) ] = value ;
}
}
2014-08-20 11:30:42 +00:00
2014-08-23 06:21:50 +00:00
// Now toggle the menu actions.. bleh
if ( mtype = = MT_CPAP ) {
for ( int i = 0 ; i < cpap_menu - > actions ( ) . size ( ) ; i + + ) {
if ( cpap_menu - > actions ( ) . at ( i ) - > isCheckable ( ) ) {
cpap_menu - > actions ( ) . at ( i ) - > setChecked ( value ) ;
}
}
} else if ( mtype = = MT_OXIMETER ) {
for ( int i = 0 ; i < oximeter_menu - > actions ( ) . size ( ) ; i + + ) {
if ( oximeter_menu - > actions ( ) . at ( i ) - > isCheckable ( ) ) {
oximeter_menu - > actions ( ) . at ( i ) - > setChecked ( value ) ;
}
}
}
}
2014-08-20 11:30:42 +00:00
}
2014-08-17 12:56:05 +00:00
void gGraphView : : onLinesClicked ( QAction * action )
{
2014-08-23 07:11:50 +00:00
QString name = action - > data ( ) . toString ( ) . section ( " | " , 0 , 0 ) ;
QString data = action - > data ( ) . toString ( ) . section ( " | " , - 1 ) ;
QHash < QString , gGraph * > : : iterator it = m_graphsbyname . find ( name ) ;
2014-08-17 12:56:05 +00:00
if ( it = = m_graphsbyname . end ( ) ) return ;
gGraph * graph = it . value ( ) ;
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( graph , LT_LineChart ) ) ;
if ( ! lc ) return ;
2014-08-23 07:11:50 +00:00
bool ok ;
int i = data . toInt ( & ok ) ;
if ( ok ) {
2014-08-17 12:56:05 +00:00
DottedLine & dot = lc - > m_dotlines [ i ] ;
schema : : Channel & chan = schema : : channel [ dot . code ] ;
2014-08-23 09:24:22 +00:00
chan . calc [ dot . type ] . enabled = ! chan . calc [ dot . type ] . enabled ;
lc - > m_dot_enabled [ dot . code ] [ dot . type ] = ! lc - > m_dot_enabled [ dot . code ] [ dot . type ] ;
2014-08-17 12:56:05 +00:00
}
2014-08-23 07:11:50 +00:00
timedRedraw ( 0 ) ;
2014-08-17 12:56:05 +00:00
}
2014-04-17 05:21:50 +00:00
void gGraphView : : mousePressEvent ( QMouseEvent * event )
2011-08-25 06:11:44 +00:00
{
2014-04-17 05:21:50 +00:00
int x = event - > x ( ) ;
int y = event - > y ( ) ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
float h , pinned_height = 0 , py = 0 ;
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
bool done = false ;
2011-08-25 06:11:44 +00:00
2014-04-05 01:28:07 +00:00
// first handle pinned graphs.
// Calculate total height of all pinned graphs
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | ! g - > isPinned ( ) ) {
2014-04-05 01:28:07 +00:00
continue ;
2014-04-17 05:21:50 +00:00
}
2014-04-05 01:28:07 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-17 05:21:50 +00:00
pinned_height + = h + graphSpacer ;
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
2014-04-05 01:28:07 +00:00
break ;
2014-04-17 05:21:50 +00:00
}
2014-04-05 01:28:07 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
2014-04-17 05:21:50 +00:00
if ( ( y > = py + h - 1 ) & & ( y < = py + h + graphSpacer ) ) {
2014-04-05 01:28:07 +00:00
this - > setCursor ( Qt : : SplitVCursor ) ;
2014-04-17 05:21:50 +00:00
m_sizer_dragging = true ;
m_sizer_index = i ;
2014-04-05 01:28:07 +00:00
m_sizer_point . setX ( x ) ;
m_sizer_point . setY ( y ) ;
2014-04-17 05:21:50 +00:00
done = true ;
2014-04-05 01:28:07 +00:00
} else if ( ( y > = py ) & & ( y < py + h ) ) {
//qDebug() << "Clicked" << i;
2014-08-17 12:56:05 +00:00
if ( ( event - > button ( ) = = Qt : : LeftButton ) & & ( x < titleWidth + 20 ) ) {
2014-04-05 01:28:07 +00:00
// clicked on title to drag graph..
// Note: reorder has to be limited to pinned graphs.
2014-04-17 05:21:50 +00:00
m_graph_dragging = true ;
2014-04-05 01:28:07 +00:00
m_tooltip - > cancel ( ) ;
timedRedraw ( 50 ) ;
2014-04-17 05:21:50 +00:00
m_graph_index = i ;
2014-04-05 01:28:07 +00:00
m_sizer_point . setX ( x ) ;
m_sizer_point . setY ( py ) ; // point at top of graph..
this - > setCursor ( Qt : : ClosedHandCursor ) ;
2018-03-28 06:22:42 +00:00
//done=true;
2014-08-17 12:56:05 +00:00
} else if ( ( event - > button ( ) = = Qt : : RightButton ) & & ( x < ( titleWidth + gYAxis : : Margin ) ) ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
pin_action - > setText ( QObject : : tr ( " Unpin %1 Graph " ) . arg ( g - > title ( ) ) ) ;
pin_graph = g ;
populateMenu ( g ) ;
context_menu - > popup ( event - > globalPos ( ) ) ;
2018-03-28 06:22:42 +00:00
//done=true;
2014-08-12 06:43:10 +00:00
} else if ( ! g - > blockSelect ( ) ) {
2014-07-19 13:09:08 +00:00
if ( m_metaselect ) {
if ( m_selected_graph ) {
m_selected_graph - > m_selecting_area = false ;
}
}
2014-04-17 05:21:50 +00:00
// send event to graph..
m_point_clicked = QPoint ( event - > x ( ) , event - > y ( ) ) ;
2014-07-19 13:09:08 +00:00
2014-04-05 01:28:07 +00:00
//QMouseEvent e(event->type(),m_point_clicked,event->button(),event->buttons(),event->modifiers());
2014-07-19 13:09:08 +00:00
2014-04-17 05:21:50 +00:00
m_button_down = true ;
2014-07-20 09:22:31 +00:00
m_metaselect = event - > modifiers ( ) & & Qt : : AltModifier ;
2014-04-17 05:21:50 +00:00
m_horiz_travel = 0 ;
m_graph_index = i ;
2014-07-25 07:53:48 +00:00
m_selected_graph = g ;
g - > mousePressEvent ( event ) ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
done = true ;
2014-04-05 01:28:07 +00:00
}
}
2014-04-17 05:21:50 +00:00
2014-04-05 01:28:07 +00:00
py + = h + graphSpacer ;
}
2011-08-25 06:11:44 +00:00
2014-04-05 01:28:07 +00:00
// then handle the remainder...
2014-04-17 05:21:50 +00:00
py = - m_offsetY ;
py + = pinned_height ;
2014-04-05 01:28:07 +00:00
if ( ! done )
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( ! g ) continue ;
2014-04-05 01:28:07 +00:00
2014-07-25 07:53:48 +00:00
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | g - > isPinned ( ) ) { continue ; }
2011-08-25 06:11:44 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ;
}
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
if ( ( y > = py + h - 1 ) & & ( y < = py + h + graphSpacer ) ) {
this - > setCursor ( Qt : : SplitVCursor ) ;
m_sizer_dragging = true ;
m_sizer_index = i ;
2011-08-25 06:11:44 +00:00
m_sizer_point . setX ( x ) ;
2014-04-17 05:21:50 +00:00
m_sizer_point . setY ( y ) ;
//qDebug() << "Sizer clicked" << i;
2018-03-28 06:22:42 +00:00
//done=true;
2014-04-17 05:21:50 +00:00
} else if ( ( y > = py ) & & ( y < py + h ) ) {
//qDebug() << "Clicked" << i;
2014-08-17 12:56:05 +00:00
if ( ( event - > button ( ) = = Qt : : LeftButton ) & & ( x < ( titleWidth + 20 ) ) ) { // clicked on title to drag graph..
2014-04-17 05:21:50 +00:00
m_graph_dragging = true ;
m_tooltip - > cancel ( ) ;
redraw ( ) ;
m_graph_index = i ;
m_sizer_point . setX ( x ) ;
m_sizer_point . setY ( py ) ; // point at top of graph..
this - > setCursor ( Qt : : ClosedHandCursor ) ;
2018-03-28 06:22:42 +00:00
//done=true;
2014-08-17 12:56:05 +00:00
} else if ( ( event - > button ( ) = = Qt : : RightButton ) & & ( x < ( titleWidth + gYAxis : : Margin ) ) ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
2018-05-03 05:08:45 +00:00
popout_action - > setText ( QObject : : tr ( " Popout %1 Graph " ) . arg ( g - > title ( ) ) ) ;
popout_graph = g ;
2014-08-17 12:56:05 +00:00
pin_action - > setText ( QObject : : tr ( " Pin %1 Graph " ) . arg ( g - > title ( ) ) ) ;
2018-05-03 05:08:45 +00:00
2014-08-17 12:56:05 +00:00
pin_graph = g ;
populateMenu ( g ) ;
context_menu - > popup ( event - > globalPos ( ) ) ;
2018-03-28 06:22:42 +00:00
//done=true;
2014-08-12 06:43:10 +00:00
} else if ( ! g - > blockSelect ( ) ) {
if ( m_metaselect ) {
2014-07-19 13:09:08 +00:00
if ( m_selected_graph ) {
m_selected_graph - > m_selecting_area = false ;
}
}
2014-04-17 05:21:50 +00:00
// send event to graph..
m_point_clicked = QPoint ( event - > x ( ) , event - > y ( ) ) ;
//QMouseEvent e(event->type(),m_point_clicked,event->button(),event->buttons(),event->modifiers());
m_button_down = true ;
2014-07-20 09:22:31 +00:00
m_metaselect = event - > modifiers ( ) & & Qt : : AltModifier ;
2014-07-19 12:17:32 +00:00
2014-04-17 05:21:50 +00:00
m_horiz_travel = 0 ;
m_graph_index = i ;
2014-07-25 07:53:48 +00:00
m_selected_graph = g ;
g - > mousePressEvent ( event ) ;
2014-04-17 05:21:50 +00:00
}
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
py + = h + graphSpacer ;
2014-08-17 12:56:05 +00:00
done = true ;
2011-08-25 06:11:44 +00:00
}
2014-08-17 12:56:05 +00:00
if ( ! done ) {
// if (event->button() == Qt::RightButton) {
// this->setCursor(Qt::ArrowCursor);
// context_menu->popup(event->globalPos());
// done=true;
// }
}
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
void gGraphView : : mouseReleaseEvent ( QMouseEvent * event )
2011-08-25 06:11:44 +00:00
{
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
int x = event - > x ( ) ;
int y = event - > y ( ) ;
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
float h , py = 0 , pinned_height = 0 ;
bool done = false ;
2013-10-25 10:39:30 +00:00
2014-07-26 12:46:11 +00:00
// Copy to a local variable to make sure this gets cleared
bool button_down = m_button_down ;
m_button_down = false ;
2014-04-05 01:28:07 +00:00
// Handle pinned graphs first
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | ! g - > isPinned ( ) ) {
2013-10-25 10:39:30 +00:00
continue ;
2014-04-17 05:21:50 +00:00
}
2013-10-25 10:39:30 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-17 05:21:50 +00:00
pinned_height + = h + graphSpacer ;
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
if ( ( y > = py + h - 1 ) & & ( y < ( py + h + graphSpacer ) ) ) {
2013-10-25 10:39:30 +00:00
this - > setCursor ( Qt : : SplitVCursor ) ;
2014-04-17 05:21:50 +00:00
done = true ;
} else if ( ( y > = py + 1 ) & & ( y < = py + h ) ) {
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
// if (!m_sizer_dragging && !m_graph_dragging) {
2014-07-25 07:53:48 +00:00
// g->mouseReleaseEvent(event);
2014-04-17 05:21:50 +00:00
// }
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
if ( x > = titleWidth + 10 ) {
2013-10-25 10:39:30 +00:00
this - > setCursor ( Qt : : ArrowCursor ) ;
2014-04-17 05:21:50 +00:00
} else {
2013-10-25 10:39:30 +00:00
this - > setCursor ( Qt : : OpenHandCursor ) ;
2014-04-17 05:21:50 +00:00
}
done = true ;
2013-10-25 10:39:30 +00:00
}
2014-04-17 05:21:50 +00:00
2014-04-05 01:28:07 +00:00
py + = h + graphSpacer ;
}
// Now do the unpinned ones
py = - m_offsetY ;
py + = pinned_height ;
if ( done )
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
2014-04-05 01:28:07 +00:00
2014-07-25 07:53:48 +00:00
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | g - > isPinned ( ) ) {
2014-04-17 05:21:50 +00:00
continue ;
}
2014-04-05 01:28:07 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
if ( ( y > = py + h - 1 ) & & ( y < ( py + h + graphSpacer ) ) ) {
this - > setCursor ( Qt : : SplitVCursor ) ;
} else if ( ( y > = py + 1 ) & & ( y < = py + h ) ) {
2014-04-05 01:28:07 +00:00
2014-04-17 05:21:50 +00:00
// if (!m_sizer_dragging && !m_graph_dragging) {
2014-07-25 07:53:48 +00:00
// g->mouseReleaseEvent(event);
2014-04-17 05:21:50 +00:00
// }
2013-10-25 10:39:30 +00:00
2014-04-17 05:21:50 +00:00
if ( x > = titleWidth + 10 ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
} else {
this - > setCursor ( Qt : : OpenHandCursor ) ;
}
}
py + = h + graphSpacer ;
2014-04-05 01:28:07 +00:00
}
2011-08-25 06:11:44 +00:00
if ( m_sizer_dragging ) {
2014-04-17 05:21:50 +00:00
m_sizer_dragging = false ;
2011-08-25 06:11:44 +00:00
return ;
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
if ( m_graph_dragging ) {
2014-04-17 05:21:50 +00:00
m_graph_dragging = false ;
2013-10-25 10:39:30 +00:00
// not sure why the cursor code doesn't catch this..
2014-04-17 05:21:50 +00:00
if ( x > = titleWidth + 10 ) {
this - > setCursor ( Qt : : ArrowCursor ) ;
} else {
this - > setCursor ( Qt : : OpenHandCursor ) ;
}
2011-08-25 06:11:44 +00:00
return ;
}
2013-10-25 10:39:30 +00:00
// The graph that got the button press gets the release event
2014-07-26 12:46:11 +00:00
if ( button_down ) {
// m_button_down = false;
2014-07-20 09:22:31 +00:00
m_metaselect = event - > modifiers ( ) & Qt : : AltModifier ;
2014-07-19 14:09:04 +00:00
saveHistory ( ) ;
2014-07-19 13:38:07 +00:00
2014-07-19 12:17:32 +00:00
if ( m_metaselect ) {
m_point_released = event - > pos ( ) ;
} else {
2014-08-07 21:54:32 +00:00
if ( ( m_graph_index > = 0 ) & & ( m_graphs [ m_graph_index ] ) ) {
2014-07-25 07:53:48 +00:00
m_graphs [ m_graph_index ] - > mouseReleaseEvent ( event ) ;
}
2014-07-19 12:17:32 +00:00
}
}
2014-08-17 12:56:05 +00:00
timedRedraw ( 0 ) ;
2014-07-19 12:17:32 +00:00
}
void gGraphView : : keyReleaseEvent ( QKeyEvent * event )
{
2014-07-20 09:22:31 +00:00
if ( m_metaselect & & ! ( event - > modifiers ( ) & Qt : : AltModifier ) ) {
2014-07-19 12:51:17 +00:00
QMouseEvent mevent ( QEvent : : MouseButtonRelease , m_point_released , Qt : : LeftButton , Qt : : LeftButton , event - > modifiers ( ) ) ;
2014-07-20 09:26:59 +00:00
if ( m_graph_index > = 0 ) {
2014-07-19 12:51:17 +00:00
m_graphs [ m_graph_index ] - > mouseReleaseEvent ( & mevent ) ;
2014-07-20 09:26:59 +00:00
}
2014-07-19 12:17:32 +00:00
2014-07-19 12:51:17 +00:00
m_metaselect = false ;
2014-07-20 09:26:59 +00:00
2014-07-19 12:55:40 +00:00
timedRedraw ( 50 ) ;
2011-08-25 06:11:44 +00:00
}
2014-07-19 13:38:07 +00:00
if ( event - > key ( ) = = Qt : : Key_Escape ) {
if ( history . size ( ) > 0 ) {
SelectionHistoryItem h = history . takeFirst ( ) ;
SetXBounds ( h . minx , h . maxx ) ;
2014-07-19 14:09:04 +00:00
// could Forward push this to another list?
2014-07-19 13:38:07 +00:00
} else {
2014-07-19 14:09:04 +00:00
ResetBounds ( ) ;
2014-07-19 13:38:07 +00:00
}
return ;
}
2014-07-19 12:17:32 +00:00
# ifdef BROKEN_OPENGL_BUILD
QWidget : : keyReleaseEvent ( event ) ;
2015-08-27 01:37:10 +00:00
# elif QT_VERSION < QT_VERSION_CHECK(5,4,0)
2014-07-19 12:17:32 +00:00
QGLWidget : : keyReleaseEvent ( event ) ;
2015-08-27 01:37:10 +00:00
# else
QOpenGLWidget : : keyReleaseEvent ( event ) ;
2014-07-19 12:17:32 +00:00
# endif
2011-08-25 06:11:44 +00:00
}
2014-07-19 12:17:32 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : mouseDoubleClickEvent ( QMouseEvent * event )
2011-08-25 06:11:44 +00:00
{
2014-04-05 01:28:07 +00:00
mousePressEvent ( event ) ; // signal missing.. a qt change might "fix" this if we are not careful.
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
int x = event - > x ( ) ;
int y = event - > y ( ) ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
float h , py = 0 , pinned_height = 0 ;
bool done = false ;
2014-04-05 01:28:07 +00:00
// Handle pinned graphs first
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | ! g - > isPinned ( ) ) {
2014-04-05 01:28:07 +00:00
continue ;
2014-04-17 05:21:50 +00:00
}
2014-04-05 01:28:07 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2014-04-05 01:28:07 +00:00
pinned_height + = h + graphSpacer ;
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
2014-04-05 01:28:07 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
if ( ( y > = py ) & & ( y < = py + h ) ) {
if ( x < titleWidth ) {
// What to do when double clicked on the graph title ??
2014-04-06 06:32:58 +00:00
2014-07-25 07:53:48 +00:00
g - > mouseDoubleClickEvent ( event ) ;
2014-04-06 06:32:58 +00:00
// pin the graph??
2014-07-25 07:53:48 +00:00
g - > setPinned ( false ) ;
2014-04-06 06:32:58 +00:00
redraw ( ) ;
2014-04-05 01:28:07 +00:00
} else {
// send event to graph..
2014-07-25 07:53:48 +00:00
g - > mouseDoubleClickEvent ( event ) ;
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
done = true ;
2014-04-05 01:28:07 +00:00
} else if ( ( y > = py + h ) & & ( y < = py + h + graphSpacer + 1 ) ) {
// What to do when double clicked on the resize handle?
2014-04-17 05:21:50 +00:00
done = true ;
2014-04-05 01:28:07 +00:00
}
}
2014-04-17 05:21:50 +00:00
py + = h ;
py + = graphSpacer ; // do we want the extra spacer down the bottom?
2014-04-05 01:28:07 +00:00
}
2014-04-17 05:21:50 +00:00
py = - m_offsetY ;
py + = pinned_height ;
2011-08-25 06:11:44 +00:00
2014-04-05 01:28:07 +00:00
if ( ! done ) // then handle unpinned graphs
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | g - > isPinned ( ) ) {
2014-04-17 05:21:50 +00:00
continue ;
}
2011-08-25 06:11:44 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
break ;
}
2014-04-06 06:32:58 +00:00
2014-04-17 05:21:50 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
if ( ( y > = py ) & & ( y < = py + h ) ) {
if ( x < titleWidth ) {
// What to do when double clicked on the graph title ??
2014-07-25 07:53:48 +00:00
g - > mouseDoubleClickEvent ( event ) ;
2014-04-17 05:21:50 +00:00
2014-07-25 07:53:48 +00:00
g - > setPinned ( true ) ;
2014-04-17 05:21:50 +00:00
redraw ( ) ;
} else {
// send event to graph..
2014-07-25 07:53:48 +00:00
g - > mouseDoubleClickEvent ( event ) ;
2014-04-17 05:21:50 +00:00
}
} else if ( ( y > = py + h ) & & ( y < = py + h + graphSpacer + 1 ) ) {
// What to do when double clicked on the resize handle?
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
2011-08-25 06:11:44 +00:00
}
2014-04-17 05:21:50 +00:00
py + = h ;
py + = graphSpacer ; // do we want the extra spacer down the bottom?
2011-08-25 06:11:44 +00:00
}
}
2014-07-25 07:53:48 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : wheelEvent ( QWheelEvent * event )
2011-08-25 06:11:44 +00:00
{
// Hmm.. I could optionalize this to change mousewheel behaviour without affecting the scrollbar now..
2014-07-26 12:46:11 +00:00
if ( m_button_down )
return ;
2014-08-28 13:01:16 +00:00
if ( event - > modifiers ( ) = = Qt : : NoModifier ) {
2018-04-22 12:06:48 +00:00
int scrollDampening = AppSetting - > scrollDampening ( ) ;
2014-08-28 13:01:16 +00:00
if ( event - > orientation ( ) = = Qt : : Vertical ) { // Vertical Scrolling
if ( horizScrollTime . elapsed ( ) < scrollDampening ) {
return ;
}
if ( m_scrollbar )
m_scrollbar - > SendWheelEvent ( event ) ; // Just forwarding the event to scrollbar for now..
m_tooltip - > cancel ( ) ;
vertScrollTime . start ( ) ;
return ;
}
2014-08-28 14:37:49 +00:00
2014-08-28 13:01:16 +00:00
// (This is a total pain in the butt on MacBook touchpads..)
if ( vertScrollTime . elapsed ( ) < scrollDampening ) {
return ;
}
horizScrollTime . start ( ) ;
2014-08-28 14:37:49 +00:00
}
gGraph * graph = nullptr ;
int group = 0 ;
2014-10-02 07:56:57 +00:00
//int x = event->x();
2014-08-28 14:37:49 +00:00
int y = event - > y ( ) ;
2014-08-28 13:01:16 +00:00
2014-08-28 14:37:49 +00:00
float h , py = 0 , pinned_height = 0 ;
2011-08-25 13:13:58 +00:00
2014-08-28 13:01:16 +00:00
2014-08-28 14:37:49 +00:00
// Find graph hovered over
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
gGraph * g = m_graphs [ i ] ;
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | ! g - > isPinned ( ) ) {
continue ;
}
h = g - > height ( ) * m_scaleY ;
pinned_height + = h + graphSpacer ;
if ( py > height ( ) ) {
break ; // we are done.. can't draw anymore
}
if ( ( py + h + graphSpacer ) > = 0 ) {
if ( ( y > = py ) & & ( y < = py + h ) ) {
graph = g ;
break ;
} else if ( ( y > = py + h ) & & ( y < = py + h + graphSpacer + 1 ) ) {
// What to do when double clicked on the resize handle?
graph = g ;
break ;
}
}
py + = h ;
py + = graphSpacer ; // do we want the extra spacer down the bottom?
}
if ( ! graph ) {
py = - m_offsetY ;
py + = pinned_height ;
2011-08-25 13:13:58 +00:00
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
gGraph * g = m_graphs [ i ] ;
2014-08-28 14:37:49 +00:00
if ( ! g | | g - > isEmpty ( ) | | ! g - > visible ( ) | | g - > isPinned ( ) ) {
2014-08-28 13:01:16 +00:00
continue ;
}
2014-04-17 05:21:50 +00:00
2014-07-25 07:53:48 +00:00
h = g - > height ( ) * m_scaleY ;
2011-08-25 13:13:58 +00:00
2014-04-17 05:21:50 +00:00
if ( py > height ( ) ) {
2014-08-28 14:37:49 +00:00
break ;
2014-04-17 05:21:50 +00:00
}
2011-08-25 13:13:58 +00:00
if ( ( py + h + graphSpacer ) > = 0 ) {
if ( ( y > = py ) & & ( y < = py + h ) ) {
2014-08-28 13:01:16 +00:00
graph = g ;
break ;
2011-08-25 13:13:58 +00:00
} else if ( ( y > = py + h ) & & ( y < = py + h + graphSpacer + 1 ) ) {
2014-08-28 13:01:16 +00:00
// What to do when double clicked on the resize handle?
graph = g ;
break ;
2011-08-25 13:13:58 +00:00
}
2014-08-28 14:37:49 +00:00
2011-08-25 13:13:58 +00:00
}
2014-04-17 05:21:50 +00:00
py + = h ;
py + = graphSpacer ; // do we want the extra spacer down the bottom?
2011-08-25 13:13:58 +00:00
}
2014-08-28 14:37:49 +00:00
}
2013-01-18 12:23:00 +00:00
2014-08-28 13:01:16 +00:00
2014-08-28 14:37:49 +00:00
if ( event - > modifiers ( ) = = Qt : : NoModifier ) {
2014-08-28 13:01:16 +00:00
if ( ! graph ) {
// just pick any graph then
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( ! m_graphs [ i ] ) continue ;
if ( ! m_graphs [ i ] - > isEmpty ( ) ) {
graph = m_graphs [ i ] ;
group = graph - > group ( ) ;
break ;
2013-01-18 12:23:00 +00:00
}
}
2014-08-28 13:01:16 +00:00
} else group = graph - > group ( ) ;
2013-01-18 12:23:00 +00:00
2014-08-28 13:01:16 +00:00
if ( ! graph ) { return ; }
2014-04-17 05:21:50 +00:00
2014-08-28 13:01:16 +00:00
double xx = ( graph - > max_x - graph - > min_x ) ;
double zoom = 240.0 ;
2014-04-17 05:21:50 +00:00
2014-08-28 13:01:16 +00:00
int delta = event - > delta ( ) ;
2013-01-18 12:23:00 +00:00
2014-08-28 13:01:16 +00:00
if ( delta > 0 ) {
graph - > min_x - = ( xx / zoom ) * ( float ) abs ( delta ) ;
} else {
graph - > min_x + = ( xx / zoom ) * ( float ) abs ( delta ) ;
}
graph - > max_x = graph - > min_x + xx ;
if ( graph - > min_x < graph - > rmin_x ) {
graph - > min_x = graph - > rmin_x ;
graph - > max_x = graph - > rmin_x + xx ;
}
2013-01-18 12:23:00 +00:00
2014-08-28 13:01:16 +00:00
if ( graph - > max_x > graph - > rmax_x ) {
graph - > max_x = graph - > rmax_x ;
graph - > min_x = graph - > max_x - xx ;
}
saveHistory ( ) ;
SetXBounds ( graph - > min_x , graph - > max_x , group ) ;
2014-08-28 14:37:49 +00:00
} else if ( ( event - > modifiers ( ) & Qt : : ControlModifier ) ) {
2013-01-18 12:23:00 +00:00
2014-08-28 14:37:49 +00:00
if ( graph ) graph - > wheelEvent ( event ) ;
// int x = event->x();
// int y = event->y();
2014-08-28 13:01:16 +00:00
2014-08-28 14:37:49 +00:00
// float py = -m_offsetY;
// float h;
2014-08-28 13:01:16 +00:00
2014-04-17 05:21:50 +00:00
2014-08-28 14:37:49 +00:00
// for (int i = 0; i < m_graphs.size(); i++) {
// gGraph *g = m_graphs[i];
// if (!g || g->isEmpty() || !g->visible()) { continue; }
2014-08-28 13:01:16 +00:00
2014-08-28 14:37:49 +00:00
// h = g->height() * m_scaleY;
2013-01-18 12:23:00 +00:00
2014-08-28 14:37:49 +00:00
// if (py > height()) {
// break;
// }
// if ((py + h + graphSpacer) >= 0) {
// if ((y >= py) && (y <= py + h)) {
// if (x < titleWidth) {
// // What to do when ctrl+wheel is used on the graph title ??
// } else {
// // send event to graph..
// g->wheelEvent(event);
// }
// } else if ((y >= py + h) && (y <= py + h + graphSpacer + 1)) {
// // What to do when the wheel is used on the resize handle?
// }
// }
// py += h;
// py += graphSpacer; // do we want the extra spacer down the bottom?
// }
2011-08-25 13:13:58 +00:00
}
2011-08-25 06:11:44 +00:00
}
2014-08-07 17:20:52 +00:00
void gGraphView : : getSelectionTimes ( qint64 & start , qint64 & end )
{
if ( m_graph_index > = 0 ) {
gGraph * g = m_graphs [ m_graph_index ] ;
if ( ! g ) {
start = 0 ;
end = 0 ;
return ;
}
2014-08-07 21:54:32 +00:00
int x1 = g - > m_selection . x ( ) + titleWidth ;
int x2 = x1 + g - > m_selection . width ( ) ;
2014-08-07 17:20:52 +00:00
start = g - > screenToTime ( x1 ) ;
end = g - > screenToTime ( x2 ) ;
}
}
2014-04-17 05:21:50 +00:00
void gGraphView : : keyPressEvent ( QKeyEvent * event )
2011-08-25 06:11:44 +00:00
{
2014-07-20 09:22:31 +00:00
m_metaselect = event - > modifiers ( ) & Qt : : AltModifier ;
2014-08-07 17:20:52 +00:00
if ( m_metaselect & & ( ( event - > key ( ) = = Qt : : Key_B ) | | ( event - > key ( ) = = 8747 ) ) ) {
if ( mainwin - > getDaily ( ) - > graphView ( ) = = this ) {
if ( m_graph_index > = 0 ) {
m_metaselect = false ;
qint64 start , end ;
getSelectionTimes ( start , end ) ;
2015-08-11 20:01:24 +00:00
QDateTime d1 = QDateTime : : fromMSecsSinceEpoch ( start , Qt : : UTC ) ;
2014-08-07 17:20:52 +00:00
mainwin - > getDaily ( ) - > addBookmark ( start , end , QString ( " Bookmark at %1 " ) . arg ( d1 . time ( ) . toString ( " HH:mm:ss " ) ) ) ;
m_graphs [ m_graph_index ] - > cancelSelection ( ) ;
m_graph_index = - 1 ;
timedRedraw ( 0 ) ;
}
event - > accept ( ) ;
return ;
}
}
2014-07-20 09:22:31 +00:00
2014-07-25 07:53:48 +00:00
if ( ( m_metaselect ) & & ( event - > key ( ) > = Qt : : Key_0 ) & & ( event - > key ( ) < = Qt : : Key_9 ) ) {
2014-10-02 07:56:57 +00:00
//int bk = (int)event->key()-Qt::Key_0;
2014-07-25 07:53:48 +00:00
m_metaselect = false ;
2014-08-17 12:56:05 +00:00
timedRedraw ( 0 ) ;
2014-07-25 07:53:48 +00:00
}
2014-07-21 08:33:04 +00:00
if ( event - > key ( ) = = Qt : : Key_F3 ) {
2018-04-22 12:06:48 +00:00
AppSetting - > setLineCursorMode ( ! AppSetting - > lineCursorMode ( ) ) ;
2014-07-21 08:33:04 +00:00
timedRedraw ( 0 ) ;
2014-07-19 12:51:17 +00:00
}
2014-08-05 11:17:03 +00:00
if ( ( event - > key ( ) = = Qt : : Key_F1 ) ) {
2014-07-21 16:14:07 +00:00
dumpInfo ( ) ;
}
2014-07-19 13:09:08 +00:00
2014-04-17 05:21:50 +00:00
if ( event - > key ( ) = = Qt : : Key_Tab ) {
2011-10-28 11:31:31 +00:00
event - > ignore ( ) ;
return ;
}
2014-04-17 05:21:50 +00:00
if ( event - > key ( ) = = Qt : : Key_PageUp ) {
2014-05-25 07:07:08 +00:00
if ( m_scrollbar ) {
2018-04-22 12:06:48 +00:00
m_offsetY - = AppSetting - > graphHeight ( ) * 3 * m_scaleY ;
2014-05-25 07:07:08 +00:00
m_scrollbar - > setValue ( m_offsetY ) ;
m_offsetY = m_scrollbar - > value ( ) ;
redraw ( ) ;
}
2014-04-17 05:21:50 +00:00
return ;
} else if ( event - > key ( ) = = Qt : : Key_PageDown ) {
2014-05-25 07:07:08 +00:00
if ( m_scrollbar ) {
2018-04-22 12:06:48 +00:00
m_offsetY + = AppSetting - > graphHeight ( ) * 3 * m_scaleY ;
2014-04-17 05:21:50 +00:00
2014-05-25 07:07:08 +00:00
if ( m_offsetY < 0 ) { m_offsetY = 0 ; }
2014-04-17 05:21:50 +00:00
2014-05-25 07:07:08 +00:00
m_scrollbar - > setValue ( m_offsetY ) ;
m_offsetY = m_scrollbar - > value ( ) ;
redraw ( ) ;
}
2014-04-17 05:21:50 +00:00
return ;
// redraw();
2011-12-25 05:05:12 +00:00
}
2014-04-17 05:21:50 +00:00
2014-04-23 13:19:56 +00:00
gGraph * g = nullptr ;
2014-04-17 05:21:50 +00:00
int group = 0 ;
2011-11-28 01:39:28 +00:00
// Pick the first valid graph in the primary group
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( m_graphs [ i ] - > group ( ) = = group ) {
2012-01-12 22:55:50 +00:00
if ( ! m_graphs [ i ] - > isEmpty ( ) & & m_graphs [ i ] - > visible ( ) ) {
2014-04-17 05:21:50 +00:00
g = m_graphs [ i ] ;
2011-11-28 13:16:50 +00:00
break ;
}
}
}
if ( ! g ) {
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2011-11-27 23:10:16 +00:00
if ( ! m_graphs [ i ] - > isEmpty ( ) ) {
2014-04-17 05:21:50 +00:00
g = m_graphs [ i ] ;
group = g - > group ( ) ;
2011-11-27 23:10:16 +00:00
break ;
}
2011-09-05 13:26:10 +00:00
}
}
2014-04-17 05:21:50 +00:00
if ( ! g ) { return ; }
2011-11-28 01:39:28 +00:00
2011-10-28 03:45:31 +00:00
g - > keyPressEvent ( event ) ;
2011-08-25 06:11:44 +00:00
2014-04-17 05:21:50 +00:00
if ( event - > key ( ) = = Qt : : Key_Left ) {
double xx = g - > max_x - g - > min_x ;
double zoom = 8.0 ;
if ( event - > modifiers ( ) & Qt : : ControlModifier ) { zoom / = 4 ; }
g - > min_x - = xx / zoom ; ;
g - > max_x = g - > min_x + xx ;
2011-09-05 13:26:10 +00:00
2014-04-17 05:21:50 +00:00
if ( g - > min_x < g - > rmin_x ) {
g - > min_x = g - > rmin_x ;
g - > max_x = g - > rmin_x + xx ;
2011-09-05 13:26:10 +00:00
}
2014-04-17 05:21:50 +00:00
2014-07-19 14:09:04 +00:00
saveHistory ( ) ;
2014-04-17 05:21:50 +00:00
SetXBounds ( g - > min_x , g - > max_x , group ) ;
} else if ( event - > key ( ) = = Qt : : Key_Right ) {
double xx = g - > max_x - g - > min_x ;
double zoom = 8.0 ;
if ( event - > modifiers ( ) & Qt : : ControlModifier ) { zoom / = 4 ; }
g - > min_x + = xx / zoom ;
g - > max_x = g - > min_x + xx ;
if ( g - > max_x > g - > rmax_x ) {
g - > max_x = g - > rmax_x ;
g - > min_x = g - > rmax_x - xx ;
2011-09-05 13:26:10 +00:00
}
2014-04-17 05:21:50 +00:00
2014-07-19 14:09:04 +00:00
saveHistory ( ) ;
2014-04-17 05:21:50 +00:00
SetXBounds ( g - > min_x , g - > max_x , group ) ;
} else if ( event - > key ( ) = = Qt : : Key_Up ) {
float zoom = 0.75F ;
if ( event - > modifiers ( ) & Qt : : ControlModifier ) { zoom / = 1.5 ; }
g - > ZoomX ( zoom , 0 ) ; // zoom in.
} else if ( event - > key ( ) = = Qt : : Key_Down ) {
float zoom = 1.33F ;
if ( event - > modifiers ( ) & Qt : : ControlModifier ) { zoom * = 1.5 ; }
g - > ZoomX ( zoom , 0 ) ; // Zoom out
2011-09-05 13:26:10 +00:00
}
2014-04-17 05:21:50 +00:00
2011-09-06 07:33:34 +00:00
//qDebug() << "Keypress??";
2011-08-25 06:11:44 +00:00
}
2014-07-19 12:17:32 +00:00
2014-04-17 05:21:50 +00:00
void gGraphView : : setDay ( Day * day )
2011-08-31 07:40:13 +00:00
{
2014-07-25 07:53:48 +00:00
2014-04-17 05:21:50 +00:00
m_day = day ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
if ( m_graphs [ i ] ) m_graphs [ i ] - > setDay ( day ) ;
2011-08-31 07:40:13 +00:00
}
2014-04-17 05:21:50 +00:00
2011-12-20 11:12:52 +00:00
ResetBounds ( false ) ;
2011-08-31 07:40:13 +00:00
}
2011-12-10 12:14:48 +00:00
bool gGraphView : : isEmpty ( )
{
2014-04-17 05:21:50 +00:00
bool res = true ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-08-27 14:08:18 +00:00
gGraph * graph = m_graphs . at ( i ) ;
if ( ! graph - > isSnapshot ( ) & & ! graph - > isEmpty ( ) ) {
2014-04-17 05:21:50 +00:00
res = false ;
2011-12-10 12:14:48 +00:00
break ;
}
}
2014-04-17 05:21:50 +00:00
2011-12-10 12:14:48 +00:00
return res ;
}
2011-10-31 11:55:25 +00:00
void gGraphView : : refreshTimeout ( )
2011-09-03 15:54:27 +00:00
{
2014-04-17 05:21:50 +00:00
if ( this - > isVisible ( ) ) {
2013-09-06 12:42:14 +00:00
redraw ( ) ;
2014-04-17 05:21:50 +00:00
}
2011-09-03 15:54:27 +00:00
}
void gGraphView : : timedRedraw ( int ms )
{
2014-07-21 09:39:26 +00:00
if ( timer - > isActive ( ) ) {
2014-08-29 04:02:16 +00:00
if ( ms = = 0 ) {
2014-07-21 09:39:26 +00:00
timer - > stop ( ) ;
2014-08-29 04:02:16 +00:00
} else {
int m = timer - > remainingTime ( ) ;
if ( m > ms ) {
timer - > stop ( ) ;
} else return ;
}
2013-09-06 12:42:14 +00:00
}
2014-07-21 09:39:26 +00:00
timer - > setSingleShot ( true ) ;
timer - > start ( ms ) ;
2011-09-03 15:54:27 +00:00
}
2011-09-12 17:47:37 +00:00
void gGraphView : : resetLayout ( )
{
2018-04-22 12:06:48 +00:00
int default_height = AppSetting - > graphHeight ( ) ;
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
if ( m_graphs [ i ] ) m_graphs [ i ] - > setHeight ( default_height ) ;
2011-09-12 17:47:37 +00:00
}
2014-04-17 05:21:50 +00:00
2011-09-12 17:47:37 +00:00
updateScale ( ) ;
2014-08-29 04:02:16 +00:00
timedRedraw ( 0 ) ;
2011-09-12 17:47:37 +00:00
}
2011-10-31 11:55:25 +00:00
void gGraphView : : deselect ( )
{
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
2014-07-25 07:53:48 +00:00
if ( m_graphs [ i ] ) m_graphs [ i ] - > deselect ( ) ;
2011-10-31 11:55:25 +00:00
}
}
2011-09-03 15:54:27 +00:00
2014-04-17 05:21:50 +00:00
const quint32 gvmagic = 0x41756728 ;
2014-08-23 09:24:22 +00:00
const quint16 gvversion = 4 ;
2011-11-27 16:07:28 +00:00
void gGraphView : : SaveSettings ( QString title )
{
2014-09-29 14:41:31 +00:00
qDebug ( ) < < " Saving " < < title < < " settings " ;
2014-07-11 12:09:38 +00:00
QString filename = p_profile - > Get ( " {DataFolder}/ " ) + title . toLower ( ) + " .shg " ;
2011-11-27 16:07:28 +00:00
QFile f ( filename ) ;
f . open ( QFile : : WriteOnly ) ;
QDataStream out ( & f ) ;
out . setVersion ( QDataStream : : Qt_4_6 ) ;
out . setByteOrder ( QDataStream : : LittleEndian ) ;
out < < ( quint32 ) gvmagic ;
out < < ( quint16 ) gvversion ;
out < < ( qint16 ) size ( ) ;
2014-04-17 05:21:50 +00:00
for ( qint16 i = 0 ; i < size ( ) ; i + + ) {
2014-08-23 09:24:22 +00:00
gGraph * graph = m_graphs [ i ] ;
if ( ! graph ) continue ;
2014-08-27 14:02:05 +00:00
if ( graph - > isSnapshot ( ) ) continue ;
2014-08-23 09:24:22 +00:00
out < < graph - > name ( ) ;
out < < graph - > height ( ) ;
out < < graph - > visible ( ) ;
out < < graph - > RecMinY ( ) ;
out < < graph - > RecMaxY ( ) ;
out < < graph - > zoomY ( ) ;
out < < ( bool ) graph - > isPinned ( ) ;
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( graph , LT_LineChart ) ) ;
if ( lc ) {
out < < ( quint32 ) LT_LineChart ;
out < < lc - > m_flags_enabled ;
out < < lc - > m_enabled ;
out < < lc - > m_dot_enabled ;
} else {
out < < ( quint32 ) LT_Other ;
}
2014-07-25 07:53:48 +00:00
2011-11-27 16:07:28 +00:00
}
f . close ( ) ;
}
bool gGraphView : : LoadSettings ( QString title )
{
2014-07-11 12:09:38 +00:00
QString filename = p_profile - > Get ( " {DataFolder}/ " ) + title . toLower ( ) + " .shg " ;
2011-11-27 16:07:28 +00:00
QFile f ( filename ) ;
2014-04-17 05:21:50 +00:00
2014-08-11 04:52:14 +00:00
if ( ! f . exists ( ) ) {
return false ;
}
2011-11-27 16:07:28 +00:00
f . open ( QFile : : ReadOnly ) ;
QDataStream in ( & f ) ;
in . setVersion ( QDataStream : : Qt_4_6 ) ;
in . setByteOrder ( QDataStream : : LittleEndian ) ;
quint32 t1 ;
2014-09-11 14:23:08 +00:00
quint16 version ;
2011-11-27 16:07:28 +00:00
in > > t1 ;
2014-04-17 05:21:50 +00:00
if ( t1 ! = gvmagic ) {
2011-11-27 16:07:28 +00:00
qDebug ( ) < < " gGraphView " < < title < < " settings magic doesn't match " < < t1 < < gvmagic ;
return false ;
}
2014-04-17 05:21:50 +00:00
2014-09-11 14:23:08 +00:00
in > > version ;
2014-04-17 05:21:50 +00:00
2014-09-11 14:23:08 +00:00
if ( version < gvversion ) {
2014-07-16 17:23:24 +00:00
qDebug ( ) < < " gGraphView " < < title < < " settings will be upgraded. " ;
2011-11-27 16:07:28 +00:00
}
qint16 siz ;
in > > siz ;
QString name ;
float hght ;
bool vis ;
2014-04-17 05:21:50 +00:00
EventDataType recminy , recmaxy ;
2014-04-05 01:28:07 +00:00
bool pinned ;
2011-11-27 16:07:28 +00:00
2014-04-17 05:21:50 +00:00
short zoomy = 0 ;
2013-10-25 15:25:13 +00:00
2014-08-27 13:42:10 +00:00
QList < gGraph * > neworder ;
2014-04-17 05:21:50 +00:00
QHash < QString , gGraph * > : : iterator gi ;
2011-11-27 16:07:28 +00:00
2014-04-17 05:21:50 +00:00
for ( int i = 0 ; i < siz ; i + + ) {
2011-11-27 16:07:28 +00:00
in > > name ;
in > > hght ;
in > > vis ;
in > > recminy ;
in > > recmaxy ;
2014-04-17 05:21:50 +00:00
if ( gvversion > = 1 ) {
2013-10-25 15:25:13 +00:00
in > > zoomy ;
}
2014-04-17 05:21:50 +00:00
if ( gvversion > = 2 ) {
2014-04-05 01:28:07 +00:00
in > > pinned ;
}
2014-04-17 05:21:50 +00:00
2014-08-23 09:24:22 +00:00
QHash < ChannelID , bool > flags_enabled ;
QHash < ChannelID , bool > plots_enabled ;
QHash < ChannelID , QHash < quint32 , bool > > dot_enabled ;
// Warning: Do not break the follow section up!!!
quint32 layertype ;
if ( gvversion > = 4 ) {
in > > layertype ;
if ( layertype = = LT_LineChart ) {
in > > flags_enabled ;
in > > plots_enabled ;
in > > dot_enabled ;
}
}
2014-07-16 17:12:52 +00:00
gGraph * g = nullptr ;
2014-04-17 05:21:50 +00:00
2014-09-11 14:23:08 +00:00
if ( version < = 2 ) {
continue ;
// // Names were stored as translated strings, so look up title instead.
// g = nullptr;
// for (int z=0; z<m_graphs.size(); ++z) {
// if (m_graphs[z]->title() == name) {
// g = m_graphs[z];
// break;
// }
// }
2011-11-27 16:07:28 +00:00
} else {
2014-07-16 17:12:52 +00:00
gi = m_graphsbyname . find ( name ) ;
if ( gi = = m_graphsbyname . end ( ) ) {
qDebug ( ) < < " Graph " < < name < < " has been renamed or removed " ;
} else {
g = gi . value ( ) ;
}
}
if ( g ) {
2011-11-27 16:07:28 +00:00
neworder . push_back ( g ) ;
g - > setHeight ( hght ) ;
g - > setVisible ( vis ) ;
g - > setRecMinY ( recminy ) ;
g - > setRecMaxY ( recmaxy ) ;
2013-10-25 15:25:13 +00:00
g - > setZoomY ( zoomy ) ;
2014-04-05 01:28:07 +00:00
g - > setPinned ( pinned ) ;
2014-08-23 09:24:22 +00:00
if ( gvversion > = 4 ) {
if ( layertype = = LT_LineChart ) {
gLineChart * lc = dynamic_cast < gLineChart * > ( findLayer ( g , LT_LineChart ) ) ;
if ( lc ) {
lc - > m_flags_enabled = flags_enabled ;
lc - > m_enabled = plots_enabled ;
lc - > m_dot_enabled = dot_enabled ;
}
}
}
2011-11-27 16:07:28 +00:00
}
}
2014-04-17 05:21:50 +00:00
if ( neworder . size ( ) = = m_graphs . size ( ) ) {
m_graphs = neworder ;
2011-11-27 16:07:28 +00:00
}
f . close ( ) ;
2011-11-27 16:35:17 +00:00
updateScale ( ) ;
2011-11-27 16:07:28 +00:00
return true ;
}
2011-11-27 22:36:38 +00:00
gGraph * gGraphView : : findGraph ( QString name )
{
2014-07-16 17:12:52 +00:00
QHash < QString , gGraph * > : : iterator i = m_graphsbyname . find ( name ) ;
2014-04-17 05:21:50 +00:00
2014-07-16 17:12:52 +00:00
if ( i = = m_graphsbyname . end ( ) ) { return nullptr ; }
2014-04-17 05:21:50 +00:00
2011-11-27 22:36:38 +00:00
return i . value ( ) ;
}
2014-07-16 17:12:52 +00:00
gGraph * gGraphView : : findGraphTitle ( QString title )
{
for ( int i = 0 ; i < m_graphs . size ( ) ; + + i ) {
if ( m_graphs [ i ] - > title ( ) = = title ) return m_graphs [ i ] ;
}
return nullptr ;
}
2011-12-01 15:57:06 +00:00
int gGraphView : : visibleGraphs ( )
{
2014-04-17 05:21:50 +00:00
int cnt = 0 ;
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
if ( m_graphs [ i ] - > visible ( ) & & ! m_graphs [ i ] - > isEmpty ( ) ) { cnt + + ; }
2011-12-01 15:57:06 +00:00
}
2014-04-17 05:21:50 +00:00
2011-12-01 15:57:06 +00:00
return cnt ;
}
2014-05-16 10:44:09 +00:00
2014-09-14 15:29:07 +00:00
void gGraphView : : dataChanged ( )
{
for ( int i = 0 ; i < m_graphs . size ( ) ; i + + ) {
m_graphs [ i ] - > dataChanged ( ) ;
}
}
2011-12-20 11:12:52 +00:00
void gGraphView : : redraw ( )
{
2014-05-16 14:08:16 +00:00
# ifdef BROKEN_OPENGL_BUILD
repaint ( ) ;
# else
2015-08-27 01:37:10 +00:00
update ( ) ;
2014-05-16 14:08:16 +00:00
# endif
2011-12-20 11:12:52 +00:00
}