+}
+
+
+bool BufferViewDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
+{
+ if (event->type() != QEvent::MouseButtonRelease)
+ return QStyledItemDelegate::editorEvent(event, model, option, index);
+
+ if (!(model->flags(index) & Qt::ItemIsUserCheckable))
+ return QStyledItemDelegate::editorEvent(event, model, option, index);
+
+ QVariant value = index.data(Qt::CheckStateRole);
+ if (!value.isValid())
+ return QStyledItemDelegate::editorEvent(event, model, option, index);
+
+#if QT_VERSION < 0x050000
+ QStyleOptionViewItemV4 viewOpt(option);
+#else
+ QStyleOptionViewItem viewOpt(option);
+#endif
+ initStyleOption(&viewOpt, index);
+
+ QRect checkRect = viewOpt.widget->style()->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, viewOpt.widget);
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+
+ if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
+ return QStyledItemDelegate::editorEvent(event, model, option, index);
+
+ Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
+ if (state == Qt::Unchecked)
+ state = Qt::PartiallyChecked;
+ else if (state == Qt::PartiallyChecked)
+ state = Qt::Checked;
+ else
+ state = Qt::Unchecked;
+ model->setData(index, state, Qt::CheckStateRole);
+ return true;
+}
+
+
+// ==============================
+// BufferView Dock
+// ==============================
+BufferViewDock::BufferViewDock(BufferViewConfig *config, QWidget *parent)
+ : QDockWidget(parent),
+ _childWidget(0),
+ _widget(new QWidget(parent)),
+ _filterEdit(new QLineEdit(parent)),
+ _active(false),
+ _title(config->bufferViewName())
+{
+ setObjectName("BufferViewDock-" + QString::number(config->bufferViewId()));
+ toggleViewAction()->setData(config->bufferViewId());
+ setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea);
+ connect(config, SIGNAL(bufferViewNameSet(const QString &)), this, SLOT(bufferViewRenamed(const QString &)));
+ connect(config, SIGNAL(configChanged()), SLOT(configChanged()));
+ updateTitle();
+
+ _widget->setLayout(new QVBoxLayout);
+ _widget->layout()->setSpacing(0);
+ _widget->layout()->setContentsMargins(0, 0, 0, 0);
+
+ // We need to potentially hide it early, so it doesn't flicker
+ _filterEdit->setVisible(config->showSearch());
+ _filterEdit->setFocusPolicy(Qt::ClickFocus);
+ _filterEdit->installEventFilter(this);
+ _filterEdit->setPlaceholderText(tr("Search..."));
+ connect(_filterEdit, SIGNAL(returnPressed()), SLOT(onFilterReturnPressed()));
+
+ _widget->layout()->addWidget(_filterEdit);
+ QDockWidget::setWidget(_widget);
+}
+
+void BufferViewDock::setLocked(bool locked) {
+ if (locked) {
+ setFeatures(0);
+ }
+ else {
+ setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
+ }
+}
+
+void BufferViewDock::updateTitle()
+{
+ QString title = _title;
+ if (isActive())
+ title.prepend(QString::fromUtf8("• "));
+ setWindowTitle(title);
+}
+
+void BufferViewDock::configChanged()
+{
+ if (_filterEdit->isVisible() != config()->showSearch()) {
+ _filterEdit->setVisible(config()->showSearch());
+ _filterEdit->clear();
+ }
+}
+
+void BufferViewDock::onFilterReturnPressed()
+{
+ if (_oldFocusItem) {
+ _oldFocusItem->setFocus();
+ _oldFocusItem = 0;
+ }
+
+ if (!config()->showSearch()) {
+ _filterEdit->setVisible(false);
+ }
+
+ BufferView *view = bufferView();
+ if (!view) {
+ return;
+ }
+
+ if (!_filterEdit->text().isEmpty()) {
+ view->selectHighlighted();
+ _filterEdit->clear();
+ } else {
+ view->clearHighlight();
+ }
+}
+
+void BufferViewDock::setActive(bool active)
+{
+ if (active != isActive()) {
+ _active = active;
+ updateTitle();
+ if (active) {
+ raise(); // for tabbed docks
+ }
+ }
+}
+
+bool BufferViewDock::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != _filterEdit) {
+ return false;
+ }
+
+ if (event->type() == QEvent::FocusOut) {
+ if (!config()->showSearch() && _filterEdit->text().isEmpty()) {
+ _filterEdit->setVisible(false);
+ return true;
+ }
+ } else if (event->type() == QEvent::KeyRelease) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+
+ BufferView *view = bufferView();
+ if (!view) {
+ return false;
+ }
+
+ switch (keyEvent->key()) {
+ case Qt::Key_Escape: {
+ _filterEdit->clear();
+
+ if (!_oldFocusItem) {
+ return false;
+ }
+
+ _oldFocusItem->setFocus();
+ _oldFocusItem = nullptr;
+ return true;
+ }
+ case Qt::Key_Down:
+ view->changeHighlight(BufferView::Backward);
+ return true;
+ case Qt::Key_Up:
+ view->changeHighlight(BufferView::Forward);
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+void BufferViewDock::bufferViewRenamed(const QString &newName)
+{
+ _title = newName;
+ updateTitle();
+ toggleViewAction()->setText(newName);
+}
+
+
+int BufferViewDock::bufferViewId() const
+{
+ BufferView *view = bufferView();
+ if (!view)
+ return 0;
+
+ if (view->config())
+ return view->config()->bufferViewId();
+ else
+ return 0;
+}
+
+
+BufferViewConfig *BufferViewDock::config() const
+{
+ BufferView *view = bufferView();
+ if (!view)
+ return 0;
+ else
+ return view->config();
+}
+
+void BufferViewDock::setWidget(QWidget *newWidget)
+{
+ _widget->layout()->addWidget(newWidget);
+ _childWidget = newWidget;
+
+ connect(_filterEdit, SIGNAL(textChanged(QString)), bufferView(), SLOT(filterTextChanged(QString)));
+}
+
+void BufferViewDock::activateFilter()
+{
+ if (!_filterEdit->isVisible()) {
+ _filterEdit->setVisible(true);
+ }
+
+ _oldFocusItem = qApp->focusWidget();
+
+ _filterEdit->setFocus();
+}
+
+
+void BufferViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItem newOption = option;
+ if (index == currentHighlight) {
+ newOption.state |= QStyle::State_HasFocus;
+ }
+ QStyledItemDelegate::paint(painter, newOption, index);