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.

647 lines
24 KiB

/***************************************************************************
kspanelmanager.cpp
-------------------
begin : Sat Oct 7 2000
copyright : (C) 2000 by Kamil Dobkowski
email : kamildobk@friko.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 "kspanelmanager.h"
#include "dialogs/kspanels.h"
#include "widgets/qsaxes2d.h"
#include "widgets/qsaxes3d.h"
#include "widgets/qscurve.h"
#include "widgets/qscontour.h"
#include "widgets/qsimage.h"
#include "widgets/qssurface.h"
#include "widgets/qsfigure.h"
#include "widgets/qsclegend.h"
#include "ksworkbook.h"
#include "qscobjects.h"
#include "kmatplotshell.h"
#include <qpushbutton.h>
#include <qbuttongroup.h>
#include <qvbuttongroup.h>
#include <qhgroupbox.h>
#include <qscrollview.h>
#include <qpopupmenu.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qtimer.h>
#include <qobjectlist.h>
#include <qsplitter.h>
#include <qlayout.h>
//-------------------------------------------------------------//
struct kspanelmanager_private_data {
Qt::Orientation o;
KMatplotShell *shell;
KSWorkbook *workbook;;
KSPanel *curr_panel;
QSplitter *splitter;
QWidget *buttons;
QFrame *categ_area;
QScrollView *panel_area;
KSSimpleContainer *main_area;
QPopupMenu *menu;
QVButtonGroup *categ_buttons;
QButtonGroup *panel_buttons;
QPushButton *apply;
QTimer *atimer;
QTimer *rtimer;
QGuardedPtr<QSPlotView> curr_view;
QGuardedPtr<QSCObject> curr_object;
};
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
//-------------------------------------------------------------//
KSPanelManager::KSPanelManager( KMatplotShell *shell, QWidget *parent, const char *name )
: QFrame(parent,name)
{
/////////////////////////
// init panel manager //
/////////////////////////
is_enabled = false;
pr_reading = false;
pr_applying = false;
pr_autoset = true;
resize( 355, 140 );
setFont( QFont("Arial",11) );
d = new kspanelmanager_private_data();
d->shell = shell;
d->o = Horizontal;
/////////////////////////
// timers //
/////////////////////////
// instead of calling readProperties directly use rather rtimer->start( 250, TRUE );
// instead of calling applyProperties directly use rather atimer->start( 250, TRUE );
d->rtimer = new QTimer( this );
d->atimer = new QTimer( this );
connect( d->rtimer, SIGNAL(timeout()), this, SLOT(slot_panel_read_properties()) );
connect( d->atimer, SIGNAL(timeout()), this, SLOT(slot_panel_apply_properties()) );
/////////////////////////////////////
// place for buttons and panels //
/////////////////////////////////////
d->splitter = new QSplitter( Horizontal, this );
d->buttons = new QWidget( d->splitter );
QGridLayout *l = new QGridLayout( d->buttons, 2, 2, 0, 5 );
d->categ_area = new QFrame( d->buttons );
d->categ_area->setFixedWidth( 35 );
d->panel_area = new QScrollView( d->buttons );
d->panel_area->setMinimumWidth( 50 );
d->panel_area->setMinimumHeight( 50 );
d->panel_area->setHScrollBarMode( QScrollView::AlwaysOff );
d->panel_area->setVScrollBarMode( QScrollView::Auto );
d->panel_area->viewport()->setBackgroundMode( PaletteBackground );
d->panel_area->setFrameStyle( StyledPanel | Sunken );
d->panel_area->viewport()->installEventFilter( this );
d->apply = new QPushButton( tr("Apply"), d->buttons );
d->apply->setDefault(true);
connect( d->apply, SIGNAL(clicked()), this, SLOT(slot_panel_apply_properties()) );
setAutoSetProperties( true );
l->addWidget( d->categ_area, 0, 0 );
l->addWidget( d->panel_area, 0, 1 );
l->addWidget( d->apply, 1, 1 );
d->splitter->setResizeMode( d->buttons, QSplitter::Stretch );
d->main_area = new KSSimpleContainer( d->splitter, 500, 130, 1 );
d->main_area->setFrameStyle( StyledPanel | Sunken );
d->splitter->setResizeMode( d->main_area, QSplitter::Stretch );
QValueList<int> sizes;
sizes.append( 200 );
sizes.append( 500 );
d->splitter->setSizes( sizes );
d->menu = new QPopupMenu( this );
d->shell->m_cut_dataset->addTo( d->menu );
d->shell->m_copy_dataset->addTo( d->menu );
d->shell->m_copy_all_dataset->addTo( d->menu );
d->shell->m_paste_dataset->addTo( d->menu );
d->shell->m_delete_dataset->addTo( d->menu );
d->menu->insertSeparator();
d->shell->m_raise_dataset->addTo( d->menu );
d->shell->m_lower_dataset->addTo( d->menu );
d->menu->insertSeparator();
d->shell->m_bring_dataset_to_front->addTo( d->menu );
d->shell->m_send_dataset_to_back->addTo( d->menu );
///////////////////////////////
// buttons //
///////////////////////////////
d->categ_buttons = NULL;
d->panel_buttons = NULL;
//////////////////////////////
// current state //
//////////////////////////////
d->curr_view = NULL;
d->curr_object = NULL;
d->curr_panel = NULL;
///////////////////////////////////////
// apply button ( hided by default ) //
///////////////////////////////////////
}
//-------------------------------------------------------------//
KSPanelManager::~KSPanelManager()
{
// check if there is applyProperties waiting to be called
if ( d->atimer->isActive() ) slot_panel_apply_properties();
emit dataObjectSelected( NULL );
delete d->categ_buttons;
delete d->panel_buttons;
delete d;
}
//-------------------------------------------------------------//
void KSPanelManager::setView( QSPlotView *view )
{
if ( d->curr_view ) {
disconnect( d->curr_view, SIGNAL(sigActiveObjectChanged() ), this, SLOT(slot_update_panel_list()) );
disconnect( d->curr_view, SIGNAL(sigActiveAxesChanged() ), this, SLOT(slot_update_panel_list()) );
disconnect( d->curr_view, SIGNAL(sigActiveAxesDatasetsChanged()), this, SLOT(slot_update_panel_list()) );
disconnect( d->curr_view, SIGNAL(message( const QString&)), this, SLOT(slot_set_message(const QString&)) );
}
d->curr_view = view;
d->workbook = dynamic_cast<KSWorkbook*>(view->workbook());
if ( d->curr_view ) {
connect( d->curr_view, SIGNAL(sigActiveObjectChanged() ), this, SLOT(slot_update_panel_list()) );
connect( d->curr_view, SIGNAL(sigActiveAxesChanged() ), this, SLOT(slot_update_panel_list()) );
connect( d->curr_view, SIGNAL(sigActiveAxesDatasetsChanged()), this, SLOT(slot_update_panel_list()) );
connect( d->curr_view, SIGNAL(message( const QString&)), this, SLOT(slot_set_message(const QString&)) );
}
slot_update_panel_list();
}
//-------------------------------------------------------------//
QSPlotView *KSPanelManager::view() const
{
return (QSPlotView *)d->curr_view;
}
//-------------------------------------------------------------//
void KSPanelManager::setEnabled( bool enabled )
{
is_enabled = enabled;
slot_update_panel_list();
}
//-------------------------------------------------------------//
void KSPanelManager::setAutoSetProperties( bool enabled )
{
pr_autoset = enabled;
if ( pr_autoset ) d->apply->hide();
else d->apply->show();
}
//-------------------------------------------------------------//
void KSPanelManager::slot_update_panel_list()
// called when plot changes or active object changes
{
if ( !d->curr_object.isNull() ) disconnect( d->curr_object, SIGNAL(sigUpdate()), this, SLOT(slot_update_panel_contents()) );
if ( is_enabled ) {
// try to preserve the currently selected category
int curr_category = -1;
if ( (QSCObject *)d->curr_object == get_curr_object() && d->categ_buttons )
curr_category = d->categ_buttons->id( d->categ_buttons->selected() );
d->curr_object = get_curr_object();
// create category buttons, ( and panel buttons if needed )
category_button_factory( curr_category );
}
if ( !d->curr_object.isNull() ) connect( d->curr_object, SIGNAL(sigUpdate()), this, SLOT(slot_update_panel_contents()) );
}
//-------------------------------------------------------------//
void KSPanelManager::slot_category_selected( int category_id )
// user pressed category button
{
panel_button_factory( category_id );
}
//-------------------------------------------------------------//
void KSPanelManager::slot_panel_selected( int button_id )
// called when new panel is selected
{
// check if contents of the currently removed panel changed
if ( d->atimer->isActive() ) { d->atimer->stop(); slot_panel_apply_properties(); }
// delete a previous panel
d->curr_panel = NULL;
d->main_area->setWidget( NULL );
// create a new panel
if ( is_enabled && panel_button(button_id) ) d->curr_panel = panel_button(button_id)->createPanel( d->main_area );
// show a new panel
d->main_area->setWidget( d->curr_panel );
// watch if its properties changed
if ( d->curr_panel ) {
adjust_panel_orientation();
slot_panel_read_properties();
connect( d->curr_panel, SIGNAL(propertiesChanged()), this, SLOT(slot_update_graph()) );
connect( d->curr_panel, SIGNAL(message(const QString&)), this, SLOT(slot_set_message(const QString&)) );
}
if ( panel_button(button_id) ) emit dataObjectSelected( panel_button(button_id)->dataObject() );
else emit dataObjectSelected( NULL );
}
//-------------------------------------------------------------//
KSPanelButton *KSPanelManager::panel_button( int button_id )
{
if ( d->panel_buttons ) return dynamic_cast<KSPanelButton*>(d->panel_buttons->find(button_id));
return NULL;
}
//-------------------------------------------------------------//
void KSPanelManager::selectPanel( int category, int element )
// show panel - called from outside
{
if ( get_curr_object() )
if ( category >= 0 || element >= 0 ) {
// TODO: we must somehow unifu categories of buttons and categories of graph elements
int button_category = KSPanelButton::BObject;
switch( category ) {
case QSAxes::GeneralCategory: button_category = KSPanelButton::BGeneral; break;
case QSAxes::AxisCategory: button_category = KSPanelButton::BAxes; break;
case QSAxes::GridCategory: button_category = KSPanelButton::BAxes; break;
case QSAxes::DatasetCategory: button_category = KSPanelButton::BDatasets; break;
}
// select category
if ( d->categ_buttons )
if ( d->categ_buttons->find(button_category) &&
!d->categ_buttons->find(button_category)->isOn() ) {
d->categ_buttons->find(button_category)->animateClick();
}
// select panel
if ( d->panel_buttons )
for( int button_nr=0; button_nr<d->panel_buttons->count(); button_nr++ ) {
KSPanelButton *button = panel_button(button_nr);
if ( button )
if ( button->isButtonFor(get_curr_object(),category,element) ) {
d->panel_area->ensureVisible( button->x(), button->y() );
if ( !button->isOn() ) button->animateClick();
}
}
}
}
//-------------------------------------------------------------//
void KSPanelManager::slot_panel_apply_properties()
{
pr_applying = true;
if ( d->curr_panel ) d->curr_panel->applyProperties();
pr_applying = false;
}
//-------------------------------------------------------------//
void KSPanelManager::slot_panel_read_properties()
{
pr_reading = true;
if ( d->curr_panel ) d->curr_panel->readProperties();
pr_reading = false;
}
//-------------------------------------------------------------//
void KSPanelManager::slot_update_panel_contents()
{
if ( is_enabled && !pr_autoset || !pr_applying ) d->rtimer->start( 250, TRUE );
}
//-------------------------------------------------------------//
void KSPanelManager::slot_update_graph()
{
if ( is_enabled && pr_autoset && !pr_reading ) d->atimer->start( 1000, TRUE );
}
//-------------------------------------------------------------//
QSCObject *KSPanelManager::get_curr_object()
{
if ( d->curr_view ) if ( d->curr_view->activeObject() ) return d->curr_view->activeObject();
return NULL;
}
//-------------------------------------------------------------//
void KSPanelManager::add_category_button( int category )
{
d->categ_buttons->insert( KSPanelButton::categoryButton( (KSPanelButton::ButtonCategory )category, d->categ_buttons ), category );
}
//-------------------------------------------------------------//
void KSPanelManager::arrange_button_row( const QString& title, int num_buttons, QSGraphicalData *dataObject )
{
// fill unused space
for( int i=num_buttons; i<3; i++ ) new QWidget( d->panel_buttons );
// add title
QLabel *label = new QLabel( title, d->panel_buttons );
label->setIndent( 5 );
label->setMaximumHeight( 50 );
label->setAlignment( AlignAuto | AlignVCenter | ExpandTabs );
if ( dataObject ) connect( dataObject, SIGNAL(sigTitleChanged(const QString&)), label, SLOT(setText(const QString&)) );
}
//-------------------------------------------------------------//
void KSPanelManager::slot_set_message( const QString& string )
{
emit message( string );
}
//-------------------------------------------------------------//
void KSPanelManager::category_button_factory( int select_category )
{
QButtonGroup *button_group = d->categ_buttons;
///////////////////////////////////
// delete panel list //
///////////////////////////////////
panel_button_factory( -1 );
///////////////////////////////////
// Delete old buttons //
///////////////////////////////////
delete d->categ_buttons;
d->categ_buttons = new QVButtonGroup( d->categ_area );
d->categ_buttons->setFrameStyle( NoFrame );
d->categ_buttons->setFixedSize( d->categ_area->width(), 140 );
d->categ_buttons->setExclusive( true );
d->categ_buttons->setInsideMargin( 3 );
d->categ_buttons->setInsideSpacing( 0 );
connect( d->categ_buttons, SIGNAL(pressed(int)), this, SLOT(slot_category_selected(int)) );
///////////////////////////////////
// Create new buttons //
///////////////////////////////////
QSCObject *curr_object = d->curr_object;
if ( curr_object && curr_object->isAxesShadow() ) {
add_category_button( KSPanelButton::BGeneral );
add_category_button( KSPanelButton::BAxes );
add_category_button( KSPanelButton::BDatasets );
}
else if ( curr_object ) {
add_category_button( KSPanelButton::BObject );
}
//////////////////////////////////
// set button panel //
//////////////////////////////////
//d->categ_buttons->resize( d->categ_buttons->width(), d->categ_buttons->sizeHint().height() );
d->categ_buttons->show();
//////////////////////////////////
// Select the first category //
//////////////////////////////////
if ( d->categ_buttons->find(select_category) ) {
d->categ_buttons->find(select_category)->animateClick();
} else {
for( int i=0; i<4; i++ )
if ( d->categ_buttons->find(i) ) {
d->categ_buttons->find(i)->animateClick(); break;
}
}
}
//-------------------------------------------------------------//
void KSPanelManager::panel_button_factory( int category )
{
QSCObject *curr_object = d->curr_object;
QButtonGroup *button_group = d->panel_buttons;
////////////////////////////////////
// delete currently visible panel //
////////////////////////////////////
slot_panel_selected( -1 );
////////////////////////////////////////
// delete old buttons //
////////////////////////////////////////
d->panel_area->removeChild( d->panel_buttons );
delete d->panel_buttons;
d->panel_buttons = new QButtonGroup( 4, Horizontal, d->panel_area->viewport() );
d->panel_buttons->setExclusive( true );
d->panel_buttons->setFrameStyle( NoFrame | Plain );
d->panel_buttons->setInsideMargin( 3 );
d->panel_buttons->setInsideSpacing( 0 );
connect( d->panel_buttons, SIGNAL(pressed(int)), this, SLOT(slot_panel_selected(int)) );
////////////////////////////////////////
// create new buttons //
////////////////////////////////////////
if ( curr_object && curr_object->isAxesShadow() ) {
QSAxes *axes = curr_object->parentAxes();
if ( category == KSPanelButton::BGeneral ) {
new KSPanelButtonRange(d->panel_buttons,d->workbook,axes);
arrange_button_row( tr("Range"), 1 );
new KSPanelButtonGeneral(d->panel_buttons,d->workbook,axes);
arrange_button_row( tr("General"), 1 );
}
if ( category == KSPanelButton::BGeneral )
if ( dynamic_cast<QSAxes2D*>(axes) ) {
QSAxes2D *axes2 = dynamic_cast<QSAxes2D*>(axes);
new KSPanelButtonFrame( d->panel_buttons, d->workbook, axes2 );
arrange_button_row( tr("Frame"), 1 );
}
if ( category == KSPanelButton::BGeneral )
if ( dynamic_cast<QSAxes3D*>(axes) ) {
QSAxes3D *axes3 = dynamic_cast<QSAxes3D*>(axes);
new KSPanelButtonCube(d->panel_buttons,d->workbook,axes3);
arrange_button_row( tr("Cube"), 1 );
new KSPanelButtonView(d->panel_buttons,d->workbook,axes3);
arrange_button_row( tr("View"), 1 );
new KSPanelButtonLight(d->panel_buttons,d->workbook,axes3);
arrange_button_row( tr("Light"), 1 );
new KSPanelButtonGL(d->panel_buttons,d->workbook,axes3);
arrange_button_row( tr("OpenGL"), 1 );
}
if ( category == KSPanelButton::BAxes )
for( int axis=axes->axisCount()-1; axis>=0; axis-- ) {
new KSPanelButtonAxis(d->panel_buttons,d->workbook,axes->axis(axis));
new KSPanelButtonGrid(d->panel_buttons,d->workbook,axes->axis(axis));
arrange_button_row( axes->axis(axis)->title(), 2, axes->axis(axis) );
}
if ( category == KSPanelButton::BDatasets )
for( int dataset=axes->plotCount()-1; dataset>=0; dataset-- ) {
if ( dynamic_cast<QSCurve*>(axes->plot(dataset)) ) {
QSCurve *curve = dynamic_cast<QSCurve*>(axes->plot(dataset));
new KSPanelButtonCurve(d->panel_buttons,d->workbook,curve);
arrange_button_row( axes->plot(dataset)->title(), 1, axes->plot(dataset) );
}
if ( dynamic_cast<QSContour*>(axes->plot(dataset)) ) {
QSContour *contour = dynamic_cast<QSContour*>(axes->plot(dataset));
new KSPanelButtonContour(d->panel_buttons,d->workbook,contour);
new KSPanelButtonGradient(d->panel_buttons,d->workbook,contour);
arrange_button_row( axes->plot(dataset)->title(), 2, axes->plot(dataset) );
}
if ( dynamic_cast<QSImage*>(axes->plot(dataset)) ) {
QSImage *image = dynamic_cast<QSImage*>(axes->plot(dataset));
new KSPanelButtonImage(d->panel_buttons,d->workbook,image);
new KSPanelButtonGradient(d->panel_buttons,d->workbook,image);
arrange_button_row( axes->plot(dataset)->title(), 2, axes->plot(dataset) );
}
if ( dynamic_cast<QSSurface*>(axes->plot(dataset)) ) {
QSSurface *surface = dynamic_cast<QSSurface*>(axes->plot(dataset));
new KSPanelButtonSurface(d->panel_buttons,d->workbook,surface);
new KSPanelButtonMesh(d->panel_buttons,d->workbook,surface);
arrange_button_row( axes->plot(dataset)->title(), 2, axes->plot(dataset) );
}
if ( dynamic_cast<QSFigure*>(axes->plot(dataset)) ) {
QSFigure *figure = dynamic_cast<QSFigure*>(axes->plot(dataset));
new KSPanelButtonFigure(d->panel_buttons,d->workbook,figure);
new KSPanelButtonMesh(d->panel_buttons,d->workbook,figure);
arrange_button_row( axes->plot(dataset)->title(), 2, axes->plot(dataset) );
}
}
}
if ( category == KSPanelButton::BObject )
if ( dynamic_cast<QSCLegend*>(curr_object) ) {
QSCLegend *l = dynamic_cast<QSCLegend*>(curr_object);
new KSPanelButtonCLegend(d->panel_buttons,d->workbook,l);
arrange_button_row( tr("Legend"), 1 );
new KSPanelButtonCLabel(d->panel_buttons,d->workbook,l);
arrange_button_row( tr("Labels"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,l,"posX","posY","posZ","coordX","coordY","coordZ");
arrange_button_row( tr("Position"), 1 );
}
else
if ( dynamic_cast<QSCArrow*>(curr_object) ) {
QSCArrow *a = dynamic_cast<QSCArrow*>(curr_object);
new KSPanelButtonCArrow(d->panel_buttons,d->workbook,a);
arrange_button_row( tr("Arrow"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,a,"originX","originY","originZ","originCoordX","originCoordY","originCoordZ");
arrange_button_row( tr("Origin"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,a,"endX","endY","endZ","endCoordX","endCoordY","endCoordZ");
arrange_button_row( tr("End"), 1 );
}
else
if ( dynamic_cast<QSCLabel*>(curr_object) ) {
QSCLabel *l = dynamic_cast<QSCLabel*>(curr_object);
new KSPanelButtonCLabel(d->panel_buttons,d->workbook,l);
arrange_button_row( tr("Label"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,l,"posX","posY","posZ","coordX","coordY","coordZ");
arrange_button_row( tr("Position"), 1 );
}
else
if ( dynamic_cast<QSCRect*>(curr_object) ) {
QSCRect *r = dynamic_cast<QSCRect*>(curr_object);
new KSPanelButtonCRect(d->panel_buttons,d->workbook,r);
arrange_button_row( tr("Rectangle"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,r,"originX","originY","originZ","originCoordX","originCoordY","originCoordZ");
arrange_button_row( tr("First corner"), 1 );
new KSPanelButtonCPos(d->panel_buttons,d->workbook,r,"endX","endY","endZ","endCoordX","endCoordY","endCoordZ");
arrange_button_row( tr("Second corner"), 1 );
}
//////////////////////////////////////////////
// set button view //
//////////////////////////////////////////////
//d->panel_buttons->setFixedSize( d->panel_buttons->sizeHint() );
d->panel_buttons->show();
d->panel_area->addChild( d->panel_buttons );
d->panel_area->resizeContents( d->panel_buttons->sizeHint().width(),
d->panel_buttons->sizeHint().height() );
//////////////////////////////
// select the first panel //
//////////////////////////////
if ( d->panel_buttons->find(0) ) d->panel_buttons->find(0)->animateClick();
}
//-------------------------------------------------------------//
bool KSPanelManager::eventFilter ( QObject *watched, QEvent *e )
{
if ( watched == d->panel_area->viewport() && e->type() == QEvent::ContextMenu ) {
d->menu->popup( ((QContextMenuEvent*)e)->globalPos() );
return TRUE;
}
return FALSE;
}
//-------------------------------------------------------------//
void KSPanelManager::setOrientation( Qt::Orientation o )
{
d->o = o;
d->splitter->setOrientation( o );
adjust_panel_orientation();
}
//-------------------------------------------------------------//
void KSPanelManager::adjust_panel_orientation()
{
if ( d->curr_panel ) {
const QObjectList *objects = d->curr_panel->queryList( "QBoxLayout", 0, FALSE, FALSE );
if ( objects ) {
QObjectListIt object( *objects );
while ( (QObject*)object ) {
QBoxLayout *layout = dynamic_cast<QBoxLayout*>((QObject*)object);
if ( layout ) layout->setDirection( d->o==Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom );
++object;
}
}
}
}
//-------------------------------------------------------------//
void KSPanelManager::resizeEvent ( QResizeEvent * )
{
d->splitter->resize( size() );
}