1 #include "taskeditor.h"
3 #include <QAbstractTableModel>
8 #include <QSortFilterProxyModel>
11 #include <QVBoxLayout>
13 #include "branchitem.h"
14 #include "mainwindow.h"
16 #include "taskmodel.h"
19 extern Main *mainWindow;
20 extern Settings settings;
21 extern QMenu *taskContextMenu;
22 extern TaskModel *taskModel;
24 extern QString editorFocusStyle;
26 TaskEditor::TaskEditor(QWidget *)
29 view = new QTableView;
33 QVBoxLayout *mainLayout = new QVBoxLayout;
35 QToolBar *tb = new QToolBar("TaskEditor filters");
36 tb->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
37 mainLayout->addWidget(tb);
39 // Original icon from KDE:
40 // /usr/share/icons/oxygen/16x16/actions/view-filter.png
42 QIcon icon = QIcon(":/taskfilter-currentmap.png");
44 new QAction(icon, "", this); // tr( "Current map","TaskEditor" ),this );
46 tr("Show only tasks from current map", "Filters in task Editor"));
47 a->setCheckable(true);
48 a->setChecked(settings.value("/taskeditor/filterMap", true).toBool());
50 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterMap()));
51 actionToggleFilterMap = a;
53 icon = QIcon(":/taskfilter-activetask.png");
54 a = new QAction(icon, "", this); // tr( "Active tasks","TaskEditor" ),this
56 a->setToolTip(tr("Show only active tasks", "Filters in task Editor"));
57 a->setCheckable(true);
58 a->setChecked(settings.value("/taskeditor/filterActive", true).toBool());
60 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterActive()));
61 actionToggleFilterActive = a;
63 icon = QIcon(":/taskfilter-newtask.png");
64 a = new QAction(icon, "", this); // tr( "New tasks","TaskEditor" ),this );
65 a->setToolTip(tr("Show only new tasks", "Filters in task Editor"));
66 a->setCheckable(true);
67 a->setChecked(settings.value("/taskeditor/filterNew", false).toBool());
69 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterNew()));
70 actionToggleFilterNew = a;
72 icon = QIcon(":/flag-stopsign.svg");
73 a = new QAction(icon, "", this); // tr( "New tasks","TaskEditor" ),this );
74 a->setToolTip(tr("Show only blocker tasks", "Filters in task Editor"));
75 a->setCheckable(true);
76 a->setChecked(settings.value("/taskeditor/filterBlocker", false).toBool());
78 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterBlocker()));
79 actionToggleFilterBlocker = a;
81 icon = QIcon(":/flag-arrow-up.svg");
82 a = new QAction(icon, "", this);
83 a->setToolTip(tr("Show only tasks marked with this arrow-up flag",
84 "Filters in task Editor"));
85 a->setCheckable(true);
86 a->setChecked(settings.value("/taskeditor/filterFlags1", false).toBool());
88 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags1()));
89 actionToggleFilterFlags1 = a;
91 icon = QIcon(":/flag-arrow-2up.svg");
92 a = new QAction(icon, "", this);
93 a->setToolTip(tr("Show only tasks marked with this arrow-up flag",
94 "Filters in task Editor"));
95 a->setCheckable(true);
96 a->setChecked(settings.value("/taskeditor/filterFlags2", false).toBool());
98 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags2()));
99 actionToggleFilterFlags2 = a;
101 icon = QIcon(":/flag-no-arrow-up.png");
102 a = new QAction(icon, "", this);
103 a->setToolTip(tr("Show only tasks marked without any arrow-up flag",
104 "Filters in task Editor"));
105 a->setCheckable(true);
106 a->setChecked(settings.value("/taskeditor/filterFlags3", false).toBool());
108 connect(a, SIGNAL(triggered()), this, SLOT(toggleFilterFlags3()));
109 actionToggleFilterFlags3 = a;
111 // Clone actions defined in MainWindow
112 foreach (QAction *qa, mainWindow->taskEditorActions) {
113 a = new QAction(this);
114 a->setShortcut(qa->shortcut());
115 a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
116 connect(a, SIGNAL(triggered()), qa, SLOT(trigger()));
120 mainLayout->addWidget(view);
121 setLayout(mainLayout);
123 view->setSelectionBehavior(QAbstractItemView::SelectRows);
124 view->horizontalHeader()->setStretchLastSection(true);
125 view->verticalHeader()->hide();
126 // view->setEditTriggers(QAbstractItemView::NoEditTriggers);
128 filterActiveModel = new TaskFilterModel;
129 filterActiveModel->setSourceModel(taskModel);
130 filterActiveModel->setDynamicSortFilter(true);
132 view->setModel(filterActiveModel);
133 view->setSortingEnabled(true);
134 view->setIconSize(QSize(64, 64));
136 QHeaderView *hv = view->horizontalHeader();
137 hv->setSortIndicator(0, Qt::AscendingOrder);
138 view->sortByColumn(hv->sortIndicatorSection(), hv->sortIndicatorOrder());
140 view->setSelectionMode(QAbstractItemView::ExtendedSelection);
141 view->setDragEnabled(true);
142 view->setAcceptDrops(true);
143 view->setDropIndicatorShown(true);
144 view->setAutoScroll(false);
146 blockExternalSelect = false;
148 connect(view->selectionModel(),
149 SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
150 SLOT(selectionChanged(QItemSelection, QItemSelection)));
152 connect(view, SIGNAL(clicked(QModelIndex)),
153 this, SLOT(cellClicked(QModelIndex)));
155 // Enable wordwrap when data changes
156 if (settings.value("/taskeditor/wordWrap", true)
157 .toBool()) // FIXME-3 not working or only sometimes?
159 connect(taskModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), view,
160 SLOT(resizeRowsToContents()));
161 connect(view->horizontalHeader(), SIGNAL(sectionResized(int, int, int)),
162 view, SLOT(resizeRowsToContents()));
165 // Initialize view filters according to previous settings
174 // Initialize display of parents of a task
176 int i = settings.value("/taskeditor/showParentsLevel", 0).toInt(&ok);
178 taskModel->setShowParentsLevel(i);
180 view->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
181 connect(view->horizontalHeader(),
182 SIGNAL(customContextMenuRequested(QPoint)),
183 SLOT(headerContextMenu()));
185 view->setStyleSheet("QTableView:focus {" + editorFocusStyle + "}");
187 updateColumnLayout();
190 TaskEditor::~TaskEditor()
192 settings.setValue("/taskeditor/filterMap",
193 actionToggleFilterMap->isChecked());
194 settings.setValue("/taskeditor/filterActive",
195 actionToggleFilterActive->isChecked());
196 settings.setValue("/taskeditor/filterNew",
197 actionToggleFilterNew->isChecked());
198 settings.setValue("/taskeditor/filterBlocker",
199 actionToggleFilterBlocker->isChecked());
200 settings.setValue("/taskeditor/filterFlags1",
201 actionToggleFilterFlags1->isChecked());
202 settings.setValue("/taskeditor/filterFlags2",
203 actionToggleFilterFlags2->isChecked());
204 settings.setValue("/taskeditor/filterFlags3",
205 actionToggleFilterFlags3->isChecked());
206 settings.setValue("/taskeditor/showParentsLevel",
207 taskModel->getShowParentsLevel());
209 for (int i = 0; i <= 8; i++) {
210 settings.setValue(QString("/taskeditor/column/%1/width").arg(i),
211 view->columnWidth(i));
212 settings.setValue(QString("/taskeditor/column/%1/hidden").arg(i),
213 view->isColumnHidden(i));
217 void TaskEditor::setMapName(const QString &n)
224 bool TaskEditor::isUsedFilterMap()
226 return actionToggleFilterMap->isChecked();
229 void TaskEditor::setFilterMap()
231 if (isUsedFilterMap())
232 filterActiveModel->setMapFilter(currentMapName);
234 filterActiveModel->setMapFilter(QString());
238 bool TaskEditor::isUsedFilterActive()
240 return actionToggleFilterActive->isChecked();
243 void TaskEditor::setFilterActive()
245 filterActiveModel->setFilter(actionToggleFilterActive->isChecked());
249 void TaskEditor::setFilterNew()
251 filterActiveModel->setFilterNew(actionToggleFilterNew->isChecked());
255 void TaskEditor::setFilterBlocker()
257 filterActiveModel->setFilterBlocker(actionToggleFilterBlocker->isChecked());
261 void TaskEditor::setFilterFlags1()
263 filterActiveModel->setFilterFlags1(actionToggleFilterFlags1->isChecked());
267 void TaskEditor::setFilterFlags2()
269 filterActiveModel->setFilterFlags2(actionToggleFilterFlags2->isChecked());
273 void TaskEditor::setFilterFlags3()
275 filterActiveModel->setFilterFlags3(actionToggleFilterFlags3->isChecked());
279 void TaskEditor::updateFilters()
281 // ugly, but calling twice updates rows as expected // FIXME-3 review...
282 filterActiveModel->invalidate();
283 filterActiveModel->invalidate();
286 bool TaskEditor::taskVisible(Task *task)
288 return filterActiveModel->taskVisible(task);
291 void TaskEditor::showSelection()
293 QModelIndexList list = view->selectionModel()->selectedIndexes();
294 if (list.count() > 0)
295 // Usually whole row is selected, so just go for first cell
296 view->scrollTo(taskModel->index(taskModel->getTask(list.first())),
297 QAbstractItemView::EnsureVisible);
300 bool TaskEditor::select(Task *task)
303 blockExternalSelect = true;
304 QModelIndex i0b = taskModel->index(task);
305 QModelIndex i0e = taskModel->indexRowEnd(task);
307 QModelIndex i1b = filterActiveModel->mapFromSource(i0b);
308 QModelIndex i1e = filterActiveModel->mapFromSource(i0e);
310 QItemSelection sel(i1b, i1e);
312 view->selectionModel()->select(sel,
313 QItemSelectionModel::ClearAndSelect);
314 blockExternalSelect = false;
320 void TaskEditor::clearSelection() { view->selectionModel()->clearSelection(); }
322 void TaskEditor::cellClicked(QModelIndex ix_unmapped)
324 QModelIndex ix = filterActiveModel->mapToSource(ix_unmapped);
325 if (ix.isValid() && ix.column() == 2)
326 taskModel->getTask(ix)->getBranch()->getModel()->cycleTaskStatus();
329 void TaskEditor::headerContextMenu()
331 // qDebug() << "TE::headerContextMenu()";
332 // Trying to workaround https://bugreports.qt.io/browse/QTBUG-52307
333 // view->horizontalHeader()->setStretchLastSection(true);
334 // view->resizeColumnsToContents();
339 void TaskEditor::updateColumnLayout()
341 // Update column widths and visibility
343 QString s = "/taskeditor/column/%1/";
347 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt());
348 view->setColumnHidden(i,
349 settings.value(s.arg(i) + "hidden", false).toBool());
353 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt());
354 view->setColumnHidden(i,
355 settings.value(s.arg(i) + "hidden", false).toBool());
359 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt());
360 view->setColumnHidden(i,
361 settings.value(s.arg(i) + "hidden", false).toBool());
365 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt());
366 view->setColumnHidden(i,
367 settings.value(s.arg(i) + "hidden", true).toBool());
371 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 50).toInt());
372 view->setColumnHidden(i,
373 settings.value(s.arg(i) + "hidden", true).toBool());
377 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt());
378 view->setColumnHidden(i,
379 settings.value(s.arg(i) + "hidden", true).toBool());
383 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 100).toInt());
384 view->setColumnHidden(i,
385 settings.value(s.arg(i) + "hidden", true).toBool());
389 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt());
390 view->setColumnHidden(i,
391 settings.value(s.arg(i) + "hidden", false).toBool());
395 view->setColumnWidth(i, settings.value(s.arg(i) + "width", 80).toInt());
396 view->setColumnHidden(i,
397 settings.value(s.arg(i) + "hidden", false).toBool());
400 void TaskEditor::selectionChanged(const QItemSelection &selected,
401 const QItemSelection &)
403 // FIXME-3 what, if multiple selection in MapEditor?
405 if (selected.indexes().isEmpty())
406 // Avoid segfault on quit, when selected is empty
409 QItemSelection sel0 = filterActiveModel->mapSelectionToSource(selected);
410 QModelIndex ix = sel0.indexes().first();
411 Task *t = taskModel->getTask(ix);
413 BranchItem *bi = t->getBranch();
415 VymModel *m = bi->getModel();
416 if (!blockExternalSelect)
418 if (m != mainWindow->currentModel())
419 mainWindow->gotoModel(m);
421 "QTableView {selection-background-color: " +
422 m->getSelectionBrushColor().name() +
423 "; selection-color:" + bi->getHeadingColor().name() + "}" +
424 "QTableView:focus {" + editorFocusStyle + "}");
425 view->scrollTo(selected.indexes().first());
430 void TaskEditor::contextMenuEvent(QContextMenuEvent *e)
432 taskContextMenu->popup(e->globalPos());
435 void TaskEditor::toggleFilterMap() { setFilterMap(); }
437 void TaskEditor::toggleFilterActive() { setFilterActive(); }
438 void TaskEditor::toggleFilterNew() { setFilterNew(); }
439 void TaskEditor::toggleFilterBlocker() { setFilterBlocker(); }
441 void TaskEditor::toggleFilterFlags1() { setFilterFlags1(); }
442 void TaskEditor::toggleFilterFlags2() { setFilterFlags2(); }
443 void TaskEditor::toggleFilterFlags3() { setFilterFlags3(); }