diff options
Diffstat (limited to 'kchart/kchart_view.cpp')
-rw-r--r-- | kchart/kchart_view.cpp | 764 |
1 files changed, 764 insertions, 0 deletions
diff --git a/kchart/kchart_view.cpp b/kchart/kchart_view.cpp new file mode 100644 index 00000000..ba2d1321 --- /dev/null +++ b/kchart/kchart_view.cpp @@ -0,0 +1,764 @@ +/** + * + * Kalle Dalheimer <[email protected]> + */ + + +#include <tqfile.h> +#include <tqpainter.h> +#include <tqcursor.h> +#include <tqpopupmenu.h> +#include <tqpaintdevicemetrics.h> +#include <tqcstring.h> // For TQByteArray + +#include <tdeaction.h> +#include <tdeglobal.h> +#include <tdelocale.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <kprinter.h> +#include <kstandarddirs.h> +#include <tdetempfile.h> +#include <dcopobject.h> +#include <kxmlguifactory.h> +#include <tdefiledialog.h> +#include <tdemessagebox.h> + +#include <KoTemplateCreateDia.h> + +#include "kdchart/KDChart.h" +#include "kchart_view.h" +#include "kchart_factory.h" +#include "kchart_part.h" +#include "kchart_params.h" +#include "kchartWizard.h" +#include "kchartDataEditor.h" +#include "kchartConfigDialog.h" +#include "KChartViewIface.h" +#include "kchartPageLayout.h" +#include "kchartPrinterDlg.h" +#include "csvimportdialog.h" + + +using namespace std; + + +//#include "sheetdlg.h" + +namespace KChart +{ + + +KChartView::KChartView( KChartPart* part, TQWidget* parent, const char* name ) + : KoView( part, parent, name ) +{ + + // No flicker + setBackgroundMode( TQt::NoBackground ); + + setInstance( KChartFactory::global() ); + if ( koDocument()->isReadWrite() ) + setXMLFile( "kchart.rc" ); + else + setXMLFile( "kchart_readonly.rc" ); + m_dcop = 0; + dcopObject(); // build it + + m_importData = new TDEAction( i18n( "Import Data..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( importData() ), + actionCollection(), "import_data" ); +#if 0 + TDEAction * actionExtraCreateTemplate = +#endif + new TDEAction( i18n( "&Create Template From Document..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( extraCreateTemplate() ), + actionCollection(), "extra_template" ); + + m_wizard = new TDEAction( i18n("Customize with &Wizard..."), + "wizard", 0, + TQT_TQOBJECT(this), TQT_SLOT( wizard() ), + actionCollection(), "wizard"); + m_edit = new TDEAction( i18n("Edit &Data..."), "edit", 0, + TQT_TQOBJECT(this), TQT_SLOT( editData() ), + actionCollection(), "editdata"); + m_config = new TDEAction( i18n( "&Chart..." ), "configure", 0, + + TQT_TQOBJECT(this), TQT_SLOT( slotConfig() ), + actionCollection(), "config" ); + + // One TDEToggleAction per chart type + m_chartbars = new TDEToggleAction( i18n("&Bar"), "chart_bar_3d", 0, TQT_TQOBJECT(this), + TQT_SLOT( barsChart() ), actionCollection(), + "barschart"); + m_chartbars->setExclusiveGroup( "charttypes" ); + m_chartbars->setChecked( true ); + + m_chartline = new TDEToggleAction( i18n("&Line"), "chart_line", 0, TQT_TQOBJECT(this), + TQT_SLOT( lineChart() ), actionCollection(), + "linechart"); + m_chartline->setExclusiveGroup( "charttypes" ); + + m_chartareas = new TDEToggleAction( i18n("&Area"), "chart_area", 0, TQT_TQOBJECT(this), + TQT_SLOT( areasChart() ), actionCollection(), + "areaschart"); + m_chartareas->setExclusiveGroup( "charttypes" ); + + m_charthilo = new TDEToggleAction( i18n("&HiLo"), "chart_hilo", 0, TQT_TQOBJECT(this), + TQT_SLOT( hiLoChart() ), actionCollection(), + "hilochart"); + m_charthilo->setExclusiveGroup( "charttypes" ); + + m_chartbw = new TDEToggleAction( i18n("Bo&x && Whiskers"), "chart_boxwhisker", 0, TQT_TQOBJECT(this), + TQT_SLOT( bwChart() ), actionCollection(), + "bwchart"); + m_chartbw->setExclusiveGroup( "charttypes" ); + + m_chartpie = new TDEToggleAction( i18n("&Pie"), "chart_pie", 0, TQT_TQOBJECT(this), + TQT_SLOT( pieChart() ), actionCollection(), + "piechart"); + m_chartpie->setExclusiveGroup( "charttypes" ); + + m_chartring = new TDEToggleAction( i18n("&Ring"), "chart_ring", 0, TQT_TQOBJECT(this), + TQT_SLOT( ringChart() ), actionCollection(), + "ringchart"); + m_chartring->setExclusiveGroup( "charttypes" ); + + m_chartpolar = new TDEToggleAction( i18n("&Polar"), "chart_polar", 0, TQT_TQOBJECT(this), + TQT_SLOT( polarChart() ), actionCollection(), + "polarchart"); + m_chartpolar->setExclusiveGroup( "charttypes" ); + + // Configuration TDEActions + m_colorConfig = new TDEAction( i18n( "&Colors..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigColor() ), + actionCollection(), "color_config" ); + + m_fontConfig = new TDEAction( i18n( "&Font..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigFont() ), + actionCollection(), "font_config" ); + + m_backConfig = new TDEAction( i18n( "&Background..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigBack() ), + actionCollection(), "back_config" ); + + m_legendConfig = new TDEAction( i18n( "&Legend..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigLegend() ), + actionCollection(), "legend_config" ); + + m_subTypeChartConfig = new TDEAction( i18n( "Chart &Sub-type..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigSubTypeChart() ), + actionCollection(), "legend_subtype" ); + + m_dataFormatConfig = new TDEAction( i18n( "&Data Format..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigDataFormat() ), + actionCollection(), "data_format" ); + + m_headerFooterConfig = new TDEAction( i18n( "&Header && Footer..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigHeaderFooterChart() ), + actionCollection(), "headerfooter_subtype" ); + + m_pageLayoutConfig = new TDEAction( i18n( "Page Layout..." ), 0, + TQT_TQOBJECT(this), TQT_SLOT( slotConfigPageLayout() ), + actionCollection(), "page_layout" ); + + // initialize the configuration + // loadConfig(); + + // Disable some things if we can't change the data, e.g. because + // we are inside another application that provides the data for us. + if (!((KChartPart*)koDocument())->canChangeValue()) { + m_edit->setEnabled(false); + m_importData->setEnabled(false); + } + + updateGuiTypeOfChart(); +} + + +KChartView::~KChartView() +{ + delete m_dcop; +} + + +DCOPObject* KChartView::dcopObject() +{ + if ( !m_dcop ) + m_dcop = new KChartViewIface( this ); + + return m_dcop; +} + + +void KChartView::paintEvent( TQPaintEvent* /*ev*/ ) +{ + TQPainter painter( this ); + + // ### TODO: Scaling + + // Let the document do the drawing + // This calls KChartPart::paintContent, basically. + koDocument()->paintEverything( painter, rect(), false, this ); +} + + +void KChartView::updateReadWrite( bool /*readwrite*/ ) +{ +#ifdef __GNUC__ +#warning TODO +#endif +} + + +// Edit the data to the chart. +// This opens a spreadsheet like editor with the data in it. +// + +void KChartView::editData() +{ + kchartDataEditor ed(this); + KChartParams *params = ((KChartPart*)koDocument())->params(); + KDChartTableData *dat = ((KChartPart*)koDocument())->data(); + + kdDebug(35001) << "***Before calling editor: cols =" << dat->cols() + << " , rows = " << dat->rows() + << " , usedCols = " << dat->usedCols() + << " usedRows = " << dat->usedRows() << endl; + + ed.setData( params, dat ); + ed.setRowLabels(((KChartPart*)koDocument())->rowLabelTexts()); + ed.setColLabels(((KChartPart*)koDocument())->colLabelTexts()); + + // Activate the Apply button in the editor. + connect(&ed, TQT_SIGNAL(applyClicked(kchartDataEditor *)), + TQT_TQOBJECT(this), TQT_SLOT(applyEdit(kchartDataEditor *))); + + // Execute the data editor. + if ( ed.exec() != TQDialog::Accepted ) { + return; + } + if (!ed.modified()) + return; + + // Get the data and legend back. + ed.getData(params, dat); + ed.getRowLabels(((KChartPart*)koDocument())->rowLabelTexts()); + ed.getColLabels(((KChartPart*)koDocument())->colLabelTexts()); + ((KChartPart*)koDocument())->setModified(true); + + kdDebug(35001) << "***After calling editor: cols =" << dat->cols() + << " , rows = " << dat->rows() + << " , usedCols = " << dat->usedCols() + << " usedRows = " << dat->usedRows() << endl; + update(); +} + + +void KChartView::applyEdit(kchartDataEditor *ed) +{ + if (!ed->modified()) + return; + + ed->getData( ((KChartPart*)koDocument())->params(), + ((KChartPart*)koDocument())->data() ); + ed->getRowLabels(((KChartPart*)koDocument())->rowLabelTexts()); + ed->getColLabels(((KChartPart*)koDocument())->colLabelTexts()); + + ((KChartPart*)koDocument())->setModified(true); + + update(); +} + + +void KChartView::wizard() +{ + kdDebug(35001) << "Wizard called" << endl; + KChartWizard *wiz = new KChartWizard((KChartPart*)koDocument(), this, + "KChart Wizard", true); + kdDebug(35001) << "Executed. Now, display it" << endl; + if (wiz->exec()) { + ((KChartPart*)koDocument())->setModified(true); + update(); + updateGuiTypeOfChart(); + kdDebug(35001) << "Ok, executed..." << endl; + } +} + + +void KChartView::updateGuiTypeOfChart() +{ + KDChartParams* params = ((KChartPart*)koDocument())->params(); + + switch(params->chartType()) { + case KDChartParams::Bar: + m_chartbars->setChecked(true); + break; + case KDChartParams::Line: + m_chartline->setChecked(true); + break; + case KDChartParams::Area: + m_chartareas->setChecked(true); + break; + case KDChartParams::Pie: + m_chartpie->setChecked(true); + break; + case KDChartParams::HiLo: + m_charthilo->setChecked(true); + break; + case KDChartParams::Ring: + m_chartring->setChecked(true); + break; + case KDChartParams::Polar: + m_chartpolar->setChecked(true); + break; + case KDChartParams::BoxWhisker: + m_chartbw->setChecked( true ); + break; + default: + //todo + break; + } + + // Disable subtype configuration button if appropriate. + updateButton(); +} + + +void KChartView::slotConfig() +{ + config(KChartConfigDialog::KC_ALL); +} + + +void KChartView::config(int flags) +{ + // open a config dialog depending on the chart type + KChartParams *params = ((KChartPart*)koDocument())->params(); + KDChartTableData *dat = ((KChartPart*)koDocument())->data(); + + KChartConfigDialog *d = new KChartConfigDialog( params, this, flags, + dat ); + + connect( d, TQT_SIGNAL( dataChanged() ), + TQT_TQOBJECT(this), TQT_SLOT( slotRepaint() ) ); + d->exec(); + delete d; +} + + +void KChartView::slotRepaint() +{ + ((KChartPart*)koDocument())->setModified(true); + update(); +} + + +void KChartView::saveConfig() +{ + kdDebug(35001) << "Save config..." << endl; + ((KChartPart*)koDocument())->saveConfig( TDEGlobal::config() ); +} + + +void KChartView::loadConfig() +{ + kdDebug(35001) << "Load config..." << endl; + + TDEGlobal::config()->reparseConfiguration(); + ((KChartPart*)koDocument())->loadConfig( TDEGlobal::config() ); + + updateGuiTypeOfChart(); + //refresh chart when you load config + update(); +} + + +void KChartView::defaultConfig() +{ + ((KChartPart*)koDocument())->defaultConfig( ); + updateGuiTypeOfChart(); + update(); +} + + +void KChartView::pieChart() +{ + if ( m_chartpie->isChecked() ) { + forceAxisParams(false); + KChartParams *params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::Pie ); + params->setThreeDPies(params->threeDBars()); + params->setExplodeFactor( 0 ); + params->setExplode( true ); + + updateButton(); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartpie->setChecked( true ); // always one has to be checked ! +} + +void KChartView::forceAxisParams(bool lineMode) { + KChartParams *params = ((KChartPart*)koDocument())->params(); + KDChartAxisParams axisParams; + axisParams = params->axisParams( KDChartAxisParams::AxisPosLeft ); + if(params->chartType() == KChartParams::Line) + m_logarithmicScale = axisParams.axisCalcMode(); + if(lineMode) { + if(m_logarithmicScale) + axisParams.setAxisCalcMode(KDChartAxisParams::AxisCalcLogarithmic); + } else + axisParams.setAxisCalcMode(KDChartAxisParams::AxisCalcLinear); + params->setAxisParams( KDChartAxisParams::AxisPosLeft, axisParams ); +} + +void KChartView::lineChart() +{ + if ( m_chartline->isChecked() ) { + forceAxisParams(true); + KChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::Line ); + params->setLineChartSubType( KDChartParams::LineNormal ); + + updateButton(); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartline->setChecked( true ); // always one has to be checked ! + +} + + +void KChartView::barsChart() +{ + if ( m_chartbars->isChecked() ) { + forceAxisParams(false); + KChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::Bar ); + params->setBarChartSubType( KDChartParams::BarNormal ); + + updateButton(); + params->setThreeDBars( params->threeDPies() ); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartbars->setChecked( true ); // always one has to be checked ! +} + + +void KChartView::areasChart() +{ + if ( m_chartareas->isChecked() ) { + forceAxisParams(false); + KChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::Area ); + params->setAreaChartSubType( KDChartParams::AreaNormal ); + + updateButton(); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartareas->setChecked( true ); // always one has to be checked ! + +} + + +void KChartView::hiLoChart() +{ + if ( m_charthilo->isChecked() ) { + forceAxisParams(false); + KChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::HiLo ); + params->setHiLoChartSubType( KDChartParams::HiLoNormal ); + + updateButton(); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_charthilo->setChecked( true ); // always one has to be checked ! +} + + +void KChartView::ringChart() +{ + if ( m_chartring->isChecked() ) { + forceAxisParams(false); + KChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KChartParams::Ring ); + + updateButton(); + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartring->setChecked( true ); // always one has to be checked ! + +} + + +void KChartView::polarChart() +{ + if ( m_chartpolar->isChecked() ) { + forceAxisParams(false); + KDChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KDChartParams::Polar ); + params->setPolarChartSubType( KDChartParams::PolarNormal ); + + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartpolar->setChecked( true ); // always one has to be checked ! +} + + +void KChartView::bwChart() +{ + if ( m_chartbw->isChecked() ) { + forceAxisParams(false); + KDChartParams* params = ((KChartPart*)koDocument())->params(); + + params->setChartType( KDChartParams::BoxWhisker ); + params->setBWChartSubType( KDChartParams::BWNormal ); + + update(); + ((KChartPart*)koDocument())->setModified(true); + } + else + m_chartbw->setChecked( true ); // always one has to be checked ! +} + + +void KChartView::mousePressEvent ( TQMouseEvent *e ) +{ + if (!koDocument()->isReadWrite() || !factory()) + return; + if ( e->button() == Qt::RightButton ) + ((TQPopupMenu*)factory()->container("action_popup",this))->popup(TQCursor::pos()); +} + + +void KChartView::slotConfigColor() +{ + config(KChartConfigDialog::KC_COLORS); +} + + +void KChartView::slotConfigFont() +{ + config(KChartConfigDialog::KC_FONT); +} + + +void KChartView::slotConfigBack() +{ + config(KChartConfigDialog::KC_BACK); +} + + +void KChartView::slotConfigLegend() +{ + config(KChartConfigDialog::KC_LEGEND); +} + +void KChartView::slotConfigDataFormat() +{ + config(KChartConfigDialog::KC_DATAFORMAT); +} + +void KChartView::slotConfigSubTypeChart() +{ + config(KChartConfigDialog::KC_SUBTYPE); +} + + +void KChartView::slotConfigHeaderFooterChart() +{ + config(KChartConfigDialog::KC_HEADERFOOTER); +} + + +// FIXME: Rename into something suitable. +void KChartView::updateButton() +{ + // Disable sub chart config item. + KChartParams* params = ((KChartPart*)koDocument())->params(); + + bool state=(params->chartType()==KChartParams::Bar || + params->chartType()==KChartParams::Area || + params->chartType()==KChartParams::Line || + params->chartType()==KChartParams::HiLo || + params->chartType()==KChartParams::Polar); + m_subTypeChartConfig->setEnabled(state); +} + + +void KChartView::slotConfigPageLayout() +{ + KChartParams *params = ((KChartPart*)koDocument())->params(); + KChartPageLayout *dialog = new KChartPageLayout(params, this, + "Page Layout"); + + connect( dialog, TQT_SIGNAL( dataChanged() ), + this, TQT_SLOT( slotRepaint() ) ); + + dialog->exec(); + delete dialog; +} + + +void KChartView::setupPrinter( KPrinter &printer ) +{ + if ( !printer.previewOnly() ) + printer.addDialogPage( new KChartPrinterDlg( 0, "KChart page" ) ); +} + + +void KChartView::print(KPrinter &printer) +{ + printer.setFullPage( false ); + + TQPainter painter; + painter.begin(&printer); + TQPaintDeviceMetrics pdm( &printer ); + + int height; + int width; + if ( !printer.previewOnly() ) { + int const scalex = printer.option("kde-kchart-printsizex").toInt(); + int const scaley = printer.option("kde-kchart-printsizey").toInt(); + + width = pdm.width() * scalex / 100; + height = pdm.height() * scaley / 100; + } + else { + // Fill the whole page. + width = pdm.width(); + height = pdm.height(); + } + + TQRect rect(0, 0, width, height); + KDChart::print(&painter, + ((KChartPart*)koDocument())->params(), + ((KChartPart*)koDocument())->data(), + 0, // regions + &rect); + + painter.end(); +} + + +// Import data from a Comma Separated Values file. +// + +void KChartView::importData() +{ + // Get the name of the file to open. + TQString filename = KFileDialog::getOpenFileName(TQString(),// startDir + TQString(),// filter + 0, + i18n("Import Data")); + kdDebug(35001) << "Filename = <" << filename << ">" << endl; + if (filename.isEmpty()) + return; + + // Check to see if we can read the file. + TQFile inFile(filename); + if (!inFile.open(IO_ReadOnly)) { + KMessageBox::sorry( 0, i18n("The file %1 could not be read.") + .arg(filename) ); + inFile.close(); + return; + } + + // Let the CSV dialog structure the data in the file. + TQByteArray inData( inFile.readAll() ); + inFile.close(); + CSVImportDialog *dialog = new CSVImportDialog(0L, inData); + + if ( !dialog->exec() ) { + kdDebug(35001) << "Cancel was pressed" << endl; + return; + } + + kdDebug(35001) << "OK was pressed" << endl; + + uint rows = dialog->rows(); + uint cols = dialog->cols(); + + kdDebug(35001) << "Rows: " << rows << " Cols: " << cols << endl; + + bool hasRowHeaders = ( rows > 1 && dialog->firstRowContainHeaders() ); + bool hasColHeaders = ( cols > 1 && dialog->firstColContainHeaders() ); + + KDChartTableData data( rows, cols ); + data.setUsedRows( rows ); + data.setUsedCols( cols ); + for (uint row = 0; row < rows; row++) { + for (uint col = 0; col < cols; col++) { + bool ok; + TQString tmp; + double val; + + // Get the text and convert to double unless in the headers. + tmp = dialog->text( row, col ); + if ( ( row == 0 && hasRowHeaders ) + || ( col == 0 && hasColHeaders ) ) { + kdDebug(35001) << "Setting header (" << row << "," << col + << ") to value " << tmp << endl; + data.setCell( row, col, tmp ); + } + else { + val = tmp.toDouble(&ok); + if (!ok) + val = 0.0; + + kdDebug(35001) << "Setting (" << row << "," << col + << ") to value " << val << endl; + + // and do the actual setting. + data.setCell( row, col, val ); + } + } + } + + ((KChartPart*)koDocument())->doSetData( data, + hasRowHeaders, hasColHeaders ); +} + + +void KChartView::extraCreateTemplate() +{ + int width = 60; + int height = 60; + TQPixmap pix = koDocument()->generatePreview(TQSize(width, height)); + + KTempFile tempFile( TQString(), ".chrt" ); + tempFile.setAutoDelete(true); + + koDocument()->saveNativeFormat( tempFile.name() ); + + KoTemplateCreateDia::createTemplate( "kchart_template", KChartFactory::global(), + tempFile.name(), pix, this ); + + KChartFactory::global()->dirs()->addResourceType("kchart_template", + TDEStandardDirs::kde_default( "data" ) + + "kchart/templates/"); +} + + +} //KChart namespace + +#include "kchart_view.moc" |