X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=src%2Ftaskeditor.cpp;fp=src%2Ftaskeditor.cpp;h=e15d4b347e388964c88d8d8bfbd9f0f02ccab041;hb=d483bd8e6523c23c6f1d8908a2e0611c2bc9ff4f;hp=0000000000000000000000000000000000000000;hpb=7dfa3fe589d1722d49681f42cdb0bf1e6efb5223;p=sven%2Fvym.git diff --git a/src/taskeditor.cpp b/src/taskeditor.cpp new file mode 100644 index 0000000..e15d4b3 --- /dev/null +++ b/src/taskeditor.cpp @@ -0,0 +1,443 @@ +#include "taskeditor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "branchitem.h" +#include "mainwindow.h" +#include "task.h" +#include "taskmodel.h" +#include "vymmodel.h" + +extern Main *mainWindow; +extern Settings settings; +extern QMenu *taskContextMenu; +extern TaskModel *taskModel; + +extern QString editorFocusStyle; + +TaskEditor::TaskEditor(QWidget *) +{ + // Creat Table view + view = new QTableView; + + setMinimumWidth(350); + + QVBoxLayout *mainLayout = new QVBoxLayout; + + QToolBar *tb = new QToolBar("TaskEditor filters"); + tb->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + mainLayout->addWidget(tb); + + // Original icon from KDE: + // /usr/share/icons/oxygen/16x16/actions/view-filter.png + + QIcon icon = QIcon(":/taskfilter-currentmap.png"); + QAction *a = + new QAction(icon, "", this); // tr( "Current map","TaskEditor" ),this ); + a->setToolTip( + tr("Show only tasks from current map", "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterMap", true).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterMap())); + actionToggleFilterMap = a; + + icon = QIcon(":/taskfilter-activetask.png"); + a = new QAction(icon, "", this); // tr( "Active tasks","TaskEditor" ),this + // ); + a->setToolTip(tr("Show only active tasks", "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterActive", true).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterActive())); + actionToggleFilterActive = a; + + icon = QIcon(":/taskfilter-newtask.png"); + a = new QAction(icon, "", this); // tr( "New tasks","TaskEditor" ),this ); + a->setToolTip(tr("Show only new tasks", "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterNew", false).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterNew())); + actionToggleFilterNew = a; + + icon = QIcon(":/flag-stopsign.svg"); + a = new QAction(icon, "", this); // tr( "New tasks","TaskEditor" ),this ); + a->setToolTip(tr("Show only blocker tasks", "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterBlocker", false).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterBlocker())); + actionToggleFilterBlocker = a; + + icon = QIcon(":/flag-arrow-up.svg"); + a = new QAction(icon, "", this); + a->setToolTip(tr("Show only tasks marked with this arrow-up flag", + "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterFlags1", false).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags1())); + actionToggleFilterFlags1 = a; + + icon = QIcon(":/flag-arrow-2up.svg"); + a = new QAction(icon, "", this); + a->setToolTip(tr("Show only tasks marked with this arrow-up flag", + "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterFlags2", false).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags2())); + actionToggleFilterFlags2 = a; + + icon = QIcon(":/flag-no-arrow-up.png"); + a = new QAction(icon, "", this); + a->setToolTip(tr("Show only tasks marked without any arrow-up flag", + "Filters in task Editor")); + a->setCheckable(true); + a->setChecked(settings.value("/taskeditor/filterFlags3", false).toBool()); + tb->addAction(a); + connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags3())); + actionToggleFilterFlags3 = a; + + // Clone actions defined in MainWindow + foreach (QAction *qa, mainWindow->taskEditorActions) { + a = new QAction(this); + a->setShortcut(qa->shortcut()); + a->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect(a, SIGNAL(triggered()), qa, SLOT(trigger())); + addAction(a); + } + + mainLayout->addWidget(view); + setLayout(mainLayout); + + view->setSelectionBehavior(QAbstractItemView::SelectRows); + view->horizontalHeader()->setStretchLastSection(true); + view->verticalHeader()->hide(); + // view->setEditTriggers(QAbstractItemView::NoEditTriggers); + + filterActiveModel = new TaskFilterModel; + filterActiveModel->setSourceModel(taskModel); + filterActiveModel->setDynamicSortFilter(true); + + view->setModel(filterActiveModel); + view->setSortingEnabled(true); + view->setIconSize(QSize(64, 64)); + + QHeaderView *hv = view->horizontalHeader(); + hv->setSortIndicator(0, Qt::AscendingOrder); + view->sortByColumn(hv->sortIndicatorSection(), hv->sortIndicatorOrder()); + + view->setSelectionMode(QAbstractItemView::ExtendedSelection); + view->setDragEnabled(true); + view->setAcceptDrops(true); + view->setDropIndicatorShown(true); + view->setAutoScroll(false); + + blockExternalSelect = false; + + connect(view->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, + SLOT(selectionChanged(QItemSelection, QItemSelection))); + + connect(view, SIGNAL(clicked(QModelIndex)), + this, SLOT(cellClicked(QModelIndex))); + + // Enable wordwrap when data changes + if (settings.value("/taskeditor/wordWrap", true) + .toBool()) // FIXME-3 not working or only sometimes? + { + connect(taskModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), view, + SLOT(resizeRowsToContents())); + connect(view->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), + view, SLOT(resizeRowsToContents())); + } + + // Initialize view filters according to previous settings + setFilterMap(); + setFilterActive(); + setFilterNew(); + setFilterBlocker(); + setFilterFlags1(); + setFilterFlags2(); + setFilterFlags3(); + + // Initialize display of parents of a task + bool ok; + int i = settings.value("/taskeditor/showParentsLevel", 0).toInt(&ok); + if (ok) + taskModel->setShowParentsLevel(i); + + view->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(view->horizontalHeader(), + SIGNAL(customContextMenuRequested(QPoint)), + SLOT(headerContextMenu())); + + view->setStyleSheet("QTableView:focus {" + editorFocusStyle + "}"); + + updateColumnLayout(); +} + +TaskEditor::~TaskEditor() +{ + settings.setValue("/taskeditor/filterMap", + actionToggleFilterMap->isChecked()); + settings.setValue("/taskeditor/filterActive", + actionToggleFilterActive->isChecked()); + settings.setValue("/taskeditor/filterNew", + actionToggleFilterNew->isChecked()); + settings.setValue("/taskeditor/filterBlocker", + actionToggleFilterBlocker->isChecked()); + settings.setValue("/taskeditor/filterFlags1", + actionToggleFilterFlags1->isChecked()); + settings.setValue("/taskeditor/filterFlags2", + actionToggleFilterFlags2->isChecked()); + settings.setValue("/taskeditor/filterFlags3", + actionToggleFilterFlags3->isChecked()); + settings.setValue("/taskeditor/showParentsLevel", + taskModel->getShowParentsLevel()); + + for (int i = 0; i <= 8; i++) { + settings.setValue(QString("/taskeditor/column/%1/width").arg(i), + view->columnWidth(i)); + settings.setValue(QString("/taskeditor/column/%1/hidden").arg(i), + view->isColumnHidden(i)); + } +} + +void TaskEditor::setMapName(const QString &n) +{ + currentMapName = n; + + setFilterMap(); +} + +bool TaskEditor::isUsedFilterMap() +{ + return actionToggleFilterMap->isChecked(); +} + +void TaskEditor::setFilterMap() +{ + if (isUsedFilterMap()) + filterActiveModel->setMapFilter(currentMapName); + else + filterActiveModel->setMapFilter(QString()); + updateFilters(); +} + +bool TaskEditor::isUsedFilterActive() +{ + return actionToggleFilterActive->isChecked(); +} + +void TaskEditor::setFilterActive() +{ + filterActiveModel->setFilter(actionToggleFilterActive->isChecked()); + updateFilters(); +} + +void TaskEditor::setFilterNew() +{ + filterActiveModel->setFilterNew(actionToggleFilterNew->isChecked()); + updateFilters(); +} + +void TaskEditor::setFilterBlocker() +{ + filterActiveModel->setFilterBlocker(actionToggleFilterBlocker->isChecked()); + updateFilters(); +} + +void TaskEditor::setFilterFlags1() +{ + filterActiveModel->setFilterFlags1(actionToggleFilterFlags1->isChecked()); + updateFilters(); +} + +void TaskEditor::setFilterFlags2() +{ + filterActiveModel->setFilterFlags2(actionToggleFilterFlags2->isChecked()); + updateFilters(); +} + +void TaskEditor::setFilterFlags3() +{ + filterActiveModel->setFilterFlags3(actionToggleFilterFlags3->isChecked()); + updateFilters(); +} + +void TaskEditor::updateFilters() +{ + // ugly, but calling twice updates rows as expected // FIXME-3 review... + filterActiveModel->invalidate(); + filterActiveModel->invalidate(); +} + +bool TaskEditor::taskVisible(Task *task) +{ + return filterActiveModel->taskVisible(task); +} + +void TaskEditor::showSelection() +{ + QModelIndexList list = view->selectionModel()->selectedIndexes(); + if (list.count() > 0) + // Usually whole row is selected, so just go for first cell + view->scrollTo(taskModel->index(taskModel->getTask(list.first())), + QAbstractItemView::EnsureVisible); +} + +bool TaskEditor::select(Task *task) +{ + if (task) { + blockExternalSelect = true; + QModelIndex i0b = taskModel->index(task); + QModelIndex i0e = taskModel->indexRowEnd(task); + + QModelIndex i1b = filterActiveModel->mapFromSource(i0b); + QModelIndex i1e = filterActiveModel->mapFromSource(i0e); + + QItemSelection sel(i1b, i1e); + + view->selectionModel()->select(sel, + QItemSelectionModel::ClearAndSelect); + blockExternalSelect = false; + return true; + } + return false; +} + +void TaskEditor::clearSelection() { view->selectionModel()->clearSelection(); } + +void TaskEditor::cellClicked(QModelIndex ix_unmapped) +{ + QModelIndex ix = filterActiveModel->mapToSource(ix_unmapped); + if (ix.isValid() && ix.column() == 2) + taskModel->getTask(ix)->getBranch()->getModel()->cycleTaskStatus(); +} + +void TaskEditor::headerContextMenu() +{ + // qDebug() << "TE::headerContextMenu()"; + // Trying to workaround https://bugreports.qt.io/browse/QTBUG-52307 + // view->horizontalHeader()->setStretchLastSection(true); + // view->resizeColumnsToContents(); + // updateGeometry(); + // show(); +} + +void TaskEditor::updateColumnLayout() +{ + // Update column widths and visibility + + QString s = "/taskeditor/column/%1/"; + + // Priority + int i = 0; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", false).toBool()); + + // Delta + i = 1; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", false).toBool()); + + // Status + i = 2; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", false).toBool()); + + // Age total + i = 3; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", true).toBool()); + + // Age mod + i = 4; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", true).toBool()); + + // Sleep + i = 5; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", true).toBool()); + + // Map + i = 6; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 100).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", true).toBool()); + + // Flags + i = 7; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", false).toBool()); + + // Taskname + i = 8; + view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt()); + view->setColumnHidden(i, + settings.value(s.arg(i) + "hidden", false).toBool()); +} + +void TaskEditor::selectionChanged(const QItemSelection &selected, + const QItemSelection &) +{ + // FIXME-3 what, if multiple selection in MapEditor? + + if (selected.indexes().isEmpty()) + // Avoid segfault on quit, when selected is empty + return; + + QItemSelection sel0 = filterActiveModel->mapSelectionToSource(selected); + QModelIndex ix = sel0.indexes().first(); + Task *t = taskModel->getTask(ix); + if (t) { + BranchItem *bi = t->getBranch(); + if (bi) { + VymModel *m = bi->getModel(); + if (!blockExternalSelect) + m->select(bi); + if (m != mainWindow->currentModel()) + mainWindow->gotoModel(m); + view->setStyleSheet( + "QTableView {selection-background-color: " + + m->getSelectionBrushColor().name() + + "; selection-color:" + bi->getHeadingColor().name() + "}" + + "QTableView:focus {" + editorFocusStyle + "}"); + view->scrollTo(selected.indexes().first()); + } + } +} + +void TaskEditor::contextMenuEvent(QContextMenuEvent *e) +{ + taskContextMenu->popup(e->globalPos()); +} + +void TaskEditor::toggleFilterMap() { setFilterMap(); } + +void TaskEditor::toggleFilterActive() { setFilterActive(); } +void TaskEditor::toggleFilterNew() { setFilterNew(); } +void TaskEditor::toggleFilterBlocker() { setFilterBlocker(); } + +void TaskEditor::toggleFilterFlags1() { setFilterFlags1(); } +void TaskEditor::toggleFilterFlags2() { setFilterFlags2(); } +void TaskEditor::toggleFilterFlags3() { setFilterFlags3(); }