You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1446 lines
44 KiB
1446 lines
44 KiB
/***************************************************************************
|
|
qsplotview.cpp
|
|
-------------------
|
|
begin : 01-January-2000
|
|
copyright : (C) 2000 by Kamil Dobkowski
|
|
email : kamildobk@poczta.onet.pl
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include"qsplotview.h"
|
|
#include"qsdrvqt.h"
|
|
#include"qsdrvhittest.h"
|
|
#include"qsruler.h"
|
|
|
|
#include<qpixmap.h>
|
|
#include<qtimer.h>
|
|
#include<qapplication.h>
|
|
#include<qcursor.h>
|
|
#include<qpaintdevicemetrics.h>
|
|
#include<qprinter.h>
|
|
#include<qslider.h>
|
|
#include<qscrollbar.h>
|
|
#include<qevent.h>
|
|
#include<qlayout.h>
|
|
#include<qpushbutton.h>
|
|
#include<qpopupmenu.h>
|
|
#include<qtabbar.h>
|
|
#include<qinputdialog.h>
|
|
#include<qmessagebox.h>
|
|
|
|
#include<math.h>
|
|
|
|
#ifdef Q_WS_X11
|
|
#include<X11/X.h>
|
|
#include<X11/Xlib.h>
|
|
#endif
|
|
|
|
#define SHADOW_WIDTH 3
|
|
#define SLIDER_WIDTH 16
|
|
#define SCROLLBAR_RANGE 10000.0
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSSelection::QSSelection( QObject *parent )
|
|
: QSCObjectCollection( parent, false )
|
|
{
|
|
m_workbook = NULL;
|
|
m_curr_collection = NULL;
|
|
m_root_collection = NULL;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSSelection::~QSSelection()
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::set( QSCObject *object )
|
|
{
|
|
parametersChanging();
|
|
bool temp = tempAutoUpdatesOff();
|
|
clear();
|
|
if ( object ) {
|
|
set_collection( object );
|
|
add( object );
|
|
}
|
|
tempAutoUpdatesRestore( temp );
|
|
listChanged();
|
|
parametersChanged();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::turn( QSCObject *objectToSwitch )
|
|
{
|
|
if ( find(objectToSwitch) < 0 ) add( objectToSwitch ); else remove( find(objectToSwitch) );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::insert( int position, QSCObject *objectToAdd )
|
|
{
|
|
if ( objectToAdd && find(objectToAdd) < 0 ) {
|
|
if ( !collection() || collection()->find(objectToAdd) < 0 ) clear();
|
|
set_collection( objectToAdd );
|
|
QSCObjectCollection::insert( position, objectToAdd );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::remove( int index )
|
|
{
|
|
if ( object(index) ) {
|
|
QSCObjectCollection::remove( index );
|
|
if ( isEmpty() ) set_collection( NULL );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::set_collection( QSCObject *object )
|
|
{
|
|
if ( m_root_collection ) {
|
|
disconnect( m_root_collection, SIGNAL(sigRemoved(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_object_removed(QSCObjectCollection*,QSCObject*)) );
|
|
}
|
|
if ( object ) {
|
|
m_curr_collection = object->collection();
|
|
m_root_collection = object->rootCollection();
|
|
} else {
|
|
m_curr_collection = NULL;
|
|
m_root_collection = NULL;
|
|
}
|
|
if ( m_root_collection ) {
|
|
connect( m_root_collection, SIGNAL(sigRemoved(QSCObjectCollection*,QSCObject*)), this, SLOT(slot_object_removed(QSCObjectCollection*,QSCObject*)) );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::set_workbook( QSWorkbook *workbook )
|
|
{
|
|
if ( m_workbook != workbook ) {
|
|
if ( !isEmpty() ) clear();
|
|
if ( m_workbook ) disconnect( m_workbook, SIGNAL(sigPageRemoved(QSPage*)), this, SLOT(slot_page_removed(QSPage*)) );
|
|
m_workbook = workbook;
|
|
if ( m_workbook ) connect( m_workbook, SIGNAL(sigPageRemoved(QSPage*)), this, SLOT(slot_page_removed(QSPage*)) );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::slot_object_removed( QSCObjectCollection*, QSCObject *removedObject )
|
|
{
|
|
if ( find(removedObject) >= 0 ) remove( find(removedObject) );
|
|
else
|
|
if ( dynamic_cast<QSCGroup*>(removedObject) ) {
|
|
// if group contains a one object from our selection
|
|
// it must contain all objects so we must clear the whole selection !
|
|
if ( ((QSCGroup*)(removedObject))->objects()->contains(object(0),true) ) clear();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSSelection::slot_page_removed( QSPage *page )
|
|
{
|
|
if ( page->objects() == m_root_collection ) clear();
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
|
|
QSRangeScrollBar::QSRangeScrollBar( QWidget *parent )
|
|
: QScrollBar( 0, 0, 1, 1, 0, QScrollBar::Horizontal, parent )
|
|
{
|
|
m_axes = NULL;
|
|
m_type = QSAxis::UnknownAxisType;
|
|
m_updating_range = false;
|
|
m_updating_scrollbars = false;
|
|
m_min = 0.0;
|
|
m_max = 1.0;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSRangeScrollBar::~QSRangeScrollBar()
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSRangeScrollBar::setAxes( QSAxes *axes, QSAxis::AxisType type )
|
|
{
|
|
m_axes = axes;
|
|
m_type = type;
|
|
updateScrollbar();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSRangeScrollBar::updateScrollbar()
|
|
{
|
|
if ( m_updating_range ) return;
|
|
|
|
m_updating_scrollbars = true;
|
|
|
|
// calculate data range on joined axes in world coordinates
|
|
double min = 0.0;
|
|
double max = 1.0;
|
|
|
|
if ( m_axes && m_type != QSAxis::UnknownAxisType )
|
|
for( int axis_nr=0; axis_nr<m_axes->axisCount(); axis_nr++ ) {
|
|
QSAxis *curr_axis = m_axes->axis(axis_nr);
|
|
if ( curr_axis->type() == m_type && curr_axis->scrollable() ) {
|
|
double data_min = curr_axis->dataToWorld(curr_axis->min(QSAxis::RangeData));
|
|
double data_max = curr_axis->dataToWorld(curr_axis->max(QSAxis::RangeData));
|
|
// Not always data_min < data_max, if axis range is reversed it will be reversed
|
|
// so real data_min is QMIN( data_min, data_max )
|
|
min = QMIN( min, QMIN( data_min, data_max ) );
|
|
max = QMAX( max, QMAX( data_min, data_max ) );
|
|
}
|
|
}
|
|
|
|
// remember for further processing
|
|
m_min = min;
|
|
m_max = max;
|
|
|
|
// visible range in normalized world coordinates ( v_max = v_min + 1.0 )
|
|
double v_min = 0.0 - min;
|
|
|
|
// range on axes in normalized coordinates
|
|
max = max - min;
|
|
min = min - min; // always 0
|
|
|
|
// Map to integer: < 0.0, max > -> < 0, SCROLLBAR_RANGE >
|
|
// slider range <0,max-1.0>
|
|
setRange( 0, int( (max-1.0)/max*SCROLLBAR_RANGE+0.5 ) );
|
|
// page_step = 1.0
|
|
setPageStep( int( 1.0/max*SCROLLBAR_RANGE+0.5 ) );
|
|
|
|
// value = v_min
|
|
int curr_value = int( v_min/max*SCROLLBAR_RANGE+0.5 );
|
|
// reverse direction of the vertical scrollbar
|
|
setValue( orientation() == Horizontal ? curr_value : maxValue() - curr_value );
|
|
|
|
m_updating_scrollbars = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSRangeScrollBar::updateRange()
|
|
{
|
|
if ( m_updating_scrollbars ) return;
|
|
|
|
m_updating_range = true;
|
|
|
|
// reverse direction of the vertical scrollbar
|
|
int curr_value = orientation() == Horizontal ? value() : maxValue() - value();
|
|
|
|
// Map to float: < 0, SCROLLBAR_RANGE > -> < m_min, m_max >
|
|
double v_min = double(curr_value)/SCROLLBAR_RANGE*(m_max-m_min)+m_min;
|
|
double v_max = v_min + 1.0;
|
|
|
|
// some round-offs
|
|
if ( curr_value == maxValue() ) {
|
|
v_min = m_max-1.0;
|
|
v_max = m_max;
|
|
}
|
|
|
|
if ( m_axes && m_type != QSAxis::UnknownAxisType )
|
|
for( int axis_nr=0; axis_nr<m_axes->axisCount(); axis_nr++ ) {
|
|
QSAxis *curr_axis = m_axes->axis(axis_nr);
|
|
if ( curr_axis->type() == m_type && curr_axis->scrollable() ) {
|
|
curr_axis->setRange( curr_axis->worldToData(v_min),
|
|
curr_axis->worldToData(v_max) );
|
|
}
|
|
}
|
|
|
|
m_updating_range = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
//-------------------------------------------------------------//
|
|
|
|
|
|
|
|
QSPlotView::QSPlotView(QWidget *parent, const char *name )
|
|
: QWidget(parent,name)
|
|
{
|
|
m_refresh_buffer = new QTimer( this );
|
|
connect( m_refresh_buffer, SIGNAL(timeout()), this, SLOT(slot_refresh_screen_buffer()) );
|
|
m_screen_buffer_valid = false;
|
|
m_screen_buffer = NULL;
|
|
m_workbook = NULL;
|
|
m_curr_page = NULL;
|
|
m_active_axes = NULL;
|
|
m_ctool = NULL;
|
|
m_active_object = NULL;
|
|
m_tool_activated = false;
|
|
m_tool_activating = false;
|
|
m_screen_buffering = true;
|
|
m_selection = new QSSelection( this );
|
|
connect( m_selection, SIGNAL(sigListChanged()), this, SLOT(slot_selection_changed()) );
|
|
|
|
m_page_margins_visible = true;
|
|
|
|
m_full_page = true;
|
|
m_zoom = 1.0;
|
|
|
|
m_grid_visible = true;
|
|
m_grid_x = 5;
|
|
m_grid_y = 5;
|
|
|
|
m_rulers_visible = true;
|
|
m_hruler = NULL;
|
|
m_vruler = NULL;
|
|
|
|
m_sliders_visible = true;
|
|
m_hscrollbar = NULL;
|
|
m_vscrollbar = NULL;
|
|
|
|
m_page_list = NULL;
|
|
|
|
for( int i=0; i<3; i++ ) {
|
|
m_sliders[i].slider = NULL;
|
|
m_sliders[i].min = 0;
|
|
m_sliders[i].max = 0;
|
|
}
|
|
|
|
for( int i=0; i<2; i++ ) {
|
|
m_scrollbars[i].scrollbar = NULL;
|
|
m_scrollbars[i].type = QSAxis::UnknownAxisType;
|
|
}
|
|
|
|
m_interior = new QWidget( this );
|
|
m_interior->installEventFilter(this);
|
|
m_interior->setBackgroundColor( lightGray );
|
|
m_interior->show();
|
|
|
|
m_shadow = new QWidget( m_interior );
|
|
m_shadow->setBackgroundColor( black );
|
|
|
|
m_canvas = new QWidget( m_interior );
|
|
m_canvas->installEventFilter(this);
|
|
m_canvas->setBackgroundMode( NoBackground );
|
|
|
|
m_layout = new QGridLayout( this, 5, 6 );
|
|
|
|
// scaled main view
|
|
m_layout->setRowStretch( 1, 10 );
|
|
m_layout->setColStretch( 1, 0 );
|
|
m_layout->setColStretch( 2, 10 );
|
|
m_layout->addMultiCellWidget( m_interior, 1, 1, 1, 2 );
|
|
|
|
m_layout->setColStretch( 0, 0 );
|
|
m_layout->setColStretch( 3, 0 );
|
|
m_layout->setColStretch( 4, 0 );
|
|
m_layout->setColStretch( 5, 0 );
|
|
m_layout->setColStretch( 6, 0 );
|
|
|
|
m_layout->setRowStretch( 0, 0 );
|
|
m_layout->setRowStretch( 2, 0 );
|
|
m_layout->setRowStretch( 3, 0 );
|
|
m_layout->setRowStretch( 4, 0 );
|
|
|
|
m_pages.setAutoDelete( FALSE );
|
|
|
|
recreate_gui();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSPlotView::~QSPlotView()
|
|
{
|
|
if ( m_curr_page && m_curr_page->objects()->busy() ) m_curr_page->objects()->stop();
|
|
delete m_ctool;
|
|
delete m_screen_buffer;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setPixmapBuffering( bool enabled )
|
|
{
|
|
m_screen_buffering = enabled;
|
|
set_backstore_internal( !m_screen_buffering );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_selection_changed()
|
|
{
|
|
if ( selection()->count() == 1 ) {
|
|
set_active_object( selection()->object(0), true );
|
|
} else {
|
|
set_active_object( NULL, true );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_gui()
|
|
{
|
|
recreate_rulers();
|
|
recreate_parameter_scrollbars();
|
|
recreate_parameter_sliders();
|
|
recreate_canvas_scrollbars();
|
|
recreate_page_bar();
|
|
adjust_canvas_size();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_rulers()
|
|
{
|
|
if ( m_full_page && m_rulers_visible ) {
|
|
if ( !m_hruler ) m_hruler = new QSRuler( QSRuler::Horizontal, this );
|
|
if ( !m_vruler ) m_vruler = new QSRuler( QSRuler::Vertical, this );
|
|
m_hruler->setUnit( UnitMillimeter );
|
|
m_vruler->setUnit( UnitMillimeter );
|
|
m_layout->addMultiCellWidget( m_hruler, 0, 0, 1, 2 );
|
|
m_layout->addWidget( m_vruler, 1, 0 );
|
|
m_hruler->show();
|
|
m_vruler->show();
|
|
} else {
|
|
delete m_hruler;
|
|
delete m_vruler;
|
|
m_hruler = NULL;
|
|
m_vruler = NULL;
|
|
}
|
|
|
|
update_rulers();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::update_rulers()
|
|
// sync rulers with canvas position
|
|
{
|
|
if ( m_hruler && m_vruler ) {
|
|
m_hruler->setZoom( (float )m_zoom );
|
|
m_vruler->setZoom( (float )m_zoom );
|
|
m_hruler->updateVisibleArea( -m_canvas->x(), -m_canvas->y() );
|
|
m_vruler->updateVisibleArea( -m_canvas->x(), -m_canvas->y() );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_parameter_scrollbars()
|
|
{
|
|
// create only sliders which have type != UnknownAxiType
|
|
for( int i=0; i<2; i++ ) {
|
|
if ( m_active_axes && m_sliders_visible && !m_full_page && m_scrollbars[i].type != QSAxis::UnknownAxisType ) {
|
|
if ( !m_scrollbars[i].scrollbar ) m_scrollbars[i].scrollbar = new QSRangeScrollBar( this );
|
|
connect( m_scrollbars[i].scrollbar, SIGNAL(sliderPressed() ), this, SLOT(slot_scrollbar_pressed() ) );
|
|
connect( m_scrollbars[i].scrollbar, SIGNAL(sliderReleased()), this, SLOT(slot_scrollbar_released()) );
|
|
} else {
|
|
delete m_scrollbars[i].scrollbar; m_scrollbars[i].scrollbar = NULL;
|
|
}
|
|
}
|
|
|
|
if ( m_scrollbars[0].scrollbar ) {
|
|
connect( m_scrollbars[0].scrollbar, SIGNAL(valueChanged(int)), this, SLOT(slot_hscrollbar_moved(int)) );
|
|
m_scrollbars[0].scrollbar->setOrientation( QScrollBar::Horizontal );
|
|
m_layout->addMultiCellWidget( m_scrollbars[0].scrollbar, 3, 3, 1, 2 );
|
|
m_scrollbars[0].scrollbar->show();
|
|
}
|
|
if ( m_scrollbars[1].scrollbar ) {
|
|
connect( m_scrollbars[1].scrollbar, SIGNAL(valueChanged(int)), this, SLOT(slot_vscrollbar_moved(int)) );
|
|
m_scrollbars[1].scrollbar->setOrientation( QScrollBar::Vertical );
|
|
m_layout->addWidget( m_scrollbars[1].scrollbar, 1, 4 );
|
|
m_scrollbars[1].scrollbar->show();
|
|
}
|
|
|
|
update_parameter_scrollbars();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::update_parameter_scrollbars()
|
|
// sync scrollbars with parameter value
|
|
{
|
|
if ( m_scrollbars[0].scrollbar ) m_scrollbars[0].scrollbar->setAxes( m_active_axes, m_scrollbars[0].type );
|
|
if ( m_scrollbars[1].scrollbar ) m_scrollbars[1].scrollbar->setAxes( m_active_axes, m_scrollbars[1].type );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_hscrollbar_moved( int )
|
|
{
|
|
m_scrollbars[0].scrollbar->updateRange();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_vscrollbar_moved( int )
|
|
{
|
|
m_scrollbars[1].scrollbar->updateRange();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_parameter_sliders()
|
|
{
|
|
for( int i=0; i<3; i++ ) {
|
|
// create only sliders with non empty property value and with min != max
|
|
if ( !m_full_page && m_sliders_visible && !m_sliders[i].property.isEmpty() && m_sliders[i].min != m_sliders[i].max ) {
|
|
if ( m_sliders[i].slider == NULL ) {
|
|
m_sliders[i].slider = new QSlider( m_sliders[i].min, m_sliders[i].max, 1, m_sliders[i].min, QSlider::Vertical, this );
|
|
connect( m_sliders[i].slider, SIGNAL(sliderPressed() ), this, SLOT(slot_slider_pressed() ) );
|
|
connect( m_sliders[i].slider, SIGNAL(sliderReleased()), this, SLOT(slot_slider_released()) );
|
|
}
|
|
} else {
|
|
delete m_sliders[i].slider; m_sliders[i].slider = NULL;
|
|
}
|
|
}
|
|
|
|
// Horizontal slider
|
|
if ( m_sliders[0].slider ) {
|
|
connect( m_sliders[0].slider, SIGNAL(valueChanged(int)), this, SLOT(slot_hslider_moved(int)) );
|
|
m_sliders[0].slider->setFixedHeight( SLIDER_WIDTH );
|
|
m_sliders[0].slider->setOrientation( QSlider::Horizontal );
|
|
m_layout->addMultiCellWidget( m_sliders[0].slider, 4, 4, 1, 2 );
|
|
m_sliders[0].slider->show();
|
|
}
|
|
// Vertical slider
|
|
if ( m_sliders[1].slider ) {
|
|
connect( m_sliders[1].slider, SIGNAL(valueChanged(int)), this, SLOT(slot_vslider_moved(int)) );
|
|
m_sliders[1].slider->setFixedWidth( SLIDER_WIDTH );
|
|
m_layout->addWidget(m_sliders[1].slider, 1, 5 );
|
|
m_sliders[1].slider->show();
|
|
}
|
|
// Additional slider
|
|
if ( m_sliders[2].slider ) {
|
|
connect( m_sliders[2].slider, SIGNAL(valueChanged(int)), this, SLOT(slot_aslider_moved(int)) );
|
|
m_sliders[2].slider->setFixedWidth( SLIDER_WIDTH );
|
|
m_layout->addWidget(m_sliders[2].slider, 1, 6 );
|
|
m_sliders[2].slider->show();
|
|
}
|
|
|
|
update_parameter_sliders();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::update_parameter_sliders()
|
|
// sync sliders with parameter values
|
|
{
|
|
if ( m_active_axes ) for ( int i=0; i<3; i++ )
|
|
if ( m_sliders[i].slider ) m_sliders[i].slider->setValue( m_active_axes->property( m_sliders[i].property ).toInt() );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_hslider_moved( int value )
|
|
{
|
|
if ( m_active_axes ) m_active_axes->setProperty( m_sliders[HorizontalSlider].property, value );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_vslider_moved( int value )
|
|
{
|
|
if ( m_active_axes ) m_active_axes->setProperty( m_sliders[VerticalSlider].property, value );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_aslider_moved( int value )
|
|
{
|
|
if ( m_active_axes ) m_active_axes->setProperty( m_sliders[AdditionalSlider].property, value );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_slider_pressed()
|
|
{
|
|
if ( m_active_axes ) m_active_axes->setAxesOnly( true );
|
|
emit sigSliderPressed();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_slider_released()
|
|
{
|
|
if ( m_active_axes ) m_active_axes->setAxesOnly( false );
|
|
emit sigSliderReleased();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_scrollbar_pressed()
|
|
{
|
|
emit sigScrollBarPressed();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_scrollbar_released()
|
|
{
|
|
emit sigScrollBarReleased();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_canvas_scrollbars()
|
|
{
|
|
if ( m_full_page ) {
|
|
// horizontal scrollbar
|
|
if ( !m_hscrollbar ) m_hscrollbar = new QScrollBar( 0, 0, 1, 1, 0, QScrollBar::Horizontal, this );
|
|
m_hscrollbar->setOrientation( QScrollBar::Horizontal );
|
|
connect( m_hscrollbar, SIGNAL(valueChanged(int)), this, SLOT(slot_update_canvas_pos(int)) );
|
|
m_layout->addWidget(m_hscrollbar, 2, 2 );
|
|
m_hscrollbar->show();
|
|
// veritcal slider
|
|
if ( !m_vscrollbar ) m_vscrollbar = new QScrollBar( 0, 0, 1, 1, 0, QScrollBar::Vertical, this );
|
|
m_vscrollbar->setOrientation( QScrollBar::Vertical );
|
|
connect( m_vscrollbar, SIGNAL(valueChanged(int)), this, SLOT(slot_update_canvas_pos(int)) );
|
|
m_layout->addWidget(m_vscrollbar, 1, 3 );
|
|
m_vscrollbar->show();
|
|
} else {
|
|
delete m_hscrollbar; m_hscrollbar = NULL;
|
|
delete m_vscrollbar; m_vscrollbar = NULL;
|
|
}
|
|
|
|
update_canvas_scrollbars();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::update_canvas_scrollbars()
|
|
// sync scrollbars with cancvas pos/size value
|
|
{
|
|
if ( m_hscrollbar ) {
|
|
m_hscrollbar->setRange( -5, QMAX(-5,m_canvas->width()-m_interior->width()+5) );
|
|
m_hscrollbar->setPageStep( m_interior->width() );
|
|
m_hscrollbar->setValue( -m_canvas->x() );
|
|
}
|
|
if ( m_vscrollbar ) {
|
|
m_vscrollbar->setRange( -5, QMAX(-5,m_canvas->height()-m_interior->height()+5) );
|
|
m_vscrollbar->setPageStep( m_interior->height() );
|
|
m_vscrollbar->setValue( -m_canvas->y() );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_update_canvas_pos(int)
|
|
// sync canvas pos with sliders
|
|
{
|
|
if ( m_full_page && m_hscrollbar && m_vscrollbar ) {
|
|
if ( m_canvas->width() <= m_interior->width() ) m_canvas->move( (m_interior->width()-m_canvas->width())/2,m_canvas->y() );
|
|
else m_canvas->move( -m_hscrollbar->value(),m_canvas->y() );
|
|
if ( m_canvas->height() <= m_interior->height() ) m_canvas->move( m_canvas->x(), (m_interior->height()-m_canvas->height())/2 );
|
|
else m_canvas->move( m_canvas->x(), -m_vscrollbar->value() );
|
|
m_shadow->move( m_canvas->x()+SHADOW_WIDTH, m_canvas->y()+SHADOW_WIDTH );
|
|
update_rulers();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::recreate_page_bar()
|
|
{
|
|
// create page list
|
|
if ( m_full_page ) {
|
|
if ( !m_page_list ) {
|
|
m_page_list = new QTabBar( this );
|
|
m_layout->addWidget( m_page_list, 2, 1 );
|
|
m_page_list->setShape( QTabBar::TriangularBelow );
|
|
m_page_list->setFixedWidth( 20 );
|
|
m_page_list->setFixedHeight( 10 );
|
|
m_page_list->installEventFilter( this ); // show page management popup
|
|
m_page_list->show();
|
|
connect( m_page_list, SIGNAL(selected(int)), this, SLOT(slot_page_tab_selected(int)) );
|
|
}
|
|
|
|
// remove all tabs
|
|
QIntDictIterator<QSPage> it( m_pages );
|
|
while ( it.current() ) {
|
|
QTab *curr_tab = m_page_list->tab( it.currentKey() );
|
|
m_page_list->removeTab( curr_tab );
|
|
// should I or shouldn't I
|
|
//delete curr_tab;
|
|
++it;
|
|
}
|
|
m_pages.clear();
|
|
|
|
if ( m_workbook ) {
|
|
for( int page_nr=0; page_nr<m_workbook->pageCount(); page_nr++ ) {
|
|
int id = m_page_list->insertTab( new QTab(m_workbook->page(page_nr)->title()), page_nr );
|
|
m_pages.insert( id, m_workbook->page(page_nr) );
|
|
}
|
|
m_page_list->layoutTabs();
|
|
m_page_list->setFixedWidth( QMAX(20,QMIN(m_page_list->sizeHint().width(),250)) );
|
|
m_page_list->setFixedHeight( QMAX(10,m_page_list->sizeHint().height()) );
|
|
}
|
|
} else {
|
|
delete m_page_list; m_page_list = NULL; m_pages.clear();
|
|
}
|
|
|
|
update_page_bar();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::update_page_bar()
|
|
// sync page_bar with current page value
|
|
{
|
|
QIntDictIterator<QSPage> it( m_pages );
|
|
while ( it.current() ) {
|
|
if ( it.current() == currentPage() ) {
|
|
if ( m_page_list ) m_page_list->setCurrentTab( it.currentKey() );
|
|
return;
|
|
}
|
|
++it;
|
|
}
|
|
if ( m_page_list ) m_page_list->setCurrentTab( -1 );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_tab_selected( int tab_id )
|
|
{
|
|
if ( m_workbook ) setCurrentPage( m_workbook->pageFind(m_pages[tab_id]) );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::updateCanvas()
|
|
{
|
|
m_screen_buffer_valid = false;
|
|
m_canvas->update();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::adjust_canvas_size()
|
|
// resize page to the correct size
|
|
{
|
|
int width;
|
|
int height;
|
|
|
|
if ( m_full_page ) {
|
|
// default values
|
|
int w_mm = 210;
|
|
int h_mm = 297;
|
|
// take page size from workbook
|
|
if ( m_workbook && m_workbook->printer() ) {
|
|
QPaintDeviceMetrics pdm(m_workbook->printer());
|
|
w_mm = pdm.widthMM();
|
|
h_mm = pdm.heightMM();
|
|
}
|
|
QRect r( 0, 0,
|
|
int(QSCoord::mmToPixels(w_mm,dpi())+0.5),
|
|
int(QSCoord::mmToPixels(h_mm,dpi())+0.5) );
|
|
width = r.width();
|
|
height = r.height();
|
|
} else {
|
|
// single view mode
|
|
width = m_interior->width();
|
|
height = m_interior->height();
|
|
}
|
|
|
|
m_canvas->resize( width, height );
|
|
|
|
if ( m_canvas->width() <= m_interior->width() ) {
|
|
int x = ( m_interior->width() - m_canvas->width() ) / 2;
|
|
int y = m_canvas->y();
|
|
m_canvas->move( x, y );
|
|
} else {
|
|
if ( m_canvas->x() > 0 ) m_canvas->move( 0, m_canvas->y() );
|
|
}
|
|
|
|
if ( m_canvas->height() <= m_interior->height() ) {
|
|
int x = m_canvas->x();
|
|
int y = ( m_interior->height() - m_canvas->height() ) / 2;
|
|
m_canvas->move( x, y );
|
|
} else {
|
|
if ( m_canvas->y() > 0 ) m_canvas->move( m_canvas->x(), 0 );
|
|
}
|
|
|
|
m_shadow->move( m_canvas->x()+SHADOW_WIDTH,
|
|
m_canvas->y()+SHADOW_WIDTH );
|
|
m_shadow->resize( m_canvas->size() );
|
|
|
|
// invalidate pixmap buffer
|
|
if ( m_screen_buffer &&
|
|
( m_screen_buffer->width() != m_canvas->width() ||
|
|
m_screen_buffer->height() != m_canvas->height() ) ) m_screen_buffer_valid = false;
|
|
|
|
// hide pages if there is no current page
|
|
if ( !m_curr_page ) {
|
|
m_shadow->hide();
|
|
m_canvas->hide();
|
|
} else {
|
|
m_shadow->show();
|
|
m_canvas->show();
|
|
}
|
|
|
|
if ( m_full_page ) {
|
|
update_canvas_scrollbars();
|
|
update_rulers();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setWorkbook( QSWorkbook *workbook )
|
|
// wach out canvas size changes - printer()
|
|
{
|
|
if ( m_workbook != workbook ) {
|
|
if ( m_workbook ) {
|
|
disconnect( m_workbook, SIGNAL(sigPrinterChanged()), this, SLOT(adjust_canvas_size()) );
|
|
disconnect( m_workbook, SIGNAL(sigPageRemoved(QSPage*)), this, SLOT(slot_page_removed(QSPage*)) );
|
|
disconnect( m_workbook, SIGNAL(sigPageAdded(QSPage*)), this, SLOT(slot_page_added(QSPage*)) );
|
|
disconnect( m_workbook, SIGNAL(sigPageOrder()), this, SLOT(slot_page_order()) );
|
|
disconnect( m_workbook, SIGNAL(sigPageListChanged()), this, SLOT(slot_page_list_changed()) );
|
|
disconnect( m_workbook, SIGNAL(sigObjectRemoved(QSCObject*)), this, SLOT(slot_object_removed(QSCObject*)) );
|
|
}
|
|
m_workbook = workbook;
|
|
m_selection->set_workbook( workbook );
|
|
if ( m_workbook ) {
|
|
connect( m_workbook, SIGNAL(sigPrinterChanged()), this, SLOT(adjust_canvas_size()) );
|
|
connect( m_workbook, SIGNAL(sigPageRemoved(QSPage*)), this, SLOT(slot_page_removed(QSPage*)) );
|
|
connect( m_workbook, SIGNAL(sigPageAdded(QSPage*)), this, SLOT(slot_page_added(QSPage*)) );
|
|
connect( m_workbook, SIGNAL(sigPageOrder()), this, SLOT(slot_page_order()) );
|
|
connect( m_workbook, SIGNAL(sigPageListChanged()), this, SLOT(slot_page_list_changed()) );
|
|
connect( m_workbook, SIGNAL(sigObjectRemoved(QSCObject*)), this, SLOT(slot_object_removed(QSCObject*)) );
|
|
}
|
|
recreate_page_bar(); // new number of pages
|
|
adjust_canvas_size(); // new printer() - page size
|
|
setCurrentPage( 0 ); // new current page
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_removed( QSPage *page )
|
|
{
|
|
//if ( page->objectFind(activeObject())>=0 ) setActiveObject( NULL );
|
|
// page isn't deleted yet so we can disconnect all signals safely
|
|
if ( page == currentPage() ) setCurrentPage( 0 );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_added( QSPage *page )
|
|
{
|
|
//recreate_page_bar();
|
|
if ( currentPage() == NULL ) setCurrentPage( m_workbook->pageFind(page) );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_order()
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_list_changed()
|
|
{
|
|
recreate_page_bar();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_object_removed( QSCObject * )
|
|
{
|
|
// object isnt deleted yet so we can disconnect all signals safely
|
|
//if ( object == activeObject() ) setActiveObject( NULL );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setCurrentPage( int index )
|
|
{
|
|
QSPage *new_page = m_workbook ? m_workbook->page(index) : NULL;
|
|
if ( new_page != m_curr_page ) {
|
|
if ( m_curr_page && m_curr_page->objects()->busy() ) m_curr_page->objects()->stop();
|
|
deactivate_tool();
|
|
// hope that page isn't deleted yet
|
|
if ( m_curr_page ) {
|
|
disconnect( m_curr_page, SIGNAL(sigPageChanged()), this, SLOT(updateCanvas()) );
|
|
disconnect( m_curr_page, SIGNAL(sigTitleChanged(const QString&)), this, SLOT(slot_curr_page_title_changed(const QString&)) );
|
|
disconnect( m_curr_page->objects(), SIGNAL(sigListChanged()), this, SLOT(slot_curr_page_object_list_changed()) );
|
|
}
|
|
m_curr_page = new_page;
|
|
if ( m_curr_page ) {
|
|
connect( m_curr_page, SIGNAL(sigPageChanged()), this, SLOT(updateCanvas()) );
|
|
connect( m_curr_page, SIGNAL(sigTitleChanged(const QString&)), this, SLOT(slot_curr_page_title_changed(const QString&)) );
|
|
connect( m_curr_page->objects(), SIGNAL(sigListChanged()), this, SLOT(slot_curr_page_object_list_changed()) );
|
|
}
|
|
update_page_bar();
|
|
activate_tool(); // page can't change when tool is active
|
|
adjust_canvas_size(); // hide page if is null
|
|
updateCanvas();
|
|
emit sigCurrentPageChanged();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_curr_page_object_list_changed()
|
|
{
|
|
emit sigCurrentPageObjectListChanged();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::set_active_object( QSCObject *o, bool )
|
|
{
|
|
if ( m_active_object != o ) {
|
|
//if ( !tool ) deactivate_tool();
|
|
m_active_object = o;
|
|
set_active_axes( o ? o->parentAxes() : NULL );
|
|
//if ( !tool ) activate_tool();
|
|
emit sigActiveObjectChanged();
|
|
if ( !m_full_page ) updateCanvas();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::activate_tool()
|
|
{
|
|
if ( m_ctool && !m_tool_activated && !m_tool_activating ) {
|
|
// if in activate() or deactivate() you change active axes
|
|
// there can appear infinity loop ->set_active_axes -> deactivate -> set_active_axes ...
|
|
m_tool_activating = true;
|
|
m_tool_activated = true;
|
|
m_ctool->activate(this);
|
|
m_tool_activating = false;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::deactivate_tool()
|
|
{
|
|
if ( m_ctool && m_tool_activated && !m_tool_activating ) {
|
|
m_tool_activating = true;
|
|
m_tool_activated = false;
|
|
m_ctool->deactivate();
|
|
// clean after tool - set default values.
|
|
m_canvas->setCursor( ArrowCursor );
|
|
m_canvas->setFocusPolicy(QWidget::NoFocus);
|
|
m_tool_activating = false;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::set_active_axes( QSAxes *axes )
|
|
{
|
|
if ( m_active_axes != axes ) {
|
|
deactivate_tool();
|
|
clean();
|
|
m_active_axes = axes;
|
|
init();
|
|
activate_tool();
|
|
emit sigActiveAxesChanged();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::init()
|
|
// called after new active axes has been set
|
|
{
|
|
if ( m_active_axes ) {
|
|
connect(m_active_axes,SIGNAL(sigUpdate()),this,SLOT(slot_active_axes_modified()) );
|
|
connect(m_active_axes,SIGNAL(sigRangesValid()),this,SLOT(slot_active_axes_ranges_changed()) );
|
|
connect(m_active_axes,SIGNAL(sigChildRemoved(QSData*)),this,SLOT(slot_active_axes_changed(QSData*)));
|
|
connect(m_active_axes,SIGNAL(sigChildAdded(QSData*)),this,SLOT(slot_active_axes_changed(QSData*)));
|
|
connect(m_active_axes,SIGNAL(sigChildOrder()),this,SLOT(slot_active_axes_order()));
|
|
}
|
|
|
|
set_backstore_internal( !m_screen_buffering );
|
|
update_parameter_scrollbars();
|
|
update_parameter_sliders();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::clean()
|
|
// called when active axes are to be changed
|
|
{
|
|
if ( m_active_axes ) {
|
|
disconnect(m_active_axes, SIGNAL(sigUpdate()), this, SLOT(slot_active_axes_modified()) );
|
|
disconnect(m_active_axes,SIGNAL(sigRangesValid()),this,SLOT(slot_active_axes_ranges_changed()));
|
|
disconnect(m_active_axes,SIGNAL(sigChildRemoved(QSData*)),this,SLOT(slot_active_axes_changed(QSData*)));
|
|
disconnect(m_active_axes,SIGNAL(sigChildAdded(QSData*)),this,SLOT(slot_active_axes_changed(QSData*)));
|
|
disconnect(m_active_axes,SIGNAL(sigChildOrder()),this,SLOT(slot_active_axes_order()));
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_active_axes_changed( QSData * )
|
|
{
|
|
emit sigActiveAxesDatasetsChanged();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_active_axes_order()
|
|
{
|
|
emit sigActiveAxesDatasetsChanged();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_active_axes_modified()
|
|
{
|
|
update_parameter_sliders();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_active_axes_ranges_changed()
|
|
// called EVERY times plot is redrawn ( not only when ranges really change )
|
|
{
|
|
update_parameter_scrollbars();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSCObject *QSPlotView::objectAt( const QPoint& p, bool recursive )
|
|
{
|
|
QSCObject *result = NULL;
|
|
if ( m_full_page && m_curr_page ) {
|
|
QSPt2f pos( p.x(), p.y() );
|
|
QSDrvHitTest drv(pos);
|
|
drv.setDC(new QPainter(m_canvas),dpi(),true);
|
|
drv.startDrawing(); // needed
|
|
result = m_curr_page->objects()->objectAt(pos,&drv,recursive);
|
|
} else {
|
|
if ( m_active_axes ) return m_active_axes->shadowObject();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setGridSpacing( int x_mm, int y_mm )
|
|
{
|
|
if ( m_grid_x != x_mm ||
|
|
m_grid_y != y_mm ) {
|
|
m_grid_x = x_mm;
|
|
m_grid_y = y_mm;
|
|
updateCanvas();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setGridVisible( bool visible )
|
|
{
|
|
if ( m_grid_visible != visible ) {
|
|
m_grid_visible = visible;
|
|
updateCanvas();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setPageMarginsVisible( bool visible )
|
|
{
|
|
if ( m_page_margins_visible != visible ) {
|
|
m_page_margins_visible = visible;
|
|
updateCanvas();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setRulersVisible( bool visible )
|
|
{
|
|
if ( m_rulers_visible != visible ) {
|
|
m_rulers_visible = visible;
|
|
recreate_rulers();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setFullPage( bool enabled )
|
|
{
|
|
if ( m_full_page != enabled ) {
|
|
deactivate_tool();
|
|
m_full_page = enabled;
|
|
recreate_gui(); // hide rulers/scrollbars - show sliders
|
|
adjust_canvas_size(); // fit/unfit canvas to the view area
|
|
activate_tool();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setZoom( double new_zoom )
|
|
{
|
|
if ( new_zoom >= 0.1 && new_zoom < 5.0 ) {
|
|
deactivate_tool();
|
|
m_zoom = new_zoom;
|
|
adjust_canvas_size();
|
|
activate_tool();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::bindSlider( QSPlotView::SliderType t, const char* property, int min, int max )
|
|
{
|
|
m_sliders[t].property = property;
|
|
m_sliders[t].min = min;
|
|
m_sliders[t].max = max;
|
|
recreate_parameter_sliders();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::bindScrollBar( QSPlotView::ScrollBarType t, QSAxis::AxisType type )
|
|
{
|
|
m_scrollbars[t].type = type;
|
|
recreate_parameter_scrollbars();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setSlidersVisible( bool visible )
|
|
{
|
|
if ( m_sliders_visible != visible ) {
|
|
m_sliders_visible = visible;
|
|
recreate_parameter_scrollbars();
|
|
recreate_parameter_sliders();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::setTool( QSTool *t )
|
|
{
|
|
if ( t != m_ctool ) {
|
|
deactivate_tool();
|
|
delete m_ctool;
|
|
m_ctool = t;
|
|
if ( m_ctool ) {
|
|
activate_tool();
|
|
m_canvas->setMouseTracking(TRUE);
|
|
} else {
|
|
m_canvas->setMouseTracking(FALSE);
|
|
showUserMessage( QString::null );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::draw_tool()
|
|
// tool can provide its own drawing procedure ( handles, cursors, etc. )
|
|
// this is called after page is drawn
|
|
{
|
|
//emit message( "Time " + QString::number(time.msecsTo(QTime::currentTime()))+" ms." );
|
|
if ( m_ctool && m_tool_activated ) m_ctool->draw();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
bool QSPlotView::eventFilter( QObject *o, QEvent *e )
|
|
{
|
|
if ( o == m_canvas ) {
|
|
// why not working in switch-case - strange bug in Qt ??
|
|
// simply ignore Focus events ( no redraws when focus changes !! )
|
|
if ( dynamic_cast<QFocusEvent *>(e) ) return TRUE;
|
|
switch( e->type() ) {
|
|
// avoid some unwise clip restrictions in Qt
|
|
case QEvent::Paint:
|
|
QApplication::postEvent( m_canvas, new QEvent(QEvent::User) );
|
|
return TRUE;
|
|
// here we have no permament clip area.
|
|
case QEvent::User:
|
|
draw_page(); return TRUE;
|
|
// turn on X11- backstoring
|
|
case QEvent::Show:
|
|
set_backstore_internal( !m_screen_buffering ); break;
|
|
// do not repaint if m_canvas gets focus.
|
|
// - repainting is too time-expensive
|
|
// ( OK, we block all focus events ! ).
|
|
//case QEvent::FocusIn:
|
|
//case QEvent::FocusOut:
|
|
// pass all events to the tool currently active
|
|
default:
|
|
if ( m_ctool && m_tool_activated ) return m_ctool->canvasEvent( e );
|
|
}
|
|
}
|
|
else if ( o == m_interior ) {
|
|
// in single view mode canvas fits to the view area
|
|
if ( e->type() == QEvent::Resize ) {
|
|
adjust_canvas_size();
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if ( o == m_page_list && m_page_list ) {
|
|
if ( e->type() == QEvent::MouseButtonPress )
|
|
if ( ((QMouseEvent *)e)->button() == QEvent::RightButton ) emit sigPageBarClicked();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
bool QSPlotView::confirm( const QString& message )
|
|
{
|
|
return QMessageBox::warning( NULL, tr("Confirmation"), message, QMessageBox::Yes, QMessageBox::No, 0 ) == QMessageBox::Yes;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::draw_page()
|
|
{
|
|
// just update screen from a buffer if the buffer exists
|
|
if ( m_screen_buffering && m_screen_buffer && m_screen_buffer_valid ) {
|
|
slot_refresh_screen_buffer();
|
|
return;
|
|
}
|
|
|
|
// we must draw all from the begining
|
|
// stop all pending drawing operations
|
|
if ( m_curr_page &&
|
|
m_curr_page->objects()->busy() )
|
|
m_curr_page->objects()->stop();
|
|
|
|
if ( m_active_axes &&
|
|
m_active_axes->shadowObject()->busy() )
|
|
m_active_axes->shadowObject()->stop();
|
|
|
|
// delete an old screen buffer
|
|
delete m_screen_buffer; m_screen_buffer = NULL;
|
|
|
|
// paint device can be m_screen_buffer or directly m_canvas
|
|
QPaintDevice *paint_device;
|
|
if ( m_screen_buffering ) {
|
|
m_screen_buffer = new QPixmap( m_canvas->width(), m_canvas->height() );
|
|
m_screen_buffer_valid = true;
|
|
paint_device = m_screen_buffer;
|
|
} else {
|
|
paint_device = m_canvas;
|
|
}
|
|
|
|
// ok start flushing bitmap to screen at given intervals
|
|
if ( m_screen_buffering ) m_refresh_buffer->start( 300 );
|
|
// draw page - can stop timer if there is no jobs in the background
|
|
if ( m_full_page ) draw_full_page( paint_device ); else draw_single_view( paint_device );
|
|
//
|
|
if ( !m_screen_buffering ) draw_tool();
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::draw_single_view( QPaintDevice *paint_device )
|
|
{
|
|
QPainter p( paint_device );
|
|
QRect r = m_canvas->rect();
|
|
|
|
// draw margins
|
|
int mw = r.width() * 15 / 100;
|
|
int mh = r.height() * 15 / 100;
|
|
|
|
QRect m;
|
|
m = r; m.setBottom( m.top()+mh ); p.fillRect( m, white );
|
|
m = r; m.setTop( m.bottom()-mh ); p.fillRect( m, white );
|
|
m = r; m.setRight( m.left()+mw ); p.fillRect( m, white );
|
|
m = r; m.setLeft( m.right()-mw ); p.fillRect( m, white );
|
|
|
|
r.setTop( r.top()+mh );
|
|
r.setBottom( r.bottom()-mh );
|
|
r.setLeft( r.left()+mw );
|
|
r.setRight( r.right()-mw );
|
|
|
|
if ( m_active_axes ) {
|
|
m_perf_monitor.start();
|
|
connect( m_active_axes, SIGNAL(sigDrawEnds()), this, SLOT(slot_axes_draw_ends()) );
|
|
m_active_axes->setCanvasRect( QSRectf( r.x(), r.y(), r.width(), r.height() ) );
|
|
m_active_axes->paintPlot( &p, dpi(), false, false );
|
|
} else {
|
|
p.fillRect( r, white );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::draw_full_page( QPaintDevice *paint_device )
|
|
{
|
|
QPainter p( paint_device );
|
|
|
|
// page color - always white
|
|
p.fillRect( m_canvas->rect(), white );
|
|
|
|
// draw margins
|
|
if ( m_workbook && m_workbook->printer() ) {
|
|
QRect margs = m_canvas->rect();
|
|
|
|
// draw frame
|
|
p.setPen( black );
|
|
p.setBrush( NoBrush );
|
|
p.drawRect( margs );
|
|
|
|
// draw margins
|
|
QPaintDeviceMetrics pdm(m_workbook->printer());
|
|
int mw = m_workbook->printer()->margins().width() * m_canvas->width() / pdm.width();
|
|
int mh = m_workbook->printer()->margins().height() * m_canvas->height() / pdm.height();
|
|
|
|
margs.setTop( mh );
|
|
margs.setLeft( mw );
|
|
margs.setRight( margs.right() - mw + 1 );
|
|
margs.setBottom( margs.bottom() - mh + 1 );
|
|
|
|
p.setBrush( NoBrush );
|
|
p.setPen( QPen( blue, 0, DotLine ) );
|
|
if ( m_page_margins_visible ) p.drawRect( margs );
|
|
}
|
|
|
|
if ( m_grid_visible ) draw_grid( &p );
|
|
if ( m_curr_page ) {
|
|
connect( m_curr_page->objects(), SIGNAL(sigDrawEnds()), this, SLOT(slot_page_draw_ends()) );
|
|
m_curr_page->paint( &p, dpi(), false );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::draw_grid( QPainter *p )
|
|
{
|
|
double x_step = QSCoord::mmToPixels((double)m_grid_x,dpi());
|
|
double y_step = QSCoord::mmToPixels((double)m_grid_y,dpi());
|
|
double curr_y_pos = y_step;
|
|
double curr_x_pos = x_step;
|
|
if ( x_step >= 2.0 && y_step >= 2.0 ) {
|
|
p->setPen( gray );
|
|
while( curr_y_pos < m_canvas->rect().bottom() ) {
|
|
while ( curr_x_pos < m_canvas->rect().right() ) {
|
|
p->drawPoint( int(curr_x_pos+0.5), int(curr_y_pos+0.5) );
|
|
curr_x_pos += x_step;
|
|
}
|
|
curr_x_pos = x_step;
|
|
curr_y_pos += y_step;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::showUserMessage( const QString& msg )
|
|
{
|
|
emit message( msg );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::set_backstore_internal( bool enabled )
|
|
{
|
|
#ifdef Q_WS_X11
|
|
XSetWindowAttributes attributes;
|
|
// NotUseful, WhenMapped or Always
|
|
if ( enabled ) attributes.backing_store = Always;
|
|
else attributes.backing_store = NotUseful;
|
|
XChangeWindowAttributes( m_canvas->x11Display(),
|
|
m_canvas->winId(),
|
|
CWBackingStore,
|
|
&attributes );
|
|
#endif
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
bool QSPlotView::backstore_internal()
|
|
{
|
|
bool result = false;
|
|
#ifdef Q_WS_X11
|
|
XWindowAttributes attributes;
|
|
// NotUseful, WhenMapped or Always
|
|
XGetWindowAttributes( m_canvas->x11Display(), m_canvas->winId(), &attributes );
|
|
result = (attributes.backing_store != NotUseful );
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
QSCObjectCollection *QSPlotView::activeCollection() const
|
|
{
|
|
if ( currentPage() &&
|
|
dynamic_cast<QSCGroup*>(activeObject()) &&
|
|
currentPage()->objects() == activeObject()->rootCollection() ) {
|
|
return ((QSCGroup *)activeObject())->objects();
|
|
}
|
|
else if ( currentPage() ) {
|
|
return currentPage()->objects();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_axes_draw_ends()
|
|
{
|
|
if ( !m_full_page ) showUserMessage( QString(" Drawing time ")+QString::number(m_perf_monitor.elapsed())+" ms." );
|
|
disconnect( m_active_axes, SIGNAL(sigDrawEnds()), this, SLOT(slot_axes_draw_ends()) );
|
|
slot_refresh_screen_buffer();
|
|
m_refresh_buffer->stop();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_page_draw_ends()
|
|
{
|
|
disconnect( m_curr_page->objects(), SIGNAL(sigDrawEnds()), this, SLOT(slot_page_draw_ends()) );
|
|
slot_refresh_screen_buffer();
|
|
m_refresh_buffer->stop();
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_refresh_screen_buffer()
|
|
{
|
|
if ( m_screen_buffer ) {
|
|
bitBlt( m_canvas, 0, 0, m_screen_buffer, 0, 0, m_screen_buffer->width(), m_screen_buffer->height(), CopyROP, TRUE );
|
|
draw_tool();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
void QSPlotView::slot_curr_page_title_changed( const QString& new_title )
|
|
{
|
|
emit sigCurrentPageTitleChanged( new_title );
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|