/************************* * * * * * * * * * * * * *************************** Copyright (c) 1999-2005 Ryan Bobko ryan@ostrich-emulators.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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************** * * * * * * * * * * * * **************************/ #include "qhaccview.h" #include "qhacc.h" #include "copystore.h" #include "qhacctable.h" #include "qhaccutils.h" #include "transeditor.h" #include "guiconstants.h" #include "qhaccdialogs.h" #include "qhaccconstants.h" #include "qhacclineedits.h" #include "qhaccview.moc" #include #include #include #include #include #include #include #include #include #include #include #include #include QHaccTable * QHaccTViewItem::acctcache=0; QColor QHaccTViewItem::maincolor; QColor QHaccTViewItem::altcolor; bool QHaccTViewItem::nocase; const QDate QHaccTViewItem::BASEDATE=QDate( 2000, 12, 18 ); QHaccTViewItem::QHaccTViewItem( QHaccListView * p, bool de ) : QHaccListViewItem( p ){ doubleentry=de; iinit(); } QHaccTViewItem::QHaccTViewItem( QHaccListViewItem * p, bool de ) : QHaccListViewItem( p ){ doubleentry=de; iinit(); } QHaccTViewItem::~QHaccTViewItem(){} void QHaccTViewItem::iinit(){ idcol=QC::XSID; drawdoubleentry=true; numonnum=m_known=m_odd=false; setDragEnabled( true ); setDropEnabled( true ); } void QHaccTViewItem::setDrawDoubleEntry( bool b ){ drawdoubleentry=b; repaint(); } void QHaccTViewItem::setDoubleEntry( bool b ){ bool oldde=doubleentry; doubleentry=b; if( drawdoubleentry ){ if( !oldde && doubleentry ) setHeight( height()*2 ); else if( oldde && !doubleentry ) setHeight( height()/2 ); } } void QHaccTViewItem::resetE( QHacc * e ){ QHaccListViewItem::resetE( e ); auto_ptr accts=engine->getAs( TableGet() ); if( acctcache ) delete acctcache; acctcache=new QHaccTable( *accts ); acctcache->addIndexOn( QC::AID, CTUINT ); maincolor=engine->getCP( "MAINCOLOR" ); altcolor=engine->getCP( "ALTCOLOR" ); nocase=engine->getBP( "AUTOCOMPNOCASE" ); } void QHaccTViewItem::setCheckNums( bool b ){ numonnum=b; } void QHaccTViewItem::isetRow(){ if( myrow.isNull() ) return; resolved=false; numcompval=myrow[QC::XTNUM].gets().toInt(); setText( 0, myrow[QC::XTNUM].gets() ); setText( 2, myrow[QC::XTPAYEE].gets() ); setText( 3, myrow[QC::XTMEMO].gets() ); uint xr=myrow[QC::XSRECO].getu(); if( xr==QC::YREC ) setText( 6, "R" ); else if( xr==QC::MREC ) setText( 6, "C" ); else setText( 6, "" ); datecompval=myrow[QC::XTDATE].getd().daysTo( BASEDATE ); //setText( 1, QHaccDateEdit::getDateString( myrow[QC::XTDATE].getd() ) ); const MonCon& mconv=engine->converter(); sumcompval=mconv.converti( myrow[QC::XSSUM].gets(), Engine, Engine ); } void QHaccTViewItem::setup(){ QHaccListViewItem::setup(); if( doubleentry && drawdoubleentry ) setHeight( height()*2 ); } void QHaccTViewItem::resolve(){ if( myrow.isNull() ){ resolved=true; return; } QHaccTable splits( engine->getTSplits( myrow[QC::XTID].getu() ) ); //cout<<"splits are:"<1 ){ pairstr=GUIC::SPLIT; issplit=true; pairacct=0; } else if( ns==1 ){ pairacct=splits[0][QC::SACCTID].getu(); pairstr=acctcache->getWhere( TableSelect( QC::AID, pairacct ) )[QC::ANAME].gets(); issplit=false; } else{ pairacct=0; issplit=false; pairstr=""; } resolved=true; } bool QHaccTViewItem::usealt(){ QHaccView * lv=( QHaccView * )listView(); if ( lv ){ QHaccTViewItem * above; // this stuff is taken almost verbaitim from KListView sources // Ok, there's some weirdness here that requires explanation as this is a // speed hack. itemAbove() is a O(n) operation (though this isn't // immediately clear) so we want to call it as infrequently as possible -- // especially in the case of painting a cell. // // So, in the case that we *are* painting a cell: (1) we're assuming that // said painting is happening top to bottem -- this assumption is present // elsewhere in the implementation of this class, (2) itemBelow() is fast: // roughly constant time. // // Given these assumptions we can do a mixture of caching and telling the // next item that when that item is the current item that the now // current item will be the item above it. // // Ideally this will make checking to see if item above the current item // is the alternate color a constant time operation rather than 0(n). if( lv->painting ) { if( lv->paintCurrent!=this ){ lv->paintAbove=( lv->paintBelow==this ? lv->paintCurrent : itemAbove() ); lv->paintCurrent=this; lv->paintBelow=itemBelow(); } above=( QHaccTViewItem * )lv->paintAbove; } else above=( QHaccTViewItem * )itemAbove(); m_known=( above ? above->m_known : true ); if( m_known ) m_odd=( above ? !above->m_odd : false ); else{ QHaccTViewItem * item; bool previous=true; QListViewItem * par=QListViewItem::parent(); if( par ){ item=( QHaccTViewItem * )par; if( item ) previous=item->m_odd; item=( QHaccTViewItem * )( par->firstChild() ); } else item=( QHaccTViewItem * )( lv->firstChild() ); while( item ){ item->m_odd=previous=!previous; item->m_known=true; item =( QHaccTViewItem * )( item->nextSibling() ); } } return m_odd; } return false; } //void QHaccTViewItem::paintCell( QPainter * p, const QColorGroup& cg, int c, void QHaccTViewItem::paintCell( QPainter * p, const QColorGroup&, int c, int w, int aln ){ // QListViewItem::paintCell( p, cg, c, w, aln ); //return; int h=height(); int marg=listView()->itemMargin(); QString txt( text( c ) ); p->save(); QColor basecol=( usealt() ? altcolor : maincolor ); p->fillRect( 0, 0, w, h, QBrush( basecol ) ); if( this==( listView()->currentItem() ) ){ QFont f=p->font(); f.setBold( true ); p->setFont( f ); } if( myrow.isNull() ){ if( c==2 ) p->drawText( marg, 0, w-1, h-1-marg, aln, "" ); } else { const MonCon& mconv=engine->converter(); const int w1=w-1; const int h1=h-1-marg; bool dowrite=true; switch( c ){ case 1: txt=QHaccDateEdit::getDateString( myrow[QC::XTDATE].getd() ); break; case 2: // draw the pairstr on line 2 if( doubleentry && drawdoubleentry ){ if( !resolved ) resolve(); p->drawText( marg, 0, w1, h1, AlignLeft|AlignBottom, pairstr ); } break; case 3: if( doubleentry && drawdoubleentry ){ p->drawText( marg, 0, w1, h1, AlignLeft|AlignBottom, txt ); dowrite=false; } break; case 4: if( sumcompval>0 ){ txt=mconv.convert( sumcompval, Engine, Preference ); if( myrow[QC::XTVOID].getb() ) txt=QObject::tr( "VOID" ); } else dowrite=false; break; case 5: if( sumcompval<0 ){ txt=mconv.convert( 0-sumcompval, Engine, Preference ); if( myrow[QC::XTVOID].getb() ) txt=QObject::tr( "VOID" ); } else dowrite=false; break; default: break; } if( dowrite ) p->drawText( marg, 0, w1, h1, aln, txt ); } p->restore(); // draw a guide-line on the column boundary p->drawLine( 0, 0, 0, h-1 ); } int QHaccTViewItem::compare( QListViewItem * i, int col, bool asc ) const { //int ret=QHaccListViewItem::compare( i, col, asc ); const TableRow& irow=( ( ( QHaccTViewItem * )i )->row() ); // always make null rows sort to the bottom if( myrow.isNull() ){ if( asc ) return 1; else return -1; } else{ if( irow.isNull() ){ if( asc ) return -1; else return 1; } } // sorting on date if( col==1 ) { // sorting on date if( ( ( QHaccTViewItem * )i )->datecompval>datecompval ) return -1; else if( ( ( QHaccTViewItem * )i )->datecompvalsumcompval>sumcompval ) return 1; else if( ( ( QHaccTViewItem * )i )->sumcompvalnumcompval>numcompval ) return 1; else if( ( ( QHaccTViewItem * )i )->numcompvaltext( col ).lower() ); } else return QHaccListViewItem::compare( i, col, asc ); } void QHaccTViewItem::updateA( const Account& newy ){ if( myrow.isNull() || newy[QC::AID]!=pairacct ) return; // else the pairacct is changing resolved=false; repaint(); } bool QHaccTViewItem::acceptDrop( QMimeSource * e ){ //cout<<"tvi acceptdrop"<accept(); if( myrow[QC::XSACCTID]!=a ){ // moving a transaction from another account to this one s.updateWhere( TableSelect( QC::SACCTID, a ), TableUpdate( QC::SACCTID, myrow[QC::XSACCTID] ) ); } t.set( QC::TDATE, myrow[QC::XTDATE] ); engine->updateT( t, s ); } else if( QHaccADrag::decode( e, t ) ){ // if this is a double-entry transaction with only one // split, change the other split to point to the dropped account //cout<<"dropped an account on "<getTSplits( myrow[QC::XTID].getu() ) ); TableSelect ts( QC::SACCTID, myrow[QC::XSACCTID], TableSelect::NE ); //for( uint i=0; iupdateT( engine->splitXTrans( myrow ), spl ); } // else there's nothing to do } } /*************************************************/ /*************** QHaccView Class *****************/ /*************************************************/ QHaccView::QHaccView( QHacc * eng, QWidget * p, const char * n ) : QHaccListView( eng, p, n ){ setPrefBase( "VIEW" ); accelerators=new QAccel( this ); connect( accelerators, SIGNAL( activated( int ) ), this, SLOT( addMTrans( int ) ) ); addColumn( tr( "Num" ) ); addColumn( tr( "Date" ) ); addColumn( tr( "Payee" ) ); addColumn( tr( "Memo" ) ); addColumn( tr( "Deposit" ) ); addColumn( tr( "Withdrawal" ) ); addColumn( tr( "Rec" ) ); for( int i=0; i<7; i++ ){ if( i==4 || i==5 ) setColumnAlignment( i, AlignRight|AlignTop ); else setColumnAlignment( i, AlignLeft|AlignTop ); } setAllColumnsShowFocus( true ); setShowSortIndicator( true ); //viewport()->setMouseTracking( true ); editor=0; editorLPT=0; QPopupMenu * popup=new QPopupMenu( this ); mempop=new QPopupMenu( this ); popup->insertItem( tr( "edit" ), this, SLOT( editTrans() ) ); popup->insertItem( tr( "toggle reco" ), this, SLOT( recTrans() ) ); popup->insertItem( tr( "delete" ), this, SLOT( remTrans() ) ); popup->insertItem( tr( "memorize" ), this, SLOT( memTrans() ) ); popup->insertSeparator(); popup->insertItem( tr( "copy" ), this, SLOT( copyTrans() ), CTRL+Key_C ); popup->insertItem( tr( "cut" ), this, SLOT( cutTrans() ), CTRL+Key_X ); paster=popup->insertItem( tr( "paste" ), this, SLOT( pasteTrans() ), CTRL+Key_P ); popup->setItemEnabled( paster, false ); popup->insertSeparator(); popup->insertItem( tr( "insert" ), this, SLOT( newTrans() ) ); popup->insertItem( tr( "memorized" ), mempop ); connect( mempop, SIGNAL( activated( int ) ), SLOT( addMTrans( int ) ) ); popup->insertItem( tr( "open mem editor" ), this, SLOT( edMTrans() ) ); setPopup( popup ); setAcceptDrops( true ); viewport()->setAcceptDrops( true ); memtrans.reset( new QHaccTable( QC::NCOLS, QC::NCOLTYPES ) ); connect( this, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( editTrans( QListViewItem * ) ) ); connect( this, SIGNAL( spacePressed( QListViewItem * ) ), this, SLOT( editTrans( QListViewItem * ) ) ); painting=false; } QHaccView::~QHaccView(){ dropEditor(); } void QHaccView::setSelectors( vector sels ){ // Note: these selectors are run against the pre-converted // dataset, so their criteria should reference QHaccc:T*, // not, QHaccView::* constants selectors=sels; makeData(); } void QHaccView::ireadPrefs( bool initial ){ QHaccTViewItem::resetE( engine ); color=engine->getCP( "MAINCOLOR" ); if( initial ){ connect( engine, SIGNAL( changedP( const QString&, bool ) ), this, SLOT( changeP( const QString&, bool ) ) ); connect( engine, SIGNAL( changedP( const QString&, QColor ) ), this, SLOT( changeP( const QString&, QColor ) ) ); connect( engine, SIGNAL( changedP( const QString&, QString ) ), this, SLOT( changeP( const QString&, QString ) ) ); connect( engine, SIGNAL( changedP( const QString&, float ) ), this, SLOT( changeP( const QString&, float ) ) ); connect( engine, SIGNAL( changedP( const QString&, int ) ), this, SLOT( changeP( const QString&, int ) ) ); connect( engine, SIGNAL( addedT( const Transaction & ) ), this, SLOT( addT( const Transaction & ) ) ); connect( engine, SIGNAL( updatedT( const Transaction & ) ), this, SLOT( updT( const Transaction & ) ) ); connect( engine, SIGNAL( removedT( const Transaction & ) ), this, SLOT( remT( const Transaction & ) ) ); connect( engine, SIGNAL( addedA( const Account & ) ), this, SLOT( addA( const Account & ) ) ); connect( engine, SIGNAL( removedA( const Account & ) ), this, SLOT( removeA( const Account & ) ) ); connect( engine, SIGNAL( updatedA( const Account &, const Account& ) ), this, SLOT( updateA( const Account &, const Account& ) ) ); } editorLPT=( engine->getBP( "DOUBLEENTRY" ) ? 2 : 1 ); } QDate QHaccView::getIUMDate() const { const Transaction& t=getMoused(); if( t.isNull() ) return QDate::currentDate(); else return t[QC::XTDATE].getd(); } void QHaccView::grabData(){ if( account.isNull() || journal.isNull() ) return; std::ostream * str=0; if( Utils::debug( Utils::CURIOSITY, str ) ) *str<<"viewer grabbing data!"<getTWhere( crit, 2, table1 ); uint rr=0; vector v; auto_ptr temp=engine->getXTForA( account, TableGet(), v, rr ); QHaccTable tbl( *temp ); if( findHighNum ){ // auto-incrementing check numbers for( uint i=0; i=highNum ) highNum=tnum+1; } } tbl.deleteWhere( TableSelect( QC::XTLID, journal[QC::LID], TableSelect::NE ) ); // do any miscellaneous selections auto_ptr t2=tbl.getWhere( selectors, rr ); temp=t2; // load what's left into our view table setUpdatesEnabled( false ); clear(); bool de=engine->getBP( "DOUBLEENTRY" ); for( uint i=0; iat( i ); QHaccTViewItem * tvi=new QHaccTViewItem( this, de ); ifinishItem( tvi ); tvi->setRow( row ); if( highNum ) tvi->setCheckNums( true ); } // add one last itm, for the line QHaccTViewItem * last=new QHaccTViewItem( this, de ); last->setRow( TableRow() ); grabMemData(); setUpdatesEnabled( true ); triggerUpdate(); ensureItemVisible( last ); setCurrentItem( last ); } void QHaccView::ifinishItem( QHaccTViewItem * ){} void QHaccView::grabMemData(){ // memorized transactions auto_ptr mems=engine->getNTsForA( account[QC::AID].getu() ); auto_ptr anytrans=engine->getNTsForA( 0 ); accelerators->clear(); memtrans->clear(); memtrans->load( mems.get() ); memtrans->load( anytrans.get() ); mempop->clear(); uint rows=memtrans->rows(); //cout<<"into grabmemdata"<at( i ).toString()< topmem; vector botmem; vector topcuts; vector botcuts; vector topids; vector botids; for( uint i=0; iat( i ); const QString& name=row[QC::NNAME].gets(); int nid=row[QC::NID].geti(); QKeySequence keyseq( row[QC::NSHORTCUT].gets() ); engine->getNT( name, t, s ); if( engine->isResolvable( t, s ) ){ topmem.push_back( name ); topids.push_back( nid ); topcuts.push_back( keyseq ); } else{ botmem.push_back( name ); botids.push_back( nid ); botcuts.push_back( keyseq ); } } for( uint i=0; iinsertItem( topmem[i], topids[i] ); accelerators->insertItem( topcuts[i], topids[i] ); } mempop->insertSeparator(); for( uint i=0; iinsertItem( botmem[i], botids[i] ); accelerators->insertItem( botcuts[i], botids[i] ); } } void QHaccView::viewportPaintEvent( QPaintEvent * e ){ paintAbove=paintBelow=paintCurrent=0; painting=true; QHaccListView::viewportPaintEvent( e ); painting=false; } void QHaccView::transCopied( bool b ){ popup->setItemEnabled( paster, b ); } void QHaccView::setAccount( const Account& a ){ dropEditor(); account=a; makeData(); } void QHaccView::setJournal( const Journal& l ){ dropEditor(); journal=l; makeData(); } void QHaccView::startDrag(){ //cout<<"am i here?"<splitXTrans( xt ); QHaccTable s=engine->getTSplits( t[QC::TID].getu() ); QDragObject * drobj=new QHaccTDrag( t, s, account[QC::AID].getu(), this ); drobj->drag(); } } void QHaccView::contentsDragEnterEvent( QDragEnterEvent * e ){ //cout<<"contentsdragenter"<accept(); } void QHaccView::contentsDropEvent( QDropEvent * e ){ //cout<<"contentsdropevent"<pos() ) ); if( tvi && !getRow( tvi ).isNull() ) tvi->dropper( e ); else { uint a; Transaction t; QHaccTable s; if( QHaccTDrag::decode( e, t, s, a ) ){ e->accept(); if( account[QC::AID]!=a ){ // moving a transaction from another account to this one s.updateWhere( TableSelect( QC::SACCTID, a ), TableUpdate( QC::SACCTID, account[QC::AID] ) ); } t.set( QC::TDATE, QDate::currentDate() ); engine->updateT( t, s ); } } } void QHaccView::changeP( const QString& p, int ){ if( p=="DATEFORMAT" ) triggerUpdate(); } void QHaccView::changeP( const QString& p, float ){ if( p=="ALTCURRENCYFACTOR" ) triggerUpdate(); } void QHaccView::changeP( const QString& p, QString ){ if( p=="DATESEPARATOR" || p=="ALTCURRENCYSEPARATOR" || p=="CURRENCYSEPARATOR" ) triggerUpdate(); } void QHaccView::changeP( const QString& p, QColor c ){ if( p=="MAINCOLOR" ) color=c; QHaccTViewItem::resetE( engine ); triggerUpdate(); } void QHaccView::changeP( const QString& pref, bool b ){ bool doupdate=false; if( pref=="DOUBLEENTRY" ){ dropEditor(); int i=( b ? 2 : 1 ); editorLPT=i; // cycle through the listitems QListViewItemIterator it( this ); while ( it.current() ){ ( ( QHaccTViewItem * )it.current() )->setDoubleEntry( b ); ifinishItem( ( QHaccTViewItem * )it.current() ); ++it; } doupdate=true; } else if( pref=="AUTOCOMPNOCASE" ) QHaccTViewItem::resetE( engine ); else if( pref=="USEALTCURRENCY" ) doupdate=true; if( doupdate ) triggerUpdate(); } void QHaccView::paintEmptyArea( QPainter * p, const QRect& rect ){ p->fillRect( rect, color ); } void QHaccView::keyPressEvent( QKeyEvent * qke ){ int key=qke->key(); //cout<<"qv got kre"<accept(); } else if( key==Key_E ){ editTrans(); qke->accept(); } else if( key==Key_R ){ recTrans(); qke->accept(); } else if( key==Key_Delete ){ remTrans(); qke->accept(); } else QHaccListView::keyPressEvent( qke ); } void QHaccView::dropEditor(){ if( editor ){ closeEditor(); delete editor; editor=0; } } void QHaccView::closeEditor(){ editor->hide(); setFocus(); } void QHaccView::openEditor( const QRect& r, const TableRow& xt, const QDate date ){ if( account.isNull() ) return; if( editor==0 ){ editor=new TransactionEditor( engine, account, journal, editorLPT>1, this ); connect( editor, SIGNAL( closed() ), SLOT( closeEditor() ) ); } bool edit=( !xt.isNull() ); Transaction t; if( edit ){ t=engine->splitXTrans( xt ); if( t[QC::TTYPE]==QC::MEMORIZED ){ t.set( QC::TDATE, TableCol( date ) ); if( t.geti( QC::TNUM )!=0 ){ t.set( QC::TNUM, TableCol( ( highNum>0 ? QString::number( highNum ) : account[QC::ADEFAULTNUM].gets() ) ) ); } } } else { // new transaction t=TableRow( QC::TCOLS ); t.set( QC::TDATE, TableCol( date ) ); t.set( QC::TNUM, TableCol( ( highNum>0 ? QString::number( highNum ) : account[QC::ADEFAULTNUM].gets() ) ) ); } int x, y; viewportToContents( r.left(), r.top(), x, y ); editor->reLayout( header(), r ); editor->prepare( t, edit ); ifinishEditor( editor ); addChild( editor, x, y ); editor->show(); } void QHaccView::ifinishEditor( TransactionEditor * ed ){ ed->setRecMode( QC::YREC ); } void QHaccView::newTrans(){ Transaction t; openEditor( itemRect( currentItem() ), t, getIUMDate() ); } void QHaccView::remTrans(){ Transaction t=getRow( currentItem() ); if( !t.isNull() ) engine->removeT( t[QC::XTID].getu() ); } void QHaccView::editTrans(){ editTrans( currentItem() ); } void QHaccView::editTrans( QListViewItem * i ){ openEditor( itemRect( i ), getRow( i ), getIUMDate() ); } void QHaccView::recTrans(){ QListViewItem * recer=currentItem(); TableRow t( getRow( recer ) ); if( t.isNull() ) newTrans(); else irecTrans( t ); setCurrentItem( recer->itemBelow() ); if( !contextTarget.isNull() ){ //setCurrentItem( findRowItem( contextTarget[QC::XSID].getu() )->itemBelow() ); } } void QHaccView::irecTrans( Transaction& xt ){ QHaccTable recs( QC::XCOLS ); int recMode=( xt[QC::XSRECO]==QC::NREC ? recMode=QC::YREC : recMode=QC::NREC ); recs+=xt; engine->setRec( &recs, recMode ); } void QHaccView::addA( const Account& ){ QHaccTViewItem::resetE( engine ); } void QHaccView::removeA( const Account& ){ QHaccTViewItem::resetE( engine ); } void QHaccView::updateA( const Account&, const Account& newy ){ if( account.isNull() ) return; if( newy[QC::AID]==account[QC::AID] ){ // if we're dealing with the open account, the default transaction // type might have changed, so worry about that if( account[QC::ADEFAULTNUM]!=newy[QC::ADEFAULTNUM] ){ bool findhighs=( newy[QC::ADEFAULTNUM]==GUIC::ACCTINCRSTR ); highNum=( findhighs ? 1 : 0 ); if( findhighs ){ // auto-incrementing check numbers, so we need to cycle // through all transactions in this account to find the // highest number uint rr=0; vector v; auto_ptr temp=engine->getXTForA( newy, TableGet(), v, rr ); for( uint i=0; iat( i )[QC::XTNUM].geti(); if( tnum>=highNum ) highNum=tnum+1; } } QListViewItemIterator it( this ); while ( it.current() ) { QHaccTViewItem * cur=( QHaccTViewItem * )it.current(); cur->updateA( newy ); cur->setCheckNums( findhighs ); ++it; } } account=newy; } QHaccTViewItem::resetE( engine ); } bool QHaccView::iInclude( const Transaction& t ) const { const TableCol& sid=t[QC::XSACCTID]; bool good=( sid==0 || ( sid==account[QC::AID] && t[QC::XTLID]==journal[QC::LID] ) ); for( uint i=0; igetBP( "DOUBLEENTRY" ) ); ifinishItem( tvi ); tvi->setRow( xt ); if( highNum ){ if( xt[QC::XTNUM].geti()>=highNum ) highNum=xt[QC::XTNUM].geti()+1; tvi->setCheckNums( true ); } setCurrentItem( tvi ); ensureItemVisible( tvi ); setUpdatesEnabled( true ); triggerUpdate(); } } } void QHaccView::updT( const Transaction& xt ){ // the given trans has been updated, so // determine if we need to repaint anything bool shouldHaveIt=iInclude( xt ); //cout<<"updT for "<::iterator it; cout<<"items map contains:"<second ).toString()<show(); } void QHaccView::addMTrans( int nid ){ const TableRow nt=memtrans->getWhere( TableSelect( QC::NID, TableCol( nid ) ) ); const uint TID=nt.getu( QC::NTID ); Transaction tr=engine->getT( TID ); QHaccTable sp=engine->getTSplits( TID ); sp.updateWhere( TableSelect(), TableUpdate( QC::SRECO, TableCol( QC::NREC ) ) ); if( engine->isResolvable( tr, sp ) ){ // if this transaction is resolvable, just add it to the engine sp.updateWhere( TableSelect( QC::SACCTID, 0 ), TableUpdate( QC::SACCTID, account[QC::AID] ) ); tr.set( QC::TDATE, TableCol( getIUMDate() ) ); tr.set( QC::TLID, journal[QC::LID] ); tr.set( QC::TTYPE, TableCol( QC::REGULAR ) ); if( highNum>0 && tr.geti( QC::TNUM )>0 ) tr.set( QC::TNUM, TableCol( QString::number( highNum ) ) ); engine->addT( tr, sp ); } else{ // if it's not resolvable, open an editor Split s=sp.getWhere( TableSelect( QC::SACCTID, account[QC::AID] ) ); // s can be null because the namedtrans might have // an "any" account, not this particular account if( s.isNull() ) s=sp.getWhere( TableSelect( QC::SACCTID, TableCol( 0 ) ) ); openEditor( itemRect( currentItem() ), engine->makeXTrans( tr, s ), getIUMDate() ); } } void QHaccView::memTrans(){ const Split& spl=getMoused(); if( !spl.isNull() ){ Transaction t( engine->splitXTrans( spl ) ); QHaccTable splits=engine->getTSplits( t[QC::TID].getu() ); TableRow nt( QC::NCOLS ); nt.set( QC::NNAME, t[QC::TPAYEE].gets()+" ("+spl[QC::XSSUM].gets()+")" ); nt.set( QC::NACCTID, account[QC::AID] ); engine->addNTForA( nt, t, splits ); } } void QHaccView::icopycut( bool cut ){ const Split& sp=getMoused(); if( !sp.isNull() ){ Transaction t( engine->splitXTrans( sp ) ); if( !cut ) t.set( QC::TDATE, TableCol( QC::XDATE ) ); const uint TID=t[QC::TID].getu(); QHaccTable s=engine->getTSplits( TID ); uint a=account[QC::AID].getu(); QApplication::clipboard()->setData( new QHaccTDrag( t, s, a ) ); if( cut ) engine->removeT( TID ); emit transToClipboard( true ); } else emit transToClipboard( false ); } void QHaccView::cutTrans(){ icopycut( true ); } void QHaccView::copyTrans(){ icopycut( false ); } void QHaccView::pasteTrans(){ Transaction t; QHaccTable s; uint a=0; if( QHaccTDrag::decode( QApplication::clipboard()->data(), t, s, a ) ){ // if TDATE==XDATE, we've copied the transaction, so set the date // appropriately, and if this is a checking account, also set the num if( t[QC::TDATE]==QC::XDATE ){ t.set( QC::TDATE, TableCol( getIUMDate() ) ); if( highNum && t[QC::TNUM].geti()>0 ) t.set( QC::TNUM, highNum++ ); } //cout<<"t is "< pvs; pvs.push_back( PosVal( QC::SRECO, TableCol( QC::NREC ) ) ); pvs.push_back( PosVal( QC::TLID, journal[QC::LID] ) ); s.updateWhere( TableSelect(), TableUpdate( pvs ) ); // change the "parent" split with the current account's AID s.updateWhere( TableSelect( QC::SACCTID, TableCol( a ) ), TableUpdate( QC::SACCTID, account[QC::AID] ) ); engine->addT( t, s ); } } /* * * * * * * * * * * * * * * */ /* QHACCRECVIEW METHODS */ /* * * * * * * * * * * * * * * */ QHaccRecView::QHaccRecView( QHacc * e, QWidget * p, const char * n ) : QHaccView( e, p, n ){ setPrefBase( "RECVIEW" ); disconnect( this, SIGNAL( clicked( QListViewItem * ) ), this, SLOT( editTrans( QListViewItem * ) ) ); disconnect( this, SIGNAL( spacePressed( QListViewItem * ) ), this, SLOT( editTrans( QListViewItem * ) ) ); connect( this, SIGNAL( clicked( QListViewItem * ) ), SLOT( recTrans() ) ); connect( this, SIGNAL( spacePressed( QListViewItem * ) ), this, SLOT( recTrans() ) ); } QHaccRecView::~QHaccRecView(){} void QHaccRecView::setLimit( const QDate& d ){ limit=d; } QDate QHaccRecView::getIUMDate() const { QDate d=QHaccView::getIUMDate(); if( d>limit ) return limit; else return d; } void QHaccRecView::irecTrans( Transaction& xt ){ if( xt[QC::XSRECO]==QC::NREC ) engine->setRecNR( xt, QC::MREC ); else engine->setRecNR( xt, QC::NREC ); } void QHaccRecView::ifinishEditor( TransactionEditor * ed ){ ed->setRecButton( true ); ed->setRecMode( QC::MREC ); } void QHaccRecView::ifinishItem( QHaccTViewItem * i ){ i->setDrawDoubleEntry( false ); }