author | zecke <zecke> | 2002-10-07 23:37:48 (UTC) |
---|---|---|
committer | zecke <zecke> | 2002-10-07 23:37:48 (UTC) |
commit | 626183d58f43f010f5cfb055f8582be0227ff59c (patch) (side-by-side diff) | |
tree | ad219a64b642fe63480f04cca7c37de4795c5e84 | |
parent | cdc6cad191b866d481085da1d05806afb5602b2c (diff) | |
download | opie-626183d58f43f010f5cfb055f8582be0227ff59c.zip opie-626183d58f43f010f5cfb055f8582be0227ff59c.tar.gz opie-626183d58f43f010f5cfb055f8582be0227ff59c.tar.bz2 |
We're now using a home made painting of cells
This will theoretically speed up things
Currently it's noticeable slower on SQL
Cause we do up to 80 queries for 10 different
items. As you see a cache could be the answer to these
problems.
The reason for custom drawing is speed and memory consumption.
Take the unlikely case of 10.000 items
We would have 40.000 QTableItem
but would only show 40 of them at a time.
The rest seems to be wasted
-rw-r--r-- | core/pim/todo/mainwindow.cpp | 3 | ||||
-rw-r--r-- | core/pim/todo/tableitems.cpp | 4 | ||||
-rw-r--r-- | core/pim/todo/tableview.cpp | 231 | ||||
-rw-r--r-- | core/pim/todo/tableview.h | 44 | ||||
-rw-r--r-- | core/pim/todo/todoview.h | 2 |
5 files changed, 125 insertions, 159 deletions
diff --git a/core/pim/todo/mainwindow.cpp b/core/pim/todo/mainwindow.cpp index 47c0160..7e7d2f7 100644 --- a/core/pim/todo/mainwindow.cpp +++ b/core/pim/todo/mainwindow.cpp @@ -452,65 +452,66 @@ void MainWindow::slotDelete() { m_todoMgr.remove( currentView()->current() ); currentView()->removeEvent( currentView()->current() ); raiseCurrentView(); } void MainWindow::slotDeleteAll() { if(m_syncing) { QMessageBox::warning(this, tr("Todo"), tr("Can not edit data, currently syncing")); return; } //QString strName = table->text( table->currentRow(), 2 ).left( 30 ); if ( !QPEMessageBox::confirmDelete( this, tr( "Todo" ), tr("all tasks?") ) ) return; m_todoMgr.removeAll(); currentView()->clear(); raiseCurrentView(); } void MainWindow::slotDeleteCompleted() { if(m_syncing) { QMessageBox::warning(this, tr("Todo"), tr("Can not edit data, currently syncing")); return; } if ( !QPEMessageBox::confirmDelete( this, tr( "Todo" ), tr("all completed tasks?") ) ) return; - m_todoMgr.remove( currentView()->completed() ); + // FIXME + //m_todoMgr.remove( currentView()->completed() ); currentView()->updateView( ); } void MainWindow::slotFind() { } void MainWindow::slotEdit() { slotEdit( currentView()->current() ); } /* * set the category */ void MainWindow::setCategory( int c) { if ( c <= 0 ) return; qWarning("Iterating over cats %d", c ); for ( unsigned int i = 1; i < m_catMenu->count(); i++ ) m_catMenu->setItemChecked(i, c == (int)i ); if (c == 1 ) { m_curCat = QString::null; setCaption( tr("Todo") + " - " + tr("All Categories" ) ); }else if ( c == (int)m_catMenu->count() - 1 ) { m_curCat = tr("Unfiled"); setCaption( tr("Todo") + " - " + tr("Unfiled") ); }else { m_curCat = m_todoMgr.categories()[c-2]; setCaption( tr("Todo") + " - " + m_curCat ); } m_catMenu->setItemChecked( c, true ); currentView()->setShowCategory( m_curCat ); raiseCurrentView(); diff --git a/core/pim/todo/tableitems.cpp b/core/pim/todo/tableitems.cpp index ebfefc8..86fe07d 100644 --- a/core/pim/todo/tableitems.cpp +++ b/core/pim/todo/tableitems.cpp @@ -19,111 +19,111 @@ : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tableview.h" #include "tableitems.h" #include <string.h> using namespace Todo; CheckItem::CheckItem( QTable* t, const QString& sortKey, int uid, const QArray<int>& lis) : OCheckItem(t, sortKey), m_uid(uid ), m_cat( lis ) { } CheckItem::~CheckItem() { } void CheckItem::setChecked( bool b ) { OCheckItem::setChecked(b); } void CheckItem::toggle() { TableView* view = static_cast<TableView*>( table() ); OTodo ev = view->find( view->current() ); ev.setCompleted(!isChecked() ); - view->updateFromTable( ev ); + //view->updateFromTable( ev ); OCheckItem::toggle(); table()->updateCell( row(), col() ); } int CheckItem::uid() const { return m_uid; } QArray<int> CheckItem::cats() { return m_cat; } /* ComboItem */ ComboItem::ComboItem( QTable* t, EditType et ) : QTableItem( t, et, "3" ), m_cb(0) { setReplaceable( FALSE ); } ComboItem::~ComboItem() { } QWidget* ComboItem::createEditor()const { qWarning( "create editor"); QString txt = text(); ( (ComboItem*)this)-> m_cb = new QComboBox( table()->viewport() ); m_cb->insertItem( "1" ); m_cb->insertItem( "2" ); m_cb->insertItem( "3" ); m_cb->insertItem( "4" ); m_cb->insertItem( "5" ); m_cb->setCurrentItem( txt.toInt() - 1 ); return m_cb; } void ComboItem::setContentFromEditor( QWidget* w) { TableView* view = static_cast<TableView*>( table() ); OTodo ev = view->find( view->current() ); if ( w->inherits( "QComboBox" ) ) setText( ( (QComboBox*)w )->currentText() ); else QTableItem::setContentFromEditor( w ); ev.setPriority( text().toInt() ); - view->updateFromTable( ev ); + //view->updateFromTable( ev ); } void ComboItem::setText( const QString& s ) { if ( m_cb ) m_cb->setCurrentItem( s.toInt()-1 ); QTableItem::setText( s ); } QString ComboItem::text()const { if ( m_cb) return m_cb->currentText(); return QTableItem::text(); } /* TodoTextItem */ TodoTextItem::~TodoTextItem() { } TodoTextItem::TodoTextItem( QTable* t, const QString& string ) : QTableItem( t, QTableItem::Never, string ) {} /* DueTextItem */ DueTextItem::DueTextItem( QTable* t, const OTodo& ev) : QTableItem(t, Never, QString::null ) { setToDoEvent( ev ); } DueTextItem::~DueTextItem() { } diff --git a/core/pim/todo/tableview.cpp b/core/pim/todo/tableview.cpp index eaaf1bc..5594b13 100644 --- a/core/pim/todo/tableview.cpp +++ b/core/pim/todo/tableview.cpp @@ -7,362 +7,353 @@ :`=1 )Y*s>-.-- : the terms of the GNU General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <qtimer.h> #include <qpoint.h> #include <qpopupmenu.h> #include "mainwindow.h" //#include "tableitems.h" #include "tableview.h" using namespace Todo; +namespace { + static const int BoxSize = 14; + static const int RowHeight = 20; +} + TableView::TableView( MainWindow* window, QWidget* wid ) : QTable( wid ), TodoView( window ) { setUpdatesEnabled( false ); viewport()->setUpdatesEnabled( false ); m_enablePaint = false; setNumRows(0); setNumCols(4); setSorting( TRUE ); setSelectionMode( NoSelection ); setColumnStretchable( 2, TRUE ); setColumnWidth(0, 20 ); setColumnWidth(1, 35 ); setLeftMargin( 0 ); verticalHeader()->hide(); horizontalHeader()->setLabel(0, tr("C.") ); horizontalHeader()->setLabel(1, tr("Prior.") ); horizontalHeader()->setLabel(2, tr("Description" ) ); setColumnStretchable(3, FALSE ); setColumnWidth(3, 20 ); horizontalHeader()->setLabel(3, tr("Deadline") ); if ( todoWindow()->showDeadline() ) showColumn( 3); else hideColumn(3 ); connect((QTable*)this, SIGNAL( clicked( int, int, int, const QPoint& ) ), this, SLOT( slotClicked(int, int, int, const QPoint& ) ) ); connect((QTable*)this, SIGNAL( pressed( int, int, int, const QPoint& ) ), this, SLOT( slotPressed(int, int, int, const QPoint& ) ) ); connect((QTable*)this, SIGNAL(valueChanged(int, int) ), this, SLOT( slotValueChanged(int, int) ) ); connect((QTable*)this, SIGNAL(currentChanged(int, int) ), this, SLOT( slotCurrentChanged(int, int) ) ); m_menuTimer = new QTimer( this ); connect( m_menuTimer, SIGNAL(timeout()), this, SLOT(slotShowMenu()) ); m_enablePaint = true; setUpdatesEnabled( true ); viewport()->setUpdatesEnabled( true ); viewport()->update(); } /* a new day has started * update the day */ void TableView::newDay() { clear(); updateView(); } TableView::~TableView() { } void TableView::slotShowMenu() { QPopupMenu *menu = todoWindow()->contextMenu( current() ); menu->exec(QCursor::pos() ); delete menu; } -OTodo TableView::find(int uid ) { - OTodo ev = TodoView::event( uid ); - return ev; -} -void TableView::updateFromTable( const OTodo& ev, CheckItem* item ) { - TodoView::update( ev.uid(), ev ); - - /* update the other columns */ - /* if completed or not we need to update - * the table - * - * We've two cases - * either item or !item - * this makes cases more easy - */ - if ( !item ) { - item = m_cache[ev.uid()]; - } - DueTextItem *due = dueItem( item->row() ); - due->setCompleted( ev.isCompleted() ); -} QString TableView::type() const { return QString::fromLatin1( tr("Table View") ); } int TableView::current() { int cur = 0; - CheckItem* i = checkItem( currentRow() ); - if (i ) - cur = i->uid(); - + // FIXME return cur; } QString TableView::currentRepresentation() { return text( currentRow(), 2); } /* show overdue */ void TableView::showOverDue( bool ) { clear(); updateView(); } void TableView::updateView( ) { setSortOrder( 0 ); setAscending( true ); sort(); OTodoAccess::List::Iterator it, end; it = sorted().begin(); end = sorted().end(); + qWarning("setTodos"); QTime time; time.start(); m_enablePaint = false; setUpdatesEnabled( false ); viewport()->setUpdatesEnabled( false ); - clear(); - QString currentCat = todoWindow()->currentCategory(); - bool showCompleted = todoWindow()->showCompleted(); - bool showOverDue = todoWindow()->showOverDue(); - qWarning( "Current Category:" + todoWindow()->currentCategory() ); - int id = todoWindow()->currentCatId(); + QTime t; t.start(); setNumRows( it.count() ); - uint i = 0; - for (; it != end; ++it ) { - OTodo todo = (*it); - /* test if the categories match */ - if ( !currentCat.isEmpty() && - !todo.categories().contains( id ) ) { - continue; - } - /* the item is completed but we shouldn't show it */ - if ( !showCompleted && todo.isCompleted() ) { - qWarning("isCompleted "); - continue; - } - /* the item is not overdue but we should only show overdue */ - if ( showOverDue && !todo.isOverdue() ) { - continue; - } - /* now it's fine to add it */ - insertTodo( todo, i ); - i++; - } - setNumRows( i ); int elc = time.elapsed(); qWarning("Adding took %d", elc/1000 ); setUpdatesEnabled( true ); viewport()->setUpdatesEnabled( true ); viewport()->update(); + m_enablePaint = true; int el = time.elapsed(); qWarning("adding took %d", el/1000 ); } -void TableView::setTodo( int uid, const OTodo& ev ) { - QMap<int, CheckItem*>::Iterator it = m_cache.find( uid ); - - if ( it != m_cache.end() ) { - int row = it.data()->row(); - - /* update checked */ - CheckItem* check = checkItem(row ); - if (check) - check->setChecked( ev.isCompleted() ); - - /* update the text */ - QString sum = ev.summary(); - setText(row, 2, sum.isEmpty() ? - ev.description().left(40).simplifyWhiteSpace() : - sum ); - - /* update priority */ - setText(row, 1, QString::number( ev.priority() ) ); +void TableView::setTodo( int, const OTodo&) { + sort(); - /* update DueDate */ - DueTextItem *due = dueItem( row ); - due->setToDoEvent( ev ); - } + /* repaint */ + QTable::update(); } -void TableView::addEvent( const OTodo& ev) { - int row= numRows(); - setNumRows( row + 1 ); - insertTodo( ev, row ); +void TableView::addEvent( const OTodo&) { + sort(); + + QTable::update(); } /* * find the event * and then replace the complete row */ void TableView::replaceEvent( const OTodo& ev) { - setTodo( ev.uid(), ev ); + addEvent( ev ); } /* * re aligning table can be slow too * FIXME: look what performs better * either this or the old align table */ void TableView::removeEvent( int ) { - clear(); updateView(); } void TableView::setShowCompleted( bool b) { qWarning("Show Completed %d" + b ); updateView(); } void TableView::setShowDeadline( bool b) { qWarning("Show DeadLine %d" + b ); if (b) showColumn(3 ); else hideColumn(3 ); } void TableView::setShowCategory( const QString& ) { qWarning("setShowCategory"); updateView(); } void TableView::clear() { - m_cache.clear(); - int rows = numRows(); - for (int r = 0; r < rows; r++ ) { - for (int c = 0; c < numCols(); c++ ) { - if ( cellWidget(r, c) ) - clearCellWidget(r, c ); - clearCell(r, c); - } - } setNumRows( 0); } -QArray<int> TableView::completed() { - int row = numRows(); - QArray<int> ids( row ); - - int j=0; - for (int i = 0; i < row; i++ ) { - CheckItem* item = checkItem(i ); - if (item->isChecked() ) { - ids[j] = item->uid(); - j++; - } - } - ids.resize( j ); - return ids; -} void TableView::slotClicked(int row, int col, int, const QPoint& point) { if ( !cellGeometry(row, col ).contains(point ) ) return; + int ui=0; // FIXME = uid(row); switch( col ) { case 0: { - CheckItem* item = checkItem( row ); + // FIXME + CheckItem* item = 0l; /* * let's see if we centered clicked */ if ( item ) { int x = point.x() -columnPos( col ); int y = point.y() -rowPos( row ); int w = columnWidth( col ); int h = rowHeight( row ); if ( x >= ( w - OCheckItem::BoxSize ) / 2 && x <= ( w - OCheckItem::BoxSize ) / 2 + OCheckItem::BoxSize && y >= ( h - OCheckItem::BoxSize ) / 2 && y <= ( h - OCheckItem::BoxSize ) / 2 + OCheckItem::BoxSize ) item->toggle(); } } break; case 1: break; case 2: { m_menuTimer->stop(); - showTodo( checkItem(row)->uid() ); + showTodo( ui ); break; } case 3: { m_menuTimer->stop(); - TodoView::edit( checkItem(row)->uid() ); + TodoView::edit( ui ); break; } } } void TableView::slotPressed(int row, int col, int, const QPoint& point) { /* TextColumn column */ if ( col == 2 && cellGeometry( row, col ).contains( point ) ) m_menuTimer->start( 750, TRUE ); } void TableView::slotValueChanged( int, int ) { qWarning("Value Changed"); } void TableView::slotCurrentChanged(int, int ) { m_menuTimer->stop(); } -/* - * hardcode to column 0 - */ -CheckItem* TableView::checkItem( int row ) { - CheckItem *i = static_cast<CheckItem*>( item( row, 0 ) ); - return i; -} -DueTextItem* TableView::dueItem( int row ) { - DueTextItem* i = static_cast<DueTextItem*> ( item(row, 3 ) ); - return i; -} QWidget* TableView::widget() { return this; } /* * We need to overwrite sortColumn * because we want to sort whole row * based + * We event want to set the setOrder + * to a sort() and update() */ void TableView::sortColumn( int row, bool asc, bool ) { QTable::sortColumn( row, asc, TRUE ); } void TableView::viewportPaintEvent( QPaintEvent* e) { qWarning("Paint event" ); if (m_enablePaint ) QTable::viewportPaintEvent( e ); } +/* + * This segment is copyrighted by TT + * it was taken from their todolist + * application this code is GPL + */ +void TableView::paintCell(QPainter* p, int row, int col, const QRect& cr, bool ) { + const QColorGroup &cg = colorGroup(); + + p->save(); + + OTodo task = sorted()[row]; + + p->fillRect( 0, 0, cr.width(), cr.height(), cg.brush( QColorGroup::Base ) ); + + QPen op = p->pen(); + p->setPen(cg.mid()); + p->drawLine( 0, cr.height() - 1, cr.width() - 1, cr.height() - 1 ); + p->drawLine( cr.width() - 1, 0, cr.width() - 1, cr.height() - 1 ); + p->setPen(op); + + QFont f = p->font(); + QFontMetrics fm(f); + + switch(col) { + case 0: + { + // completed field + int marg = ( cr.width() - BoxSize ) / 2; + int x = 0; + int y = ( cr.height() - BoxSize ) / 2; + p->setPen( QPen( cg.text() ) ); + p->drawRect( x + marg, y, BoxSize, BoxSize ); + p->drawRect( x + marg+1, y+1, BoxSize-2, BoxSize-2 ); + p->setPen( darkGreen ); + x += 1; + y += 1; + if ( task.isCompleted() ) { + QPointArray a( 9*2 ); + int i, xx, yy; + xx = x+2+marg; + yy = y+4; + for ( i=0; i<4; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + xx++; yy++; + } + yy -= 2; + for ( i=4; i<9; i++ ) { + a.setPoint( 2*i, xx, yy ); + a.setPoint( 2*i+1, xx, yy+2 ); + xx++; yy--; + } + p->drawLineSegments( a ); + } + } + break; + case 1: + // priority field + { + QString text = QString::number(task.priority()); + p->drawText(2,2 + fm.ascent(), text); + } + break; + case 2: + // description field + { + QString text = task.summary().isEmpty() ? + task.description() : + task.summary(); + p->drawText(2,2 + fm.ascent(), text); + } + break; + case 3: + { + QString text; + if (task.hasDueDate()) { + text = "HAS"; + } else { + text = tr("None"); + } + p->drawText(2,2 + fm.ascent(), text); + } + break; + } + p->restore(); +} diff --git a/core/pim/todo/tableview.h b/core/pim/todo/tableview.h index 1fa21b2..b608204 100644 --- a/core/pim/todo/tableview.h +++ b/core/pim/todo/tableview.h @@ -17,103 +17,77 @@ ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OPIE_TABLE_VIEW_H #define OPIE_TABLE_VIEW_H #include <qtable.h> #include <qmap.h> #include "tableitems.h" #include "todoview.h" class QTimer; namespace Todo { class CheckItem; class DueTextItem; class TableView : public QTable, public TodoView { Q_OBJECT public: TableView( MainWindow*, QWidget* parent ); ~TableView(); - void updateFromTable( const OTodo&, CheckItem* = 0 ); - OTodo find(int uid); QString type()const; int current(); QString currentRepresentation(); + void clear(); void showOverDue( bool ); void updateView(); void setTodo( int uid, const OTodo& ); void addEvent( const OTodo& event ); void replaceEvent( const OTodo& ); void removeEvent( int uid ); void setShowCompleted( bool ); void setShowDeadline( bool ); void setShowCategory(const QString& =QString::null ); - void clear(); void newDay(); - QArray<int> completed(); QWidget* widget(); void sortColumn(int, bool, bool ); + + /* + * we do our drawing ourselves + * because we don't want to have + * 40.000 QTableItems for 10.000 + * OTodos where we only show 10 at a time! + */ + void paintCell(QPainter* p, int row, int col, const QRect&, bool ); private: /* reimplented for internal reasons */ void viewportPaintEvent( QPaintEvent* ); - inline void insertTodo( const OTodo&, int row ); - CheckItem* checkItem( int row ); - DueTextItem* dueItem( int row ); QTimer *m_menuTimer; - QMap<int, CheckItem*> m_cache; bool m_enablePaint:1; private slots: void slotShowMenu(); void slotClicked(int, int, int, const QPoint& ); void slotPressed(int, int, int, const QPoint& ); void slotValueChanged(int, int); void slotCurrentChanged(int, int ); }; - inline void TableView::insertTodo( const OTodo& event, int row ) { - - - QString sortKey = (char) ( (event.isCompleted() ? 'a' : 'A' ) - + event.priority() ) - + Qtopia::buildSortKey( event.description() ); - CheckItem *chk = new CheckItem( this, sortKey, event.uid(), event.categories() ); - chk->setChecked( event.isCompleted() ); - - ComboItem *cmb = new ComboItem(this, QTableItem::WhenCurrent ); - cmb->setText( QString::number( event.priority() ) ); - - QString sum = event.summary(); - QTableItem* ti = new TodoTextItem( this, sum.isEmpty() ? - event.description().left(40).simplifyWhiteSpace() : - sum ); - ti->setReplaceable( FALSE ); - - DueTextItem *due = new DueTextItem(this, event ); - - setItem( row, 0, chk ); - setItem( row, 1, cmb ); - setItem( row, 2, ti ); - setItem( row, 3, due ); - - m_cache.insert( event.uid(), chk ); - } }; #endif diff --git a/core/pim/todo/todoview.h b/core/pim/todo/todoview.h index 81ace3a..9408ef1 100644 --- a/core/pim/todo/todoview.h +++ b/core/pim/todo/todoview.h @@ -73,65 +73,65 @@ namespace Todo { void update( int uid, const Todo::SmallTodo& ); void update( int uid, const OTodo& ); /* sorry you need to cast */; void update( QWidget* wid ); void remove( int uid ); }; class MainWindow; /** * due to inheretince problems we need this base class */ class ViewBase { public: virtual QWidget* widget() = 0; virtual QString type()const = 0; virtual int current() = 0; virtual QString currentRepresentation() = 0; virtual void showOverDue( bool ) = 0; /* * update the view */ virtual void updateView() = 0; virtual void addEvent( const OTodo& ) = 0; virtual void replaceEvent( const OTodo& ) = 0; virtual void removeEvent( int uid ) = 0; virtual void setShowCompleted( bool ) = 0; virtual void setShowDeadline( bool ) = 0; virtual void setShowCategory( const QString& = QString::null ) = 0; virtual void clear() = 0; - virtual QArray<int> completed() = 0; +/* virtual QArray<int> completed() = 0; */ virtual void newDay() = 0; virtual void connectShow( QObject*, const char* ) = 0; virtual void connectEdit( QObject*, const char* ) = 0; virtual void connectUpdateSmall( QObject*, const char* ) = 0; virtual void connectUpdateBig( QObject*, const char* ) = 0; virtual void connectUpdateView( QObject*, const char*) = 0; virtual void connectRemove( QObject*, const char* ) = 0; }; /** * A base class for all TodoView which are showing * a list of todos. * Either in a QTable, QListView or any other QWidget * derived class * Through the MainWindow( dispatcher ) one can access * the relevant informations * * It's not possible to have signal and slots from within * templates this way you've to register for a signal */ class TodoView : public ViewBase{ public: /** * c'tor */ TodoView( MainWindow* win ); /** *d'tor |