#include "taskeditor.h"
#include <QAbstractTableModel>
#include <QAction>
#include <QContextMenuEvent>
#include <QDebug>
#include <QHeaderView>
#include <QMenu>
#include <QSortFilterProxyModel>
#include <QTableView>
#include <QTextEdit>
#include <QToolBar>
#include <QVBoxLayout>
#include "branchitem.h"
#include "mainwindow.h"
#include "task.h"
#include "taskfiltermodel.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->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
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( // FIXME-5 this resets column widths on Windows...
"QTableView {selection-background-color: " +
m->getSelectionBrushColor().name() +
"; selection-color:" + bi->headingColor().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(); }