From b5ff7f0e602d1c8af05797ee8ac805928ae556d7 Mon Sep 17 00:00:00 2001 From: Arrigo Zanette Date: Thu, 18 Sep 2014 13:11:29 +0200 Subject: [PATCH] fixes and improvements --- backupper.h | 2 +- piechart.h | 94 ++++++++++++++++++---------- pixmapviewer.cpp | 12 +++- pixmapviewer.h | 11 +++- sak.cpp | 177 +++++++++++++++++++++++++++++++++++++++++++++-------- sak.h | 7 +++ sak.pro | 2 +- sakhits.cpp | 27 +++++--- sakmessageitem.cpp | 10 +-- sakmessageitem.h | 2 +- sakwidget.cpp | 4 +- task.cpp | 9 ++- task.h | 1 + 13 files changed, 271 insertions(+), 87 deletions(-) rewrite piechart.h (67%) diff --git a/backupper.h b/backupper.h index 7976ee1..a4a7d58 100644 --- a/backupper.h +++ b/backupper.h @@ -11,7 +11,7 @@ const char BACKUPDATEFORMAT [] = "ddMMyyyyhhmmss"; class Backupper { public: - static const int m_nCyclicBackups = 50; + static const int m_nCyclicBackups = 5; static const char m_format [14]; QMap > m_cyclicBackups; QDir m_dir; diff --git a/piechart.h b/piechart.h dissimilarity index 67% index 4bfd39c..c01ffa1 100644 --- a/piechart.h +++ b/piechart.h @@ -1,33 +1,61 @@ -#ifndef PIECHART_H_ -#define PIECHART_H_ - -#include "task.h" - -class TaskSummaryPieChart : public QGraphicsItem -{ -public: - QRectF boundingRect() const { return QRectF(-0.61,-0.6,1.2,1.2);} - void setHits(const QMap& hits) { m_hits = hits; } - virtual void paint ( QPainter * painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */ ) { - painter->save(); - QMap::const_iterator itr = m_hits.begin(), end=m_hits.end(); - /* - while(itr != end) { - double startAngle = (start - m_min) / (m_max - m_min) * 16 * 360; - double spanAngle = itr.duration / (m_max - m_min) * 16 * 360; - QPainterPath p; - p.moveTo(0,0); - p.arcTo(QRectF(0,0,1,1), spanAngle + startAngle, spanAngle); - painter->setBrush(itr.value().second); - painter->setPen(Qt::NoPen); - painter->drawPath(p); - itr++; - } - */ - painter->restore(); - } -protected: - QMap m_hits; -}; - -#endif +#ifndef PIECHART_H_ +#define PIECHART_H_ + +#include "task.h" + +class TaskSummaryPieChart : public QGraphicsItem +{ +public: + TaskSummaryPieChart(QGraphicsItem* parent = NULL) : QGraphicsItem(parent) + { + setAcceptsHoverEvents(true); + } + QRectF boundingRect() const { return QRectF(-0.61,-0.6,1.2,1.2);} + void setHits(const QList& hits) + { + qDeleteAll(m_subItems); + m_subItems.clear(); + + // compute total values per task + double total=0; + QMap totals; + for(QList::const_iterator itr = hits.begin(); itr!= hits.end(); itr++) { + const HitElement& element = (*itr); + total += element.duration; + totals[element.task] = totals.value(element.task, 0) + element.duration; + } + // sort total values + QMap sortedTotals; + for(QMap::const_iterator titr = totals.begin(); titr!=totals.end(); titr++) { + sortedTotals.insertMulti(titr.value(), titr.key()); + } + double startAngle = 90; + for(QMap::const_iterator itr = sortedTotals.begin(); itr != sortedTotals.end(); itr++) { + Task* task = (*itr); + double spanAngle = itr.key() / (total) * 360; + qDebug() << "spanAngle" << spanAngle; + QGraphicsPathItem* pathItem = new QGraphicsPathItem(this); + scene()->addItem(pathItem); + pathItem->setToolTip(task->title); + QPainterPath path; + QPainterPath p; + p.moveTo(0,0); + p.arcTo(boundingRect(), startAngle, spanAngle); + p.closeSubpath(); + pathItem->setPath(p); + pathItem->setBrush(task->bgColor); + pathItem->setPen(QPen(QBrush(task->fgColor),0)); + startAngle += spanAngle; + m_subItems.insert(task , pathItem); + } + } + virtual void paint ( QPainter * painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */ ) + { + } +// void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + +protected: + QMap m_subItems; +}; + +#endif diff --git a/pixmapviewer.cpp b/pixmapviewer.cpp index c30d86e..f3f5d9f 100644 --- a/pixmapviewer.cpp +++ b/pixmapviewer.cpp @@ -27,6 +27,13 @@ void PixmapViewer::paintEvent(QPaintEvent* ) } } +//void PixmapViewer::keyPressEvent(QKeyEvent * e) +//{ +// if (e->key() == Qt::Key_Cancel || e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete) { +// setPixmap(QPixmap()); +// } +//} + void PixmapViewer::mousePressEvent(QMouseEvent* e) { @@ -40,10 +47,11 @@ void PixmapViewer::mousePressEvent(QMouseEvent* e) QString file = QFileDialog::getOpenFileName(0, "Select an image"); QPixmap tmp; if (!file.isEmpty()) { - if (tmp.load ( file ) ) { + if ( tmp.load ( file ) ) { setPixmap(tmp); - QMessageBox::warning(0, "Failure loading image", QString("Failed load image file %1").arg(file)); emit changed(); + } else { + QMessageBox::warning(0, "Failure loading image", QString("Failed to load image file %1").arg(file)); } } } diff --git a/pixmapviewer.h b/pixmapviewer.h index f2e2712..2edd42a 100644 --- a/pixmapviewer.h +++ b/pixmapviewer.h @@ -7,13 +7,19 @@ class PixmapViewer : public QWidget { Q_OBJECT; QPixmap m_p; + bool m_scaling; public: - PixmapViewer(QWidget* parent = 0) : QWidget(parent) { + PixmapViewer(QWidget* parent = 0, bool scaling=true) : QWidget(parent) { setMinimumWidth(150); setMinimumHeight(150); + m_scaling = scaling; } void setPixmap(const QPixmap& p) { - m_p = p.scaled(qMin(p.width(), 400),qMin(p.height(),400),Qt::KeepAspectRatio); + if (m_scaling) { + m_p = p.scaled(qMin(p.width(), 400),qMin(p.height(),400),Qt::KeepAspectRatio); + } else { + m_p = p; + } update(); } QPixmap pixmap() const { return m_p; } @@ -21,6 +27,7 @@ public: signals: void changed(); protected: +// void keyPressEvent(QKeyEvent*); void mousePressEvent(QMouseEvent* e); }; diff --git a/sak.cpp b/sak.cpp index af68ca7..e0990c1 100644 --- a/sak.cpp +++ b/sak.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "sak.h" @@ -60,10 +61,19 @@ class GView : public QGraphicsView // delete this->viewport(); // } void drawBackground(QPainter* p, const QRectF & rect) { - QBrush brush(QColor(0,0,0,200)); - p->setCompositionMode(QPainter::CompositionMode_Source); - p->fillRect(rect, brush); + viewport()->setAttribute(Qt::WA_TranslucentBackground, true); + setAttribute(Qt::WA_NoSystemBackground, true); + viewport()->setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_TranslucentBackground, true); + if (backgroundPixmap.isNull()) { + QBrush brush(QColor(100,0,0,200)); + p->setCompositionMode(QPainter::CompositionMode_Source); + p->fillRect(rect, brush); + } else { + p->drawPixmap(rect, backgroundPixmap, rect.translated(backgroundPixmap.rect().center() - viewport()->rect().center())); + } } + QPixmap backgroundPixmap; }; @@ -80,7 +90,7 @@ Sak::Sak(QObject* parent) , m_changedTask(false) , m_subtaskView(false) { - m_desktopRect = qApp->desktop()->rect(); + m_desktopRect = qApp->desktop()->screenGeometry(QPoint(0,0)); m_subtaskCompleter = 0; summaryList = hitsList = 0; trayIcon=0; @@ -185,6 +195,34 @@ void Sak::init() setupSettingsWidget(); + QPixmap askingLadyPixmap; + QPixmap viewBackgroundPixmap; + QVariant askingLadyVariant = settings.value("Lady"); + if (askingLadyVariant.canConvert(QVariant::Pixmap)) { + askingLadyPixmap = askingLadyVariant.value(); + } else { + QString fileName = QFileInfo(settings.fileName()).absoluteDir().filePath( askingLadyVariant.toString() ); + askingLadyPixmap = QPixmap(fileName); + } + if(!askingLadyPixmap.isNull()) { + askingLady->setPixmap(askingLadyPixmap); + } + + QVariant viewBackgroundVariant = settings.value("View background"); + if (viewBackgroundVariant.canConvert(QVariant::Pixmap)) { + viewBackgroundPixmap = viewBackgroundVariant.value(); + } else { + QString fileName = QFileInfo(settings.fileName()).absoluteDir().filePath( viewBackgroundVariant.toString() ); + viewBackgroundPixmap = QPixmap(fileName); + } + + if(!askingLadyPixmap.isNull()) { + askingLady->setPixmap(askingLadyPixmap);\ + } + if (!viewBackgroundPixmap.isNull()) { + viewBackground->setPixmap(viewBackgroundPixmap); + } + m_settings->installEventFilter(this); hitsList->installEventFilter(this); @@ -321,15 +359,8 @@ Task Sak::loadTaskFromFile(const QString& filePath) return t; } -void Sak::flush() +void Sak::flushSettings() { - if (m_changedTask) - saveTaskChanges(); - if (m_changedHit) - saveHitChanges(); - - if (!m_settings) return; - m_backupper->doCyclicBackup(); QSettings settings(QSettings::IniFormat, QSettings::UserScope, "ZanzaSoft", "SAK"); // QByteArray tasksArray; // QDataStream stream(&tasksArray, QIODevice::ReadWrite); @@ -338,7 +369,28 @@ void Sak::flush() // settings.setValue("tasks", tasksArray); settings.setValue("Ping interval", durationSpinBox->value()); settings.setValue("Message", bodyEdit->toPlainText()); + QDir settingsDir = QFileInfo(settings.fileName()).absoluteDir(); + QString fileName = settingsDir.filePath( "lady.png"); + askingLady->pixmap().save(fileName); + settings.setValue("Lady", "lady.png"); + + fileName = settingsDir.filePath( "viewbg.png"); + viewBackground->pixmap().save(fileName); + settings.setValue("View background", "viewbg.png"); settings.sync(); +} + +void Sak::flush() +{ + if (m_changedTask) + saveTaskChanges(); + if (m_changedHit) + saveHitChanges(); + + if (!m_settings) return; + m_backupper->doCyclicBackup(); + QSettings settings(QSettings::IniFormat, QSettings::UserScope, "ZanzaSoft", "SAK"); + QDir saveDir(QFileInfo(settings.fileName()).dir()); saveDir.mkdir("SakTasks"); @@ -504,6 +556,7 @@ void Sak::destroy() stop(); if (!m_settings) return; flush(); + flushSettings(); m_settings->deleteLater(); m_view->scene()->deleteLater(); m_view->deleteLater(); @@ -545,7 +598,14 @@ bool Sak::eventFilter(QObject* obj, QEvent* e) return taskTreeEventFilter(e); } else if (obj == hitsList || obj == summaryList) { return hitsListEventFilter(e); + } else if (obj == summaryView) { + if (e->type() == QEvent::Resize || e->type() == QEvent::Show) { + summaryView->fitInView(summaryView->sceneRect(), Qt::KeepAspectRatio); + } + return false; } else if (obj == m_settings && e->type() == QEvent::Close) { + flush(); + flushSettings(); if (m_changedTask) saveTaskChanges(); if (m_changedHit) @@ -800,7 +860,7 @@ void Sak::commitCurrentTask() if (!currentTitle.isEmpty()) { if (currentTitle != currentTask) { if (m_editedTasks.contains(currentTitle)) { - QMessageBox::warning(0, "Conflict in task names", "Conflict in task names: current task " + currentTask + ", edited title " + currentTitle); + QMessageBox::warning(0, "Conflict in task names", "Conflict in task names: current task " + currentTask + ", edited title " + currentTitle); taskTitleEditor->setText(currentTask); return; } else if (m_editedTasks.contains(currentTask)) { @@ -810,6 +870,8 @@ void Sak::commitCurrentTask() } } else return; Task& t = m_editedTasks[currentTitle]; + t.description = taskTextEditor->toPlainText(); + t.tags = taskTagsEditor->text().split(QRegExp("[,:]")); t.bgColor = bgColorButton->palette().color(QPalette::Button); t.fgColor = fgColorButton->palette().color(QPalette::ButtonText); t.icon = taskPixmapViewer->pixmap(); @@ -859,6 +921,7 @@ void Sak::commitCurrentTask() } } else return; Task::SubTask& st = t.subTasks[currentTitle]; + st.description = taskTextEditor->toPlainText(); st.bgColor = bgColorButton->palette().color(QPalette::Button); st.fgColor = fgColorButton->palette().color(QPalette::ButtonText); QList items = tasksTree->findItems(currentTask,Qt::MatchExactly,0); @@ -903,33 +966,50 @@ void Sak::selectedTask() return; } + + // Disable notifications + taskPixmapViewer->blockSignals(true); + taskTextEditor->blockSignals(true); + taskTitleEditor->blockSignals(true); + taskTagsEditor->blockSignals(true); + bgColorButton->blockSignals(true); + fgColorButton->blockSignals(true); + dueEditor->blockSignals(true); + estimatedHoursEditor->blockSignals(true); + + QTreeWidgetItem* selectedItem = tasksTree->selectedItems().first(); QTreeWidgetItem* parentItem = selectedItem->parent(); QString tt = selectedItem->text(0); if (!parentItem) { taskPixmapViewer->setEnabled(true); + taskTextEditor->setEnabled(true); + taskTagsEditor->setEnabled(true); dueEditor->setEnabled(true); estimatedHoursEditor->setEnabled(true); + bgColorButton->setEnabled(true); + fgColorButton->setEnabled(true); + taskPixmapViewer->setEnabled(true); } else { taskPixmapViewer->setEnabled(false); + taskTextEditor->setEnabled(false); + taskTagsEditor->setEnabled(false); taskPixmapViewer->setPixmap(QPixmap()); dueEditor->setEnabled(false); estimatedHoursEditor->setEnabled(false); + bgColorButton->setEnabled(false); + fgColorButton->setEnabled(false); + taskPixmapViewer->setEnabled(false); } - taskTextEditor->setEnabled(true); taskTitleEditor->setEnabled(true); - bgColorButton->setEnabled(true); - fgColorButton->setEnabled(true); if (!parentItem) { // editing a task if (!m_editedTasks.contains(tt)) return; const Task& t = m_editedTasks[tt]; taskPixmapViewer->setPixmap(t.icon); - taskTextEditor->blockSignals(true); taskTextEditor->setPlainText(t.description); - taskTextEditor->blockSignals(false); taskTitleEditor->setText(t.title); QPalette p; p.setColor(QPalette::Button, t.bgColor); @@ -941,11 +1021,12 @@ void Sak::selectedTask() currentTask = t.title; currentSubtask = ""; - } else { + } else { // editing a subtask if (!m_editedTasks.contains(parentItem->text(0))) return; const Task& t = m_editedTasks[parentItem->text(0)]; if (!t.subTasks.contains(tt)) return; const Task::SubTask& st = t.subTasks[tt]; + taskTextEditor->setPlainText(st.description); taskTitleEditor->setText(st.title); QPalette p; @@ -957,6 +1038,16 @@ void Sak::selectedTask() currentTask = t.title; currentSubtask = st.title; } + + // Re-enable notifications + taskPixmapViewer->blockSignals(false); + taskTextEditor->blockSignals(false); + taskTitleEditor->blockSignals(false); + taskTagsEditor->blockSignals(false); + bgColorButton->blockSignals(false); + fgColorButton->blockSignals(false); + dueEditor->blockSignals(false); + estimatedHoursEditor->blockSignals(false); } void Sak::doubleClickedTask(QTreeWidgetItem* i, int column) @@ -1121,7 +1212,7 @@ void Sak::workingOnTask(const QString& taskName, const QString& subTask) assert(secsToEnd < 24 * 3600 * 3600); } beforeLastHit.timestamp = beforeLastHit.timestamp.addSecs( secsToEnd/2.0 ); - beforeLastHit.duration = (int)( round( secsToEnd / 60.0 ) ); + beforeLastHit.duration = (int)( qRound( secsToEnd / 60.0 ) ); // remove the current very last hit otHits.pop_back(); } @@ -1354,7 +1445,9 @@ void Sak::popup() QHash weekStats; QHash monthStats; - foreach(const Task& t, m_tasks.values()) { + for(QHash::iterator itr = m_tasks.begin(); itr!=m_tasks.end(); itr++) { + Task& t(itr.value()); + t.checkConsistency(); if (t.active) { double m = t.workedHours(fromMonth, now); monthStats[t.title] = m; @@ -1401,7 +1494,16 @@ void Sak::popup() // add the message item - SakMessageItem* sakMessage = new SakMessageItem(bodyEdit->toPlainText()); +#ifdef CENSORED + QPixmap askingLadyPixmap(":/images/whip_vale.png"); +#else + QPixmap askingLadyPixmap(":/images/whip.png"); +#endif + if (!askingLady->pixmap().isNull()) { + askingLadyPixmap = askingLady->pixmap(); + } + + SakMessageItem* sakMessage = new SakMessageItem(bodyEdit->toPlainText(), askingLadyPixmap); sakMessage->setGeometry(messageRect); m_view->scene()->addItem(sakMessage); sakMessage->show(); @@ -1417,6 +1519,7 @@ void Sak::popup() m_view->setGeometry( QRect(m_desktopRect)/*.adjusted(200,200,-200,-200 )*/ ); + m_view->backgroundPixmap = viewBackground->pixmap().scaled(r.size(), Qt::KeepAspectRatioByExpanding); m_view->show(); m_view->raise(); m_view->setFocus(); @@ -1686,12 +1789,19 @@ void Sak::setupSettingsWidget() bodyLabel = new QLabel(tr("Message:")); bodyEdit = new QTextEdit; bodyEdit->setPlainText( settings.value("Message", "

Enter a message here!

").toString() ); + askingLady = new PixmapViewer(0,false); + askingLady->setPixmap(QPixmap(":/images/whip.png")); + viewBackground = new PixmapViewer(0, false); messageLayout->addWidget(durationLabel, 1, 0); messageLayout->addWidget(durationSpinBox, 1, 1); messageLayout->addWidget(durationLabel1, 1, 2); messageLayout->addWidget(bodyLabel, 3, 0); messageLayout->addWidget(bodyEdit, 3, 1, 2, 4); + messageLayout->addWidget(new QLabel("Character image:"), 7, 0); + messageLayout->addWidget(askingLady, 7, 1, 2, 4); + messageLayout->addWidget(new QLabel("View background:"), 11, 0); + messageLayout->addWidget(viewBackground, 11, 1, 2, 4); messageLayout->setColumnStretch(3, 1); messageLayout->setRowStretch(4, 1); mainLayout->addLayout(messageLayout); @@ -1712,6 +1822,7 @@ void Sak::setupSettingsWidget() taskTextEditor = new QTextEdit; taskTextEditor->setFixedHeight(100); taskTextEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + taskTextEditor->setToolTip("Task description"); connect(taskTextEditor, SIGNAL(textChanged()), this, SLOT(commitCurrentTask())); @@ -1719,8 +1830,16 @@ void Sak::setupSettingsWidget() taskTitleEditor->setFixedHeight(20); taskTitleEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); taskTitleEditor->setValidator(new QRegExpValidator(QRegExp("[\\w]*"), this)); + taskTitleEditor->setToolTip("Task title (alphanumeric)"); connect(taskTitleEditor, SIGNAL(editingFinished()), this, SLOT(commitCurrentTask())); + taskTagsEditor = new QLineEdit; + taskTagsEditor->setFixedHeight(20); + taskTagsEditor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + taskTagsEditor->setValidator(new QRegExpValidator(QRegExp("[\\w,:]*"), this)); + taskTagsEditor->setToolTip("Task tags (alphanumeric comma or colon separated)"); + connect(taskTagsEditor, SIGNAL(editingFinished()), this, SLOT(commitCurrentTask())); + taskPixmapViewer = new PixmapViewer; mainLayout->addWidget(tasksTree, 2); QHBoxLayout* detailsLayout = new QHBoxLayout; @@ -1729,6 +1848,8 @@ void Sak::setupSettingsWidget() connect(taskPixmapViewer, SIGNAL(changed()), this, SLOT(commitCurrentTask())); editsLayout->addWidget(taskTitleEditor); editsLayout->addWidget(taskTextEditor); + editsLayout->addWidget(taskTagsEditor); + QHBoxLayout* datesLayout = new QHBoxLayout; datesLayout->addWidget(new QLabel("Due: ")); dueEditor = new QDateEdit; @@ -1771,11 +1892,15 @@ void Sak::setupSettingsWidget() QTabWidget* tabs = new QTabWidget; tabs->setTabPosition(QTabWidget::East); tabs->addTab(summaryList, "List"); - QGraphicsView* summaryView = new QGraphicsView; + summaryView = new QGraphicsView; summaryView->setScene(new QGraphicsScene); - TaskSummaryPieChart* chart = new TaskSummaryPieChart; - summaryView->scene()->addItem(new TaskSummaryPieChart); - summaryView->centerOn(chart); + summaryChart = new TaskSummaryPieChart; + summaryView->scene()->addItem(summaryChart); + summaryView->scene()->setSceneRect(summaryChart->boundingRect()); + summaryView->fitInView(summaryView->sceneRect()); + summaryView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + summaryView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + summaryView->installEventFilter(this); tabs->addTab(summaryView, "Chart"); tab4MainLayout->addWidget(tabs); cal3 = new QCalendarWidget; diff --git a/sak.h b/sak.h index 88a0ed1..24c382e 100644 --- a/sak.h +++ b/sak.h @@ -46,6 +46,7 @@ public slots: void stop(); Task loadTaskFromFile(const QString& filePath); void flush(); + void flushSettings(); void open(const QStringList& filePaths = QStringList()); // void saveAsDb(); void exportDbCsv(); @@ -155,6 +156,9 @@ private: QLabel *bodyLabel; QSpinBox *durationSpinBox; QTextEdit *bodyEdit; + PixmapViewer* askingLady; + PixmapViewer* viewBackground; + QTreeWidget* tasksTree; QComboBox* taskSelector; @@ -164,8 +168,11 @@ private: PixmapViewer* taskPixmapViewer; QTextEdit* taskTextEditor; QLineEdit* taskTitleEditor; + QLineEdit* taskTagsEditor; QSpinBox* estimatedHoursEditor; QDateEdit* dueEditor; + QGraphicsView* summaryView; + class TaskSummaryPieChart* summaryChart; QAction *minimizeAction; QAction *maximizeAction; diff --git a/sak.pro b/sak.pro index d714ebd..d7b423f 100644 --- a/sak.pro +++ b/sak.pro @@ -6,7 +6,7 @@ TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += qt -QT += gui opengl network +QT += gui opengl network console diff --git a/sakhits.cpp b/sakhits.cpp index a28058a..1f69944 100644 --- a/sakhits.cpp +++ b/sakhits.cpp @@ -304,10 +304,7 @@ bool Sak::hitsListEventFilter(QEvent* e) return true; } else if (e->type() == QEvent::Hide) { saveHitChanges(); - }/* else if (e->type() == QEvent::Show) { - m_editedTasks = m_tasks; - selectedStartDate(QDate()); - }*/ + } return false; } @@ -331,7 +328,8 @@ void Sak::selectedStartDate(const QDate& _date) } cal2->setMinimumDate(date); cal4->setMinimumDate(date); - populateHitsList(createHitsList(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate()))); + const QList& hits ( createHitsList(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate())) ); + populateHitsList(hits); if (hitsTimeline) hitsTimeline->setPeriod(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate())); } @@ -352,7 +350,9 @@ void Sak::selectedEndDate(const QDate& _date) cal2->setSelectedDate(cal1->selectedDate().addDays(1)); cal4->setSelectedDate(cal1->selectedDate().addDays(1)); } - populateHitsList(createHitsList(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate()))); + const QList& hits ( createHitsList(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate())) ); + + populateHitsList(hits); hitsTimeline->setPeriod(QDateTime(cal1->selectedDate()), QDateTime(cal2->selectedDate())); } @@ -388,9 +388,19 @@ void Sak::hitsListItemChanged(QTreeWidgetItem* i, int column) origList.takeAt(hitPosition); Task& nt(m_editedTasks[i->text(1)]); Task::Hit p(QDateTime::fromString(i->text(0), DATETIMEFORMAT), i->text(3).toUInt()); - i->setData(1, Qt::UserRole, qVariantFromValue(HitElement(&nt, i->text(2), p.timestamp, p.duration))); + QString subTask = nt.subTasks.contains(i->text(2)) ? i->text(2) : ""; + i->setData(1, Qt::UserRole, qVariantFromValue(HitElement(&nt, subTask, p.timestamp, p.duration))); qDebug() << "insert hit into task " << i->text(1) << p.timestamp; - nt.hits[i->text(2)] << p; + nt.hits[subTask] << p; + if (subTask != i->text(2)) { + i->setText(2, subTask); + } + if (nt.bgColor != i->backgroundColor(0) || nt.fgColor != i->foreground(0).color()) { + for(int j=0; j<4; j++) { + i->setBackground(j,nt.bgColor); + i->setForeground(j,nt.fgColor); + } + } } break; } @@ -540,6 +550,7 @@ void Sak::populateHitsList(const QList& hits, QTreeWidget* theHitsLi } populateHitsTimeline(hits, hitsTimeline); + summaryChart->setHits(hits); } void Sak::populateHitsTimeline(const QList& hits, Timeline* timeline ) diff --git a/sakmessageitem.cpp b/sakmessageitem.cpp index 910052d..10db290 100644 --- a/sakmessageitem.cpp +++ b/sakmessageitem.cpp @@ -1,16 +1,10 @@ #include "sakmessageitem.h" -SakMessageItem::SakMessageItem(const QString& message) : QGraphicsItem(0) { +SakMessageItem::SakMessageItem(const QString& message, const QPixmap& p) : QGraphicsItem(0) { m_rect = QRectF(QPointF(0, 0), QSizeF(800, 200)); setAcceptsHoverEvents(true); -#ifdef CENSORED - QPixmap p(":/images/whip_vale.png"); -#else - QPixmap p(":/images/whip.png"); -#endif - p = p.scaled(200, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation); - m_p=new QGraphicsPixmapItem(p,this); + m_p=new QGraphicsPixmapItem(p.scaled(200, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation),this); m_p->setPos(0,0); m_t = new QTextDocument; diff --git a/sakmessageitem.h b/sakmessageitem.h index 9e9f449..32de306 100644 --- a/sakmessageitem.h +++ b/sakmessageitem.h @@ -6,7 +6,7 @@ class SakMessageItem : public QObject, public QGraphicsItem { public: - SakMessageItem(const QString& message); + SakMessageItem(const QString& message, const QPixmap& p); ~SakMessageItem(); //void setPixmap(const QPixmap &p); //QPixmap pixmap(); diff --git a/sakwidget.cpp b/sakwidget.cpp index 809fa0e..2d41a63 100644 --- a/sakwidget.cpp +++ b/sakwidget.cpp @@ -265,8 +265,8 @@ void SakWidget::redrawPixmaps() { if (m_task.estimatedHours) { p.setPen(Qt::NoPen); QLinearGradient g(QPointF(dateInfoTopLeft.x(),0), QPointF(dateInfoTopLeft.x()+64,0)); - g.setColorAt(0.0, Qt::red); - g.setColorAt(1.0, Qt::green); + g.setColorAt(1.0, Qt::red); + g.setColorAt(0.0, Qt::green); p.setBrush(Qt::gray); QRectF infoRect(dateInfoTopLeft + QPointF(0,66), QSizeF(64, 8)); p.drawRoundedRect(infoRect,3,3); diff --git a/task.cpp b/task.cpp index a81f2c3..615c87c 100644 --- a/task.cpp +++ b/task.cpp @@ -7,6 +7,7 @@ QXmlStreamWriter & operator<< ( QXmlStreamWriter & out, const Task & task ) out.writeStartElement("Task"); out.writeAttribute("title", task.title); + out.writeAttribute("tags", task.tags.join(",")); out.writeAttribute("active", QString("%1").arg(task.active)); if (task.dueDate.isValid()) out.writeAttribute("due", task.dueDate.toString("dd/MM/yyyy")); @@ -104,6 +105,7 @@ void parseSubtask(QXmlStreamReader & in, Task & task) { QXmlStreamAttributes attrs = in.attributes(); QString title = attrs.value("title").toString(); + QStringList tags = attrs.value("tags").toString().split(QRegExp("[,:]")); Task::SubTask& st(task.subTasks[title]); QStringRef bgColor = attrs.value("bgcolor"); QStringRef fgColor = attrs.value("fgcolor"); @@ -162,6 +164,7 @@ QXmlStreamReader & operator>> ( QXmlStreamReader & in, Task & task ) if (!in.atEnd()) { QXmlStreamAttributes attrs = in.attributes(); task.title = attrs.value("title").toString(); + task.tags = attrs.value("tags").toString().split(QRegExp("[:,]")); QStringRef bgColor = attrs.value("bgcolor"); QStringRef fgColor = attrs.value("fgcolor"); QStringRef active = attrs.value("active"); @@ -294,10 +297,10 @@ double HitElement::overestimations(const QList& hits, QVectortitle << ": overestimated time from hit " << sortedList[i].timestamp << " and hit " << t << ". Expected " << expected/60 << " minutes, got " << got/60 << " (diff = " << diff/60 << ")"; } t=sortedList[i].timestamp; diff --git a/task.h b/task.h index 0780844..58467c8 100644 --- a/task.h +++ b/task.h @@ -34,6 +34,7 @@ struct Task Task() : estimatedHours(0), bgColor(Qt::white), fgColor(Qt::black), active(true), totHours(0) {} QString title, description; + QStringList tags; QDate dueDate; int estimatedHours; QPixmap icon; -- 2.11.4.GIT