/** * * Kalle Dalheimer */ #include #include #include #include #include #include // For TQByteArray #include #include #include #include #include #include #include #include #include #include #include #include #include #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() == TQt::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"