|
@@ -21,8 +21,11 @@
|
|
|
// Qt includes
|
|
|
#include <QAction>
|
|
|
#include <QDebug>
|
|
|
+#include <QPainter>
|
|
|
+#include <QSortFilterProxyModel>
|
|
|
#include <QStandardItem>
|
|
|
#include <QStandardItemModel>
|
|
|
+#include <QTextDocument>
|
|
|
#include <QTreeView>
|
|
|
#include <QVBoxLayout>
|
|
|
|
|
@@ -37,16 +40,17 @@ public:
|
|
|
void setupUI();
|
|
|
void updateItems(QList<QStandardItem*>& items, QAction* action);
|
|
|
|
|
|
- QStandardItemModel* ActionsModel;
|
|
|
- QTreeView* ActionsTreeView;
|
|
|
- bool ShowActionsWithNoShortcut;
|
|
|
+ QStandardItemModel* ActionsModel;
|
|
|
+ ctkSortFilterActionsProxyModel* SortFilterActionsProxyModel;
|
|
|
+ QTreeView* ActionsTreeView;
|
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
ctkActionsWidgetPrivate::ctkActionsWidgetPrivate()
|
|
|
{
|
|
|
+ this->ActionsModel = 0;
|
|
|
+ this->SortFilterActionsProxyModel = 0;
|
|
|
this->ActionsTreeView = 0;
|
|
|
- this->ShowActionsWithNoShortcut = false;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -60,12 +64,16 @@ void ctkActionsWidgetPrivate::setupUI()
|
|
|
headers << "Action" << "Shortcut" << "Context" << "Details";
|
|
|
this->ActionsModel->setHorizontalHeaderLabels(headers);
|
|
|
|
|
|
+ this->SortFilterActionsProxyModel = new ctkSortFilterActionsProxyModel(p);
|
|
|
+ this->SortFilterActionsProxyModel->setSourceModel(this->ActionsModel);
|
|
|
+
|
|
|
this->ActionsTreeView = new QTreeView(p);
|
|
|
QVBoxLayout* layout = new QVBoxLayout(p);
|
|
|
layout->addWidget(this->ActionsTreeView);
|
|
|
p->setLayout(layout);
|
|
|
- this->ActionsTreeView->setModel(this->ActionsModel);
|
|
|
+ this->ActionsTreeView->setModel(this->SortFilterActionsProxyModel);
|
|
|
this->ActionsTreeView->setAlternatingRowColors(true);
|
|
|
+ //this->ActionsTreeView->setItemDelegate(new ctkRichTextItemDelegate);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -74,10 +82,16 @@ void ctkActionsWidgetPrivate
|
|
|
{
|
|
|
Q_ASSERT(items.size() == 4);
|
|
|
// Name
|
|
|
- items[0]->setText(action->text());
|
|
|
- items[0]->setIcon(action->icon());
|
|
|
+ QString actionText = action->text();
|
|
|
+ if (actionText.indexOf('&') != -1)
|
|
|
+ {
|
|
|
+ actionText = actionText.remove(actionText.indexOf('&'),1); // remove mnemonic
|
|
|
+ }
|
|
|
+ items[ctkActionsWidget::NameColumn]->setText(actionText);
|
|
|
+ items[ctkActionsWidget::NameColumn]->setIcon(action->icon());
|
|
|
// Shortcut
|
|
|
- items[1]->setText(action->shortcut().toString(QKeySequence::NativeText));
|
|
|
+ items[ctkActionsWidget::ShortcutColumn]->setText(
|
|
|
+ action->shortcut().toString(QKeySequence::NativeText));
|
|
|
// Context
|
|
|
QString shortcutContext;
|
|
|
switch (action->shortcutContext())
|
|
@@ -91,8 +105,8 @@ void ctkActionsWidgetPrivate
|
|
|
default:
|
|
|
shortcutContext = "Application";
|
|
|
}
|
|
|
- items[2]->setText(shortcutContext);
|
|
|
- items[3]->setText(action->toolTip() != action->text()
|
|
|
+ items[ctkActionsWidget::ContextColumn]->setText(shortcutContext);
|
|
|
+ items[ctkActionsWidget::DetailsColumn]->setText(action->toolTip() != actionText
|
|
|
? action->toolTip() : QString(""));
|
|
|
}
|
|
|
|
|
@@ -125,9 +139,11 @@ void ctkActionsWidget::addAction(QAction* action, const QString& group)
|
|
|
actionGroupItem->appendRow(actionItems);
|
|
|
if (expandGroupItem)
|
|
|
{
|
|
|
+ qDebug() << d->ActionsModel->indexFromItem(actionGroupItem);
|
|
|
d->ActionsTreeView->expand(
|
|
|
- d->ActionsModel->indexFromItem(actionGroupItem));
|
|
|
+ d->SortFilterActionsProxyModel->mapFromSource(d->ActionsModel->indexFromItem(actionGroupItem)));
|
|
|
}
|
|
|
+ d->ActionsTreeView->resizeColumnToContents(0);
|
|
|
connect(action, SIGNAL(changed()), this, SLOT(updateAction()));
|
|
|
}
|
|
|
|
|
@@ -141,6 +157,13 @@ void ctkActionsWidget::addActions(QList<QAction*> actions, const QString& group)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
+void ctkActionsWidget::clear()
|
|
|
+{
|
|
|
+ CTK_D(ctkActionsWidget);
|
|
|
+ d->ActionsModel->clear();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
QStandardItem* ctkActionsWidget::groupItem(const QString& group)
|
|
|
{
|
|
|
CTK_D(ctkActionsWidget);
|
|
@@ -156,6 +179,7 @@ QStandardItem* ctkActionsWidget::groupItem(const QString& group)
|
|
|
return foundGroup[0];
|
|
|
}
|
|
|
QStandardItem* groupItem = new QStandardItem(group);
|
|
|
+ groupItem->setFlags(Qt::ItemIsEnabled);
|
|
|
d->ActionsModel->appendRow(groupItem);
|
|
|
return groupItem;
|
|
|
}
|
|
@@ -168,28 +192,59 @@ QStandardItemModel* ctkActionsWidget::model()const
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
+void ctkActionsWidget::setActionsWithNoShortcutVisible(bool show)
|
|
|
+{
|
|
|
+ CTK_D(ctkActionsWidget);
|
|
|
+ d->SortFilterActionsProxyModel->setActionsWithNoShortcutVisible(show);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+bool ctkActionsWidget::areActionsWithNoShortcutVisible()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkActionsWidget);
|
|
|
+ return d->SortFilterActionsProxyModel->areActionsWithNoShortcutVisible();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkActionsWidget::setMenuActionsVisible(bool show)
|
|
|
+{
|
|
|
+ CTK_D(ctkActionsWidget);
|
|
|
+ d->SortFilterActionsProxyModel->setMenuActionsVisible(show);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+bool ctkActionsWidget::areMenuActionsVisible()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkActionsWidget);
|
|
|
+ return d->SortFilterActionsProxyModel->areMenuActionsVisible();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
void ctkActionsWidget::updateAction()
|
|
|
{
|
|
|
CTK_D(ctkActionsWidget);
|
|
|
QAction* action = qobject_cast<QAction*>(this->sender());
|
|
|
Q_ASSERT(action);
|
|
|
- QModelIndexList foundAction =
|
|
|
+ QModelIndexList foundActions =
|
|
|
d->ActionsModel->match(d->ActionsModel->index(0,0),
|
|
|
Qt::UserRole + 1, qVariantFromValue(qobject_cast<QObject*>(action)),
|
|
|
- 1, Qt::MatchExactly | Qt::MatchRecursive);
|
|
|
- Q_ASSERT(foundAction.size());
|
|
|
- QModelIndex parentIndex = foundAction[0].parent();
|
|
|
- QStandardItem* parent = parentIndex.isValid()
|
|
|
- ? d->ActionsModel->itemFromIndex(parentIndex)
|
|
|
- : d->ActionsModel->invisibleRootItem();
|
|
|
- int actionRow = foundAction[0].row();
|
|
|
- Q_ASSERT(actionRow >= 0);
|
|
|
- QList<QStandardItem*> actionItems;
|
|
|
- for(int i = 0; i < 4; ++i)
|
|
|
+ -1, Qt::MatchExactly | Qt::MatchRecursive);
|
|
|
+ Q_ASSERT(foundActions.size());
|
|
|
+ foreach (QModelIndex actionIndex, foundActions)
|
|
|
{
|
|
|
- actionItems << parent->child(actionRow, i);
|
|
|
+ QModelIndex parentIndex = actionIndex.parent();
|
|
|
+ QStandardItem* parent = parentIndex.isValid()
|
|
|
+ ? d->ActionsModel->itemFromIndex(parentIndex)
|
|
|
+ : d->ActionsModel->invisibleRootItem();
|
|
|
+ int actionRow = actionIndex.row();
|
|
|
+ Q_ASSERT(actionRow >= 0);
|
|
|
+ QList<QStandardItem*> actionItems;
|
|
|
+ for(int i = 0; i < 4; ++i)
|
|
|
+ {
|
|
|
+ actionItems << parent->child(actionRow, i);
|
|
|
+ }
|
|
|
+ d->updateItems(actionItems, action);
|
|
|
}
|
|
|
- d->updateItems(actionItems, action);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -198,3 +253,134 @@ QTreeView* ctkActionsWidget::view()const
|
|
|
CTK_D(const ctkActionsWidget);
|
|
|
return d->ActionsTreeView;
|
|
|
}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+class ctkSortFilterActionsProxyModelPrivate: public ctkPrivate<ctkSortFilterActionsProxyModel>
|
|
|
+{
|
|
|
+public:
|
|
|
+ ctkSortFilterActionsProxyModelPrivate();
|
|
|
+ bool ActionsWithNoShortcutVisible;
|
|
|
+ bool MenuActionsVisible;
|
|
|
+};
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ctkSortFilterActionsProxyModelPrivate::ctkSortFilterActionsProxyModelPrivate()
|
|
|
+{
|
|
|
+ this->ActionsWithNoShortcutVisible = true;
|
|
|
+ this->MenuActionsVisible = true;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ctkSortFilterActionsProxyModel::ctkSortFilterActionsProxyModel(QObject* parentObject)
|
|
|
+ :QSortFilterProxyModel(parentObject)
|
|
|
+{
|
|
|
+ CTK_INIT_PRIVATE(ctkSortFilterActionsProxyModel);
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkSortFilterActionsProxyModel::setActionsWithNoShortcutVisible(bool visible)
|
|
|
+{
|
|
|
+ CTK_D(ctkSortFilterActionsProxyModel);
|
|
|
+ d->ActionsWithNoShortcutVisible = visible;
|
|
|
+ this->invalidateFilter();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+bool ctkSortFilterActionsProxyModel::areActionsWithNoShortcutVisible()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkSortFilterActionsProxyModel);
|
|
|
+ return d->ActionsWithNoShortcutVisible;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void ctkSortFilterActionsProxyModel::setMenuActionsVisible(bool visible)
|
|
|
+{
|
|
|
+ CTK_D(ctkSortFilterActionsProxyModel);
|
|
|
+ d->MenuActionsVisible = visible;
|
|
|
+ this->invalidateFilter();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+bool ctkSortFilterActionsProxyModel::areMenuActionsVisible()const
|
|
|
+{
|
|
|
+ CTK_D(const ctkSortFilterActionsProxyModel);
|
|
|
+ return d->MenuActionsVisible;
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+bool ctkSortFilterActionsProxyModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
|
|
|
+{
|
|
|
+ CTK_D(const ctkSortFilterActionsProxyModel);
|
|
|
+ QStandardItem* shortcutItem = qobject_cast<QStandardItemModel*>(
|
|
|
+ this->sourceModel())->itemFromIndex(
|
|
|
+ source_parent.child(source_row, ctkActionsWidget::ShortcutColumn));
|
|
|
+ QAction* action = shortcutItem ?
|
|
|
+ qobject_cast<QAction*>(shortcutItem->data().value<QObject*>()) : 0;
|
|
|
+ if (!action)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (action->isSeparator())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (action->text().isEmpty())
|
|
|
+ {// not sure what the empty text actions are
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!d->ActionsWithNoShortcutVisible && shortcutItem->text().isEmpty())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!d->MenuActionsVisible && action->menu())
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+//---------------------------------------------------------------------------
|
|
|
+void ctkRichTextItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option,
|
|
|
+ const QModelIndex &index) const
|
|
|
+{
|
|
|
+ QStyleOptionViewItemV4 options = option;
|
|
|
+ initStyleOption(&options, index);
|
|
|
+ if (! Qt::mightBeRichText(options.text))
|
|
|
+ {
|
|
|
+ this->QStyledItemDelegate::paint(painter, option, index);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ painter->save();
|
|
|
+
|
|
|
+ QTextDocument doc;
|
|
|
+ doc.setHtml(options.text);
|
|
|
+
|
|
|
+ /* Call this to get the focus rect and selection background. */
|
|
|
+ options.text = "";
|
|
|
+ options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);
|
|
|
+
|
|
|
+ /* Draw using our rich text document. */
|
|
|
+ painter->translate(options.rect.left(), options.rect.top());
|
|
|
+ QRect clip(0, 0, options.rect.width(), options.rect.height());
|
|
|
+ doc.drawContents(painter, clip);
|
|
|
+
|
|
|
+ painter->restore();
|
|
|
+}
|
|
|
+
|
|
|
+//---------------------------------------------------------------------------
|
|
|
+QSize ctkRichTextItemDelegate::sizeHint(const QStyleOptionViewItem & option,
|
|
|
+ const QModelIndex & index)const
|
|
|
+{
|
|
|
+ QStyleOptionViewItemV4 options = option;
|
|
|
+ initStyleOption(&options, index);
|
|
|
+ if (! Qt::mightBeRichText(options.text))
|
|
|
+ {
|
|
|
+ return this->QStyledItemDelegate::sizeHint(option, index);;
|
|
|
+ }
|
|
|
+
|
|
|
+ QTextDocument doc;
|
|
|
+ doc.setHtml(options.text);
|
|
|
+ doc.setTextWidth(options.rect.width());
|
|
|
+ return QSize(doc.idealWidth(), doc.size().height());
|
|
|
+}
|