00001
#include <qfile.h>
00002
#include <qclipboard.h>
00003
#include <qlayout.h>
00004
#include <qlistbox.h>
00005
#include <qptrlist.h>
00006
#include <qptrstack.h>
00007
#include <qtextstream.h>
00008
#include <qlistview.h>
00009
#include <qtimer.h>
00010
00011
#include "kapplication.h"
00012
#include <kconfig.h>
00013
#include <kdebug.h>
00014
#include <klocale.h>
00015
#include <kfiledialog.h>
00016
#include <klineeditdlg.h>
00017
#include <kmessagebox.h>
00018
00019
#include "desktoptracker.h"
00020
#include "edittaskdialog.h"
00021
#include "idletimedetector.h"
00022
#include "preferences.h"
00023
#include "task.h"
00024
#include "taskview.h"
00025
#include "timekard.h"
00026
#include "karmstorage.h"
00027
#include "printdialog.h"
00028
00029
#define T_LINESIZE 1023
00030
#define HIDDEN_COLUMN -10
00031
00032
class DesktopTracker;
00033
00034 TaskView::TaskView(QWidget *parent,
const char *name):KListView(parent,name)
00035 {
00036 _preferences = Preferences::instance();
00037 _storage = KarmStorage::instance();
00038
00039 connect(
this, SIGNAL( doubleClicked( QListViewItem * )),
00040
this, SLOT( changeTimer( QListViewItem * )));
00041
00042
00043 previousColumnWidths[0] = previousColumnWidths[1]
00044 = previousColumnWidths[2] = previousColumnWidths[3] = HIDDEN_COLUMN;
00045
00046 addColumn( i18n(
"Task Name") );
00047 addColumn( i18n(
"Session Time") );
00048 addColumn( i18n(
"Time") );
00049 addColumn( i18n(
"Total Session Time") );
00050 addColumn( i18n(
"Total Time") );
00051 setColumnAlignment( 1, Qt::AlignRight );
00052 setColumnAlignment( 2, Qt::AlignRight );
00053 setColumnAlignment( 3, Qt::AlignRight );
00054 setColumnAlignment( 4, Qt::AlignRight );
00055 adaptColumns();
00056 setAllColumnsShowFocus(
true );
00057
00058
00059 _minuteTimer =
new QTimer(
this);
00060 connect( _minuteTimer, SIGNAL( timeout() ),
this, SLOT( minuteUpdate() ));
00061 _minuteTimer->start(1000 * secsPerMinute);
00062
00063
00064 connect(_preferences, SIGNAL(iCalFile(QString)),
00065
this, SLOT(iCalFileChanged(QString)));
00066
00067
00068 connect(_preferences, SIGNAL( setupChanged() ),
this,SLOT( adaptColumns() ));
00069
00070 _minuteTimer->start(1000 * secsPerMinute);
00071
00072
00073 _idleTimeDetector =
new IdleTimeDetector( _preferences->idlenessTimeout() );
00074 connect( _idleTimeDetector, SIGNAL( extractTime(
int) ),
00075
this, SLOT( extractTime(
int) ));
00076 connect( _idleTimeDetector, SIGNAL( stopAllTimers() ),
00077
this, SLOT( stopAllTimers() ));
00078 connect( _preferences, SIGNAL( idlenessTimeout(
int) ),
00079 _idleTimeDetector, SLOT( setMaxIdle(
int) ));
00080 connect( _preferences, SIGNAL( detectIdleness(
bool) ),
00081 _idleTimeDetector, SLOT( toggleOverAllIdleDetection(
bool) ));
00082
if (!_idleTimeDetector->isIdleDetectionPossible())
00083 _preferences->disableIdleDetection();
00084
00085
00086 _autoSaveTimer =
new QTimer(
this);
00087 connect( _preferences, SIGNAL( autoSave(
bool) ),
00088
this, SLOT( autoSaveChanged(
bool) ));
00089 connect( _preferences, SIGNAL( autoSavePeriod(
int) ),
00090
this, SLOT( autoSavePeriodChanged(
int) ));
00091 connect( _autoSaveTimer, SIGNAL( timeout() ),
this, SLOT( save() ));
00092
00093
00094 _manualSaveTimer =
new QTimer(
this);
00095 connect( _manualSaveTimer, SIGNAL( timeout() ),
this, SLOT( save() ));
00096
00097
00098 _desktopTracker =
new DesktopTracker();
00099 connect( _desktopTracker, SIGNAL( reachedtActiveDesktop(
Task* ) ),
00100
this, SLOT( startTimerFor(
Task*) ));
00101 connect( _desktopTracker, SIGNAL( leftActiveDesktop(
Task* ) ),
00102
this, SLOT( stopTimerFor(
Task*) ));
00103 }
00104
00105 TaskView::~TaskView()
00106 {
00107 _preferences->
save();
00108 }
00109
00110 Task*
TaskView::first_child()
const
00111
{
00112
return static_cast<Task*>(firstChild());
00113 }
00114
00115 Task*
TaskView::current_item()
const
00116
{
00117
return static_cast<Task*>(currentItem());
00118 }
00119
00120 Task*
TaskView::item_at_index(
int i)
00121 {
00122
return static_cast<Task*>(itemAtIndex(i));
00123 }
00124
00125 void TaskView::load()
00126 {
00127
00128 QString err = _storage->
load(
this, _preferences);
00129
00130
if (!err.isEmpty())
00131 {
00132 KMessageBox::error(
this, err);
00133
return;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
int task_idx = 0;
00143
for (
Task* task =
item_at_index(task_idx);
00144 task;
00145 task = item_at_index(++task_idx))
00146 {
00147 _desktopTracker->
registerForDesktops( task, task->
getDesktops() );
00148 }
00149
00150 setSelected(
first_child(),
true);
00151 setCurrentItem(
first_child());
00152 _desktopTracker->
startTracking();
00153 }
00154
00155 void TaskView::loadFromFlatFile()
00156 {
00157 kdDebug() <<
"TaskView::loadFromFlatFile()" << endl;
00158
00159
00160
00161 QString fileName(KFileDialog::getOpenFileName(QString::null, QString::null,
00162 0));
00163
if (!fileName.isEmpty()) {
00164 QString err = _storage->
loadFromFlatFile(
this, fileName);
00165
if (!err.isEmpty())
00166 {
00167 KMessageBox::error(
this, err);
00168
return;
00169 }
00170
00171
00172
int task_idx = 0;
00173
Task* task =
item_at_index(task_idx++);
00174
while (task)
00175 {
00176
00177 _desktopTracker->
registerForDesktops( task, task->
getDesktops() );
00178 task = item_at_index(task_idx++);
00179 }
00180
00181 setSelected(
first_child(),
true);
00182 setCurrentItem(
first_child());
00183
00184 _desktopTracker->
startTracking();
00185 }
00186 }
00187
00188 void TaskView::scheduleSave()
00189 {
00190 _manualSaveTimer->start( 10,
true );
00191 }
00192
00193 void TaskView::save()
00194 {
00195
00196
00197
00198
00199
00200
#if 0
00201
00202
00203
00204
00205
00206
00207
00208
for (
unsigned int i = 0; i < activeTasks.count(); i++)
00209 {
00210 activeTasks.at(i)->setRunning(
false, _storage);
00211 activeTasks.at(i)->setRunning(
true, _storage);
00212 }
00213
00214
00215
if (activeTasks.count() == 0)
00216
#endif
00217
{
00218 _storage->
save(
this);
00219 }
00220 }
00221
00222 void TaskView::startCurrentTimer()
00223 {
00224 startTimerFor(
current_item() );
00225 }
00226
00227 long TaskView::count()
00228 {
00229
long n = 0;
00230
for (
Task* t =
item_at_index(n); t; t=item_at_index(++n));
00231
return n;
00232 }
00233
00234
void TaskView::startTimerFor(
Task* task)
00235 {
00236
if (task != 0 && activeTasks.findRef(task) == -1) {
00237 _idleTimeDetector->
startIdleDetection();
00238 task->
setRunning(
true, _storage);
00239 activeTasks.append(task);
00240 emit updateButtons();
00241
if ( activeTasks.count() == 1 )
00242 emit timersActive();
00243
00244 emit tasksChanged( activeTasks);
00245 }
00246 }
00247
00248 void TaskView::stopAllTimers()
00249 {
00250
for (
unsigned int i=0; i<activeTasks.count();i++) {
00251 activeTasks.at(i)->setRunning(
false, _storage);
00252 }
00253 _idleTimeDetector->
stopIdleDetection();
00254 activeTasks.clear();
00255 emit updateButtons();
00256 emit timersInactive();
00257 emit tasksChanged( activeTasks);
00258 }
00259
00260 void TaskView::startNewSession()
00261 {
00262 QListViewItemIterator item(
first_child());
00263
for ( ; item.current(); ++item ) {
00264
Task * task = (
Task *) item.current();
00265 task->
startNewSession();
00266 }
00267 }
00268
00269 void TaskView::resetTimeForAllTasks()
00270 {
00271 QListViewItemIterator item(
first_child());
00272
for ( ; item.current(); ++item ) {
00273
Task * task = (
Task *) item.current();
00274 task->
resetTimes();
00275 }
00276 }
00277
00278
void TaskView::stopTimerFor(
Task* task)
00279 {
00280
if (task != 0 && activeTasks.findRef(task) != -1) {
00281 activeTasks.removeRef(task);
00282 task->
setRunning(
false, _storage);
00283
if (activeTasks.count()== 0) {
00284 _idleTimeDetector->
stopIdleDetection();
00285 emit timersInactive();
00286 }
00287 emit updateButtons();
00288 }
00289 emit tasksChanged( activeTasks);
00290 }
00291
00292 void TaskView::stopCurrentTimer()
00293 {
00294 stopTimerFor(
current_item());
00295 }
00296
00297
00298 void TaskView::changeTimer(QListViewItem *)
00299 {
00300
Task *task =
current_item();
00301
if (task != 0 && activeTasks.findRef(task) == -1) {
00302
00303
for (
unsigned int i=0; i<activeTasks.count();i++) {
00304 (activeTasks.at(i))->setRunning(
false, _storage);
00305 }
00306 activeTasks.clear();
00307
00308
00309
startCurrentTimer();
00310 }
00311
else {
00312
stopCurrentTimer();
00313 }
00314 }
00315
00316
void TaskView::minuteUpdate()
00317 {
00318 addTimeToActiveTasks(1,
false);
00319 }
00320
00321
void TaskView::addTimeToActiveTasks(
int minutes,
bool do_logging)
00322 {
00323
for(
unsigned int i=0; i<activeTasks.count();i++)
00324 activeTasks.at(i)->changeTime(minutes, do_logging, _storage);
00325 }
00326
00327 void TaskView::newTask()
00328 {
00329
newTask(i18n(
"New Task"), 0);
00330 }
00331
00332 void TaskView::newTask(QString caption,
Task *parent)
00333 {
00334
EditTaskDialog *dialog =
new EditTaskDialog(caption,
false);
00335
long total, totalDiff, session, sessionDiff;
00336 DesktopList desktopList;
00337
Task *task;
00338
00339
int result = dialog->exec();
00340
if (result == QDialog::Accepted) {
00341 QString taskName = i18n(
"Unnamed Task");
00342
if (!dialog->
taskName().isEmpty()) {
00343 taskName = dialog->
taskName();
00344 }
00345
00346 total = totalDiff = session = sessionDiff = 0;
00347 dialog->
status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00348
00349
00350
00351
if (desktopList.size() == (
unsigned int)_desktopTracker->
desktopCount())
00352 desktopList.clear();
00353
00354
if (parent == 0)
00355 {
00356 task =
new Task(taskName, total, session, desktopList,
this);
00357 task->
setUid(_storage->
addTask(task, 0));
00358 }
00359
else
00360 {
00361 task =
new Task(taskName, total, session, desktopList, parent);
00362 task->
setUid(_storage->
addTask(task, parent));
00363 }
00364
00365
if (!task->
uid().isNull())
00366 {
00367 _desktopTracker->
registerForDesktops( task, desktopList );
00368
00369 setCurrentItem( task );
00370 setSelected( task,
true );
00371
00372
save();
00373 }
00374
else
00375 {
00376
delete task;
00377 KMessageBox::error(0,i18n(
00378
"Error storing new task--your changes were not saved."));
00379 }
00380 }
00381
00382
delete dialog;
00383 }
00384
00385 void TaskView::newSubTask()
00386 {
00387
Task* task =
current_item();
00388
if(!task)
00389
return;
00390
newTask(i18n(
"New Sub Task"), task);
00391 task->setOpen(
true);
00392 setRootIsDecorated(
true);
00393 }
00394
00395
void TaskView::editTask()
00396 {
00397
Task *task =
current_item();
00398
if (!task)
00399
return;
00400
00401 DesktopList desktopList = task->
getDesktops();
00402
EditTaskDialog *dialog =
new EditTaskDialog(i18n(
"Edit Task"),
true, &desktopList);
00403 dialog->
setTask( task->
name(),
00404 task->
time(),
00405 task->
sessionTime() );
00406
int result = dialog->exec();
00407
if (result == QDialog::Accepted) {
00408 QString taskName = i18n(
"Unnamed Task");
00409
if (!dialog->
taskName().isEmpty()) {
00410 taskName = dialog->
taskName();
00411 }
00412
00413 task->
setName(taskName, _storage);
00414
00415
00416
long total, session, totalDiff, sessionDiff;
00417 total = totalDiff = session = sessionDiff = 0;
00418 DesktopList desktopList;
00419 dialog->
status( &total, &totalDiff, &session, &sessionDiff, &desktopList);
00420
00421
if( totalDiff != 0 || sessionDiff != 0)
00422 task->
changeTimes( sessionDiff ,totalDiff,
true, _storage );
00423
00424
00425
00426
if (desktopList.size() == (
unsigned int)_desktopTracker->
desktopCount())
00427 desktopList.clear();
00428
00429 task->
setDesktopList(desktopList);
00430
00431 _desktopTracker->
registerForDesktops( task, desktopList );
00432
00433 emit updateButtons();
00434 }
00435
delete dialog;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 void TaskView::deleteTask(
bool markingascomplete)
00454 {
00455
Task *task =
current_item();
00456
if (task == 0) {
00457 KMessageBox::information(0,i18n(
"No task selected."));
00458
return;
00459 }
00460
00461
int response = KMessageBox::Yes;
00462
if (!markingascomplete && _preferences->
promptDelete()) {
00463
if (task->childCount() == 0) {
00464 response = KMessageBox::warningYesNo( 0,
00465 i18n(
"Are you sure you want to delete "
00466
"the task named\n\"%1\" and its entire history?")
00467 .arg(task->
name()),
00468 i18n(
"Deleting Task"));
00469 }
00470
else {
00471 response = KMessageBox::warningYesNo( 0,
00472 i18n(
"Are you sure you want to delete the task named"
00473
"\n\"%1\" and its entire history?\n"
00474
"NOTE: all its subtasks and their history will also "
00475
"be deleted!").arg(task->
name()),
00476 i18n(
"Deleting Task"));
00477 }
00478 }
00479
00480
if (response == KMessageBox::Yes)
00481 {
00482
if (markingascomplete)
00483 {
00484 task->
setPercentComplete(100, _storage);
00485
save();
00486
00487
00488
00489
00490
00491
00492 }
00493
else
00494 {
00495 task->
remove(activeTasks, _storage);
00496 task->
removeFromView();
00497
save();
00498 }
00499
00500
00501
bool anyChilds =
false;
00502
for(
Task* child =
first_child();
00503 child;
00504 child = child->
nextSibling()) {
00505
if (child->childCount() != 0) {
00506 anyChilds =
true;
00507
break;
00508 }
00509 }
00510
if (!anyChilds) {
00511 setRootIsDecorated(
false);
00512 }
00513
00514
00515
if (activeTasks.count() == 0) {
00516 _idleTimeDetector->
stopIdleDetection();
00517 emit timersInactive();
00518 }
00519
00520 emit tasksChanged( activeTasks );
00521 }
00522 }
00523
00524 void TaskView::extractTime(
int minutes)
00525 {
00526 addTimeToActiveTasks(-minutes,
true);
00527 }
00528
00529
void TaskView::autoSaveChanged(
bool on)
00530 {
00531
if (on) {
00532 _autoSaveTimer->start(_preferences->
autoSavePeriod()*1000*secsPerMinute);
00533 }
00534
else {
00535
if (_autoSaveTimer->isActive()) {
00536 _autoSaveTimer->stop();
00537 }
00538 }
00539 }
00540
00541
void TaskView::autoSavePeriodChanged(
int )
00542 {
00543 autoSaveChanged(_preferences->
autoSave());
00544 }
00545
00546
void TaskView::adaptColumns()
00547 {
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
for(
int x=1; x <= 4; x++) {
00558
00559
if( _preferences->
displayColumn(x-1)
00560 && previousColumnWidths[x-1] != HIDDEN_COLUMN )
00561 {
00562 setColumnWidth( x, previousColumnWidths[x-1] );
00563 previousColumnWidths[x-1] = HIDDEN_COLUMN;
00564 setColumnWidthMode( x, QListView::Maximum );
00565 }
00566
00567
else
00568
if( ! _preferences->
displayColumn(x-1)
00569 && previousColumnWidths[x-1] == HIDDEN_COLUMN )
00570 {
00571 setColumnWidthMode( x, QListView::Manual );
00572
00573 previousColumnWidths[x-1] = columnWidth( x );
00574 setColumnWidth( x, 0 );
00575 }
00576 }
00577 }
00578
00579 void TaskView::deletingTask(
Task* deletedTask)
00580 {
00581 DesktopList desktopList;
00582
00583 _desktopTracker->
registerForDesktops( deletedTask, desktopList );
00584 activeTasks.removeRef( deletedTask );
00585
00586 emit tasksChanged( activeTasks);
00587 }
00588
00589 void TaskView::iCalFileChanged(QString file)
00590 {
00591 kdDebug() <<
"TaskView:iCalFileChanged: " << file << endl;
00592
load();
00593 }
00594
00595 QValueList<HistoryEvent>
TaskView::getHistory(
const QDate& from,
00596
const QDate& to)
const
00597
{
00598
return _storage->
getHistory(from, to);
00599 }
00600
00601
void TaskView::markTaskAsComplete()
00602 {
00603
if (
current_item())
00604 kdDebug() <<
"TaskView::markTaskAsComplete: "
00605 <<
current_item()->
uid() << endl;
00606
else
00607 kdDebug() <<
"TaskView::markTaskAsComplete: null current_item()" << endl;
00608
00609
bool markingascomplete =
true;
00610 deleteTask(markingascomplete);
00611 }
00612
00613 void TaskView::clipTotals()
00614 {
00615
TimeKard *t =
new TimeKard();
00616
if (
current_item() &&
current_item()->
isRoot())
00617 {
00618
int response = KMessageBox::questionYesNo( 0,
00619 i18n(
"Copy totals for just this task and its subtasks?"
00620
" (Click No to copy totals for all tasks.)"));
00621
if (response == KMessageBox::Yes)
00622 {
00623 KApplication::clipboard()->setText(t->
totalsAsText(
this));
00624 }
00625
else
00626 {
00627 KApplication::clipboard()->setText(t->
totalsAsText(
this,
false));
00628 }
00629 }
00630
else
00631 {
00632 KApplication::clipboard()->setText(t->
totalsAsText(
this));
00633 }
00634 }
00635
00636 void TaskView::clipHistory()
00637 {
00638
00639 PrintDialog *dialog =
new PrintDialog();
00640
if (dialog->exec()== QDialog::Accepted)
00641 {
00642
TimeKard *t =
new TimeKard();
00643 KApplication::clipboard()->
00644 setText(t->
historyAsText(
this, dialog->from(), dialog->to()));
00645 }
00646 }
00647
00648
#include "taskview.moc"