summaryrefslogtreecommitdiffstats
path: root/src/widgets/conversiontable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/conversiontable.cpp')
-rw-r--r--src/widgets/conversiontable.cpp426
1 files changed, 426 insertions, 0 deletions
diff --git a/src/widgets/conversiontable.cpp b/src/widgets/conversiontable.cpp
new file mode 100644
index 0000000..a48b67e
--- /dev/null
+++ b/src/widgets/conversiontable.cpp
@@ -0,0 +1,426 @@
+/***************************************************************************
+* Copyright (C) 2003-2004 by *
+* Unai Garro (ugarro@users.sourceforge.net) *
+* *
+* Copyright (C) 2003-2006 by *
+* Jason Kivlighn (jkivlighn@gmail.com) *
+* *
+* 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 "conversiontable.h"
+#include "datablocks/mixednumber.h"
+#include "widgets/fractioninput.h"
+
+#include <tqtooltip.h>
+
+#include <tdeglobal.h>
+#include <tdelocale.h>
+
+class ConversionTableToolTip : public TQToolTip
+{
+public:
+ ConversionTableToolTip( ConversionTable *t ) : TQToolTip( t->viewport() ),
+ table( t )
+ {}
+
+ void maybeTip( const TQPoint &pos )
+ {
+ if ( !table )
+ return ;
+
+ TQPoint cp = table->viewportToContents( pos );
+
+ int row = table->rowAt( cp.y() );
+ int col = table->columnAt( cp.x() );
+
+ if ( row == col )
+ return ;
+
+ TQString row_unit = table->verticalHeader() ->label( row );
+ TQString col_unit = table->horizontalHeader() ->label( col );
+ TQString text = table->text( row, col );
+ if ( text.isEmpty() )
+ text = "X"; //### Is this i18n friendly???
+
+ TQRect cr = table->cellGeometry( row, col );
+ cr.moveTopLeft( table->contentsToViewport( cr.topLeft() ) );
+ tip( cr, TQString( "1 %1 = %2 %3" ).arg( row_unit ).arg( text ).arg( col_unit ) );
+ }
+
+private:
+ ConversionTable *table;
+};
+
+ConversionTable::ConversionTable( TQWidget* parent, int maxrows, int maxcols ) : TQTable( maxrows, maxcols, parent, "table" )
+{
+ editBoxValue = -1;
+ items.setAutoDelete( true );
+ widgets.setAutoDelete( true );
+
+ ( void ) new ConversionTableToolTip( this );
+}
+
+ConversionTable::~ConversionTable()
+{}
+#include <kdebug.h>
+void ConversionTable::unitRemoved( int id )
+{
+ int index = *unitIDs.find( id );
+ kdDebug() << "index:" << index << endl;
+ removeRow( index );
+ removeColumn( index );
+ kdDebug() << "done" << endl;
+}
+
+void ConversionTable::unitCreated( const Unit &unit )
+{
+ insertColumns( numCols() );
+ insertRows( numRows() );
+ unitIDs.append( unit.id );
+ horizontalHeader() ->setLabel( numRows() - 1, unit.name );
+ verticalHeader() ->setLabel( numCols() - 1, unit.name );
+}
+
+TQTableItem* ConversionTable::item( int r, int c ) const
+{
+ return items.find( indexOf( r, c ) );
+}
+
+void ConversionTable::setItem( int r, int c, TQTableItem *i )
+{
+ items.replace( indexOf( r, c ), i );
+ i->setRow( r ); // Otherwise the item
+ i->setCol( c ); //doesn't know where it is!
+ updateCell( r, c );
+}
+
+void ConversionTable::clearCell( int r, int c )
+{
+ items.remove( indexOf( r, c ) );
+}
+
+void ConversionTable::takeItem( TQTableItem *item )
+{
+ items.setAutoDelete( false );
+ items.remove( indexOf( item->row(), item->col() ) );
+ items.setAutoDelete( true );
+}
+
+void ConversionTable::insertWidget( int r, int c, TQWidget *w )
+{
+ widgets.replace( indexOf( r, c ), w );
+}
+
+TQWidget* ConversionTable::cellWidget( int r, int c ) const
+{
+ return widgets.find( indexOf( r, c ) );
+}
+
+void ConversionTable::clearCellWidget( int r, int c )
+{
+ TQWidget * w = widgets.take( indexOf( r, c ) );
+ if ( w )
+ w->deleteLater();
+}
+
+
+ConversionTableItem::ConversionTableItem( TQTable *t, EditType et ) : TQTableItem( t, et, TQString::null )
+{
+ // we do not want this item to be replaced
+ setReplaceable( false );
+}
+
+void ConversionTableItem::paint( TQPainter *p, const TQColorGroup &cg, const TQRect &cr, bool selected )
+{
+ TQColorGroup g( cg );
+
+ // Draw in gray all those cells which are not editable
+
+ if ( row() == col() )
+ g.setColor( TQColorGroup::Base, gray );
+ TQTableItem::paint( p, g, cr, selected );
+}
+
+TQWidget* ConversionTableItem::createEditor() const
+{
+ FractionInput *editor = new FractionInput( table()->viewport(), MixedNumber::DecimalFormat );
+
+ MixedNumber current = MixedNumber::fromString(text());
+ if ( current.toDouble() > 1e-8 )
+ editor->setValue( current, 0 );
+
+ return editor;
+}
+
+void ConversionTableItem::setContentFromEditor( TQWidget *w )
+{
+ // the user changed the value of the combobox, so synchronize the
+ // value of the item (its text), with the value of the combobox
+ if ( w->inherits( "FractionInput" ) ) {
+ FractionInput* editor = ( FractionInput* ) w;
+ if ( editor->isInputValid() && !editor->isEmpty() && editor->value().toDouble() > 1e-6 ) {
+ setText( editor->value().toString(MixedNumber::DecimalFormat) );
+ emit ratioChanged( row(), col(), editor->value().toDouble() ); // Signal to store
+ }
+ else {
+ setText( TQString::null );
+ emit ratioRemoved( row(), col() );
+ }
+ }
+ else
+ TQTableItem::setContentFromEditor( w );
+}
+
+void ConversionTableItem::setText( const TQString &s )
+{
+ TQTableItem::setText( s );
+}
+TQString ConversionTable::text( int r, int c ) const // without this function, the usual (text(r,c)) won't work
+{
+ if ( item( r, c ) )
+ return item( r, c ) ->text(); //Note that item(r,c) was reimplemented here for large sparse tables...
+ else
+ return TQString::null;
+}
+
+void ConversionTable::initTable()
+{
+
+ for ( int r = 0;r < numRows();r++ ) {
+ this->createNewItem( r, r, 1.0 );
+ item( r, r ) ->setEnabled( false ); // Diagonal is not editable
+ }
+}
+
+void ConversionTable::createNewItem( int r, int c, double amount )
+{
+
+ ConversionTableItem * ci = new ConversionTableItem( this, TQTableItem::WhenCurrent );
+ ci->setText( beautify( TDEGlobal::locale() ->formatNumber( amount, 5 ) ) );
+ setItem( r, c, ci );
+ // connect signal (forward) to know when it's actually changed
+ connect( ci, TQ_SIGNAL( ratioChanged( int, int, double ) ), this, TQ_SIGNAL( ratioChanged( int, int, double ) ) );
+ connect( ci, TQ_SIGNAL( ratioRemoved( int, int ) ), this, TQ_SIGNAL( ratioRemoved( int, int ) ) );
+ connect( ci, TQ_SIGNAL( signalRepaintCell( int, int ) ), this, TQ_SLOT( repaintCell( int, int ) ) );
+}
+
+void ConversionTable::setUnitIDs( const IDList &idList )
+{
+ unitIDs = idList;
+}
+
+void ConversionTable::setRatio( int ingID1, int ingID2, double ratio )
+{
+ int indexID1 = unitIDs.findIndex( ingID1 );
+ int indexID2 = unitIDs.findIndex( ingID2 );
+
+ createNewItem( indexID1, indexID2, ratio );
+}
+
+
+int ConversionTable::getUnitID( int rc )
+{
+ return ( *( unitIDs.at( rc ) ) );
+}
+
+TQWidget * ConversionTable::beginEdit ( int row, int col, bool replace )
+{
+ // If there's no item, create it first.
+ if ( !item( row, col ) ) {
+ createNewItem( row, col, 0 );
+ }
+
+ // Then call normal beginEdit
+ return TQTable::beginEdit( row, col, replace );
+}
+
+void ConversionTableItem::setTextAndSave( const TQString &s )
+{
+ setText( s ); // Change text
+ emit signalRepaintCell( row(), col() ); // Indicate to update the cell to the table. Otherwise it's not repainted
+ emit ratioChanged( row(), col(), s.toDouble() ); // Signal to store
+}
+
+void ConversionTable::repaintCell( int r, int c )
+{
+ TQTable::updateCell( r, c );
+}
+
+void ConversionTable::resize( int r, int c )
+{
+ setNumRows( r );
+ setNumCols( c );
+ initTable();
+}
+
+void ConversionTable::clear( void )
+{
+ items.clear();
+ widgets.clear();
+ unitIDs.clear();
+ resize( 0, 0 );
+
+}
+
+//TODO this is incomplete/wrong
+void ConversionTable::swapRows( int row1, int row2, bool /*swapHeader*/ )
+{
+ //if ( swapHeader )
+ //((TQTableHeader*)verticalHeader())->swapSections( row1, row2, FALSE );
+
+ TQPtrVector<TQTableItem> tmpContents;
+ tmpContents.resize( numCols() );
+ TQPtrVector<TQWidget> tmpWidgets;
+ tmpWidgets.resize( numCols() );
+ int i;
+
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( FALSE );
+ for ( i = 0; i < numCols(); ++i ) {
+ TQTableItem *i1, *i2;
+ i1 = item( row1, i );
+ i2 = item( row2, i );
+ if ( i1 || i2 ) {
+ tmpContents.insert( i, i1 );
+ items.remove( indexOf( row1, i ) );
+ items.insert( indexOf( row1, i ), i2 );
+ items.remove( indexOf( row2, i ) );
+ items.insert( indexOf( row2, i ), tmpContents[ i ] );
+ if ( items[ indexOf( row1, i ) ] )
+ items[ indexOf( row1, i ) ] ->setRow( row1 );
+ if ( items[ indexOf( row2, i ) ] )
+ items[ indexOf( row2, i ) ] ->setRow( row2 );
+ }
+
+ TQWidget *w1, *w2;
+ w1 = cellWidget( row1, i );
+ w2 = cellWidget( row2, i );
+ if ( w1 || w2 ) {
+ tmpWidgets.insert( i, w1 );
+ widgets.remove( indexOf( row1, i ) );
+ widgets.insert( indexOf( row1, i ), w2 );
+ widgets.remove( indexOf( row2, i ) );
+ widgets.insert( indexOf( row2, i ), tmpWidgets[ i ] );
+ }
+ }
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( TRUE );
+
+ //updateRowWidgets( row1 );
+ //updateRowWidgets( row2 );
+ /*
+ if ( curRow == row1 )
+ curRow = row2;
+ else if ( curRow == row2 )
+ curRow = row1;
+ if ( editRow == row1 )
+ editRow = row2;
+ else if ( editRow == row2 )
+ editRow = row1;*/
+}
+
+//TODO this is incomplete/wrong
+void ConversionTable::swapColumns( int col1, int col2, bool /*swapHeader*/ )
+{
+ //if ( swapHeader )
+ //((TQTableHeader*)horizontalHeader())->swapSections( col1, col2, FALSE );
+
+ TQPtrVector<TQTableItem> tmpContents;
+ tmpContents.resize( numRows() );
+ TQPtrVector<TQWidget> tmpWidgets;
+ tmpWidgets.resize( numRows() );
+ int i;
+
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( FALSE );
+ for ( i = 0; i < numRows(); ++i ) {
+ TQTableItem *i1, *i2;
+ i1 = item( i, col1 );
+ i2 = item( i, col2 );
+ if ( i1 || i2 ) {
+ tmpContents.insert( i, i1 );
+ items.remove( indexOf( i, col1 ) );
+ items.insert( indexOf( i, col1 ), i2 );
+ items.remove( indexOf( i, col2 ) );
+ items.insert( indexOf( i, col2 ), tmpContents[ i ] );
+ if ( items[ indexOf( i, col1 ) ] )
+ items[ indexOf( i, col1 ) ] ->setCol( col1 );
+ if ( items[ indexOf( i, col2 ) ] )
+ items[ indexOf( i, col2 ) ] ->setCol( col2 );
+ }
+
+ TQWidget *w1, *w2;
+ w1 = cellWidget( i, col1 );
+ w2 = cellWidget( i, col2 );
+ if ( w1 || w2 ) {
+ tmpWidgets.insert( i, w1 );
+ widgets.remove( indexOf( i, col1 ) );
+ widgets.insert( indexOf( i, col1 ), w2 );
+ widgets.remove( indexOf( i, col2 ) );
+ widgets.insert( indexOf( i, col2 ), tmpWidgets[ i ] );
+ }
+ }
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( TRUE );
+
+ columnWidthChanged( col1 );
+ columnWidthChanged( col2 );
+ /*
+ if ( curCol == col1 )
+ curCol = col2;
+ else if ( curCol == col2 )
+ curCol = col1;
+ if ( editCol == col1 )
+ editCol = col2;
+ else if ( editCol == col2 )
+ editCol = col1;*/
+}
+
+//TODO this is incomplete/wrong
+void ConversionTable::swapCells( int row1, int col1, int row2, int col2 )
+{
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( FALSE );
+ TQTableItem *i1, *i2;
+ i1 = item( row1, col1 );
+ i2 = item( row2, col2 );
+ if ( i1 || i2 ) {
+ TQTableItem * tmp = i1;
+ items.remove( indexOf( row1, col1 ) );
+ items.insert( indexOf( row1, col1 ), i2 );
+ items.remove( indexOf( row2, col2 ) );
+ items.insert( indexOf( row2, col2 ), tmp );
+ if ( items[ indexOf( row1, col1 ) ] ) {
+ items[ indexOf( row1, col1 ) ] ->setRow( row1 );
+ items[ indexOf( row1, col1 ) ] ->setCol( col1 );
+ }
+ if ( items[ indexOf( row2, col2 ) ] ) {
+ items[ indexOf( row2, col2 ) ] ->setRow( row2 );
+ items[ indexOf( row2, col2 ) ] ->setCol( col2 );
+ }
+ }
+
+ TQWidget *w1, *w2;
+ w1 = cellWidget( row1, col1 );
+ w2 = cellWidget( row2, col2 );
+ if ( w1 || w2 ) {
+ TQWidget * tmp = w1;
+ widgets.remove( indexOf( row1, col1 ) );
+ widgets.insert( indexOf( row1, col1 ), w2 );
+ widgets.remove( indexOf( row2, col2 ) );
+ widgets.insert( indexOf( row2, col2 ), tmp );
+ }
+
+ //updateRowWidgets( row1 );
+ //updateRowWidgets( row2 );
+ //updateColWidgets( col1 );
+ //updateColWidgets( col2 );
+ items.setAutoDelete( FALSE );
+ widgets.setAutoDelete( TRUE );
+}
+
+#include "conversiontable.moc"