Ejemplo n.º 1
0
// ---------------------------- events ---------------------
void ModelViewReadOnly::mouseMoveEvent(QMouseEvent *event)
{
	QModelIndex dragged = indexAt(event->pos());
	if(!dragged.isValid())
	{
		qDebug("ModelViewReadOnly: invalid index..");
		QTreeView::mouseMoveEvent(event);
		return;
	}

	// we implement our own drag shit here
	if( DragUtility::confirmDrag(event) )
	{
		qDebug("ModelViewReadOnly: mouse move event!");
		ModelTree *  mtd=modelTree();

		Q_ASSERT(mtd);

		// single selection only. so we care only for on index and delegate to model!
		QMimeData * mimedata = mtd->mimeData( QModelIndexList() << dragged );
		DragUtility::executeDrag(this, mimedata, Qt::CopyAction);
		event->accept();
	}

}
Ejemplo n.º 2
0
QModelIndexList XSqlTableModelProto::match(const QModelIndex &start, int role, const QVariant &value, int hits, int flags) const
{
  XSqlTableModel *item = qscriptvalue_cast<XSqlTableModel*>(thisObject());
  if (item)
    return item->match(start, role, value, hits, (Qt::MatchFlags)flags);
  return QModelIndexList();
}
Ejemplo n.º 3
0
void AlbumCoverManager::AlbumDoubleClicked(const QModelIndex& index) {
  SongMimeData* data = GetMimeDataForAlbums(QModelIndexList() << index);
  if (data) {
    data->from_doubleclick_ = true;
    emit AddToPlaylist(data);
  }
}
Ejemplo n.º 4
0
// This returns all selected "cells", which means all cells of the same row are returned.
QModelIndexList FolderView::selectedIndexes() const {
  QItemSelectionModel* selModel = selectionModel();
  if(selModel) {
    return selModel->selectedIndexes();
  }
  return QModelIndexList();
}
Ejemplo n.º 5
0
QModelIndexList SimpleTreeView::selectedRows() const
{
	if(!selectionModel())
		return QModelIndexList();

	return selectionModel()->selectedRows();
}
Ejemplo n.º 6
0
void TreeView::startDrag(Qt::DropActions supportedActions)
{
	QModelIndex index = selectedIndexes().value(0);

	if (!index.isValid())
		return;

	QMimeData *data = model()->mimeData(QModelIndexList() << index);

	if (!data)
		return;
	QRect rect;
	QPixmap pixmap;
	QPoint point;
	{
		QAbstractItemDelegate *delegate = itemDelegate(index);
		QStyleOptionViewItemV4 option = viewOptions();
		option.locale = this->locale();
		option.locale.setNumberOptions(QLocale::OmitGroupSeparator);
		option.widget = this;
		option.state |= QStyle::State_Selected;
		option.rect = visualRect(index);
		point = option.rect.topLeft();
		option.rect.moveTo(0, 0);
		option.rect.setSize(delegate->sizeHint(option, index));
		rect = option.rect;
		pixmap = QPixmap(rect.size());
		pixmap.fill(Qt::transparent);
		QPainter painter(&pixmap);
		delegate->paint(&painter, option, index);
	}
	QDrag *drag = new QDrag(this);
	drag->setPixmap(pixmap);
	drag->setMimeData(data);
	point = QCursor::pos() - viewport()->mapToGlobal(point);
	drag->setHotSpot(point);
	//			drag->setHotSpot(QCursor::pos() - rect.topLeft());
	Qt::DropAction setDefaultDropAction = QAbstractItemView::defaultDropAction();
	Qt::DropAction defaultDropAction = Qt::IgnoreAction;
	if (setDefaultDropAction != Qt::IgnoreAction && (supportedActions & setDefaultDropAction))
		defaultDropAction = setDefaultDropAction;
	else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
		defaultDropAction = Qt::CopyAction;
	if (drag->exec(supportedActions, defaultDropAction) == Qt::IgnoreAction
			&& index.data(ItemTypeRole).toInt() == ContactType) {
		if (QWidget *widget = QApplication::topLevelAt(QCursor::pos())) {
			if (widget->window() == this->window())
				return;
		}
		Event ev("contact-list-drop",
				 QCursor::pos() - point,
				 index.data(BuddyRole));
		ev.send();
	}
	//			debug() << "DropAction" << drag->exec(supportedActions, defaultDropAction);
	//			if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
	//				d->clearOrRemove();
	//			{}
}
Ejemplo n.º 7
0
void DynamicPage::controlActions()
{
    QModelIndexList selected=qobject_cast<Dynamic *>(sender()) ? QModelIndexList() : view->selectedIndexes(false); // Dont need sorted selection here...

    editAction->setEnabled(1==selected.count());
    Dynamic::self()->startAct()->setEnabled(1==selected.count());
    removeAction->setEnabled(selected.count());
}
Ejemplo n.º 8
0
QModelIndexList ListView::selectedIndexes(bool sorted) const
{
    QModelIndexList indexes=selectionModel() ? selectionModel()->selectedIndexes() : QModelIndexList();
    if (sorted) {
        qSort(indexes);
    }
    return indexes;
}
Ejemplo n.º 9
0
void MessageView::deleteLabelAction(const QString &tag)
{
    if (!message.isValid())
        return;

    Imap::Mailbox::Model *model = dynamic_cast<Imap::Mailbox::Model *>(const_cast<QAbstractItemModel *>(message.model()));
    model->setMessageFlags(QModelIndexList() << message, tag, Imap::Mailbox::FLAG_REMOVE);
}
Ejemplo n.º 10
0
    /**
     * @brief ComponentsModel::addExists
     * @param inserter
     * @param count
     * @param pos
     */
    void ComponentsModel::addExists(const std::function<void (int)> &inserter, int count, int pos)
    {
        int innerIndex = pos == -1 ? count : pos;
        beginInsertRows(QModelIndex(), innerIndex, innerIndex);
        inserter(innerIndex);
        endInsertRows();

        showButtons(QModelIndexList() << index(innerIndex, 1));
    }
Ejemplo n.º 11
0
QModelIndexList CellModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
{
    Q_UNUSED(start);
    Q_UNUSED(role);
    Q_UNUSED(value);
    Q_UNUSED(hits);
    Q_UNUSED(flags);
    return QModelIndexList();
}
Ejemplo n.º 12
0
void GroupListView::DeleteItem()
{
    ProgramsModel *progModel = qobject_cast<ProgramsModel*>(model());
    if(!progModel)
        return;

    if(!selectedIndexes().isEmpty())
        progModel->UserRemoveRows(selectedIndexes(),rootIndex());
    else if(currentIndex().isValid())
        progModel->UserRemoveRows(QModelIndexList()<<currentIndex(),rootIndex());
}
Ejemplo n.º 13
0
void FavoritePlacesModel::moveRow(int from, int to)
{
    // Simulate a move by drag'n'drop because moving the row this way
    // is the only way to get rowsMoved() signals instead of remove+insert
    QMimeData *data = mimeData(QModelIndexList() << index(from, 0));
    Q_ASSERT(data);
    if (from < to) {
        ++to;
    }
    dropMimeData(data, Qt::MoveAction, to, 0, QModelIndex());
}
Ejemplo n.º 14
0
void MessageView::markAsRead()
{
    if (!message.isValid())
        return;
    Imap::Mailbox::Model *model = const_cast<Imap::Mailbox::Model *>(dynamic_cast<const Imap::Mailbox::Model *>(message.model()));
    Q_ASSERT(model);
    if (!model->isNetworkAvailable())
        return;
    if (!message.data(Imap::Mailbox::RoleMessageIsMarkedRead).toBool())
        model->markMessagesRead(QModelIndexList() << message, Imap::Mailbox::FLAG_ADD);
}
void AutoExpandingTreeView::ItemDoubleClicked(const QModelIndex& index) {
  ignore_next_click_ = true;

  if (add_on_double_click_) {
    QMimeData* data = model()->mimeData(QModelIndexList() << index);
    if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
      mime_data->from_doubleclick_ = true;
    }
    emit AddToPlaylistSignal(data);
  }
}
Ejemplo n.º 16
0
void AppListView::startDrag(const QModelIndex &index)
{
    if (!index.isValid())
        return;

    AppsListModel *listModel = qobject_cast<AppsListModel *>(model());
    if (!listModel)
        return;

    const QModelIndex &dragIndex = index;
    const QString appKey = index.data(AppsListModel::AppKeyRole).toString();
    const QPixmap pixmap = index.data(AppsListModel::AppIconRole).value<QPixmap>();

    QDrag *drag = new QDrag(this);
    drag->setMimeData(model()->mimeData(QModelIndexList() << dragIndex));
    drag->setPixmap(pixmap.scaled(DLauncher::APP_DRAG_ICON_SIZE, DLauncher::APP_DRAG_ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    drag->setHotSpot(QPoint(DLauncher::APP_DRAG_ICON_SIZE, DLauncher::APP_DRAG_ICON_SIZE) / 2);

    // request remove current item.
    if (listModel->category() == AppsListModel::All)
    {
        m_dropToPos = index.row();
        listModel->setDragingIndex(index);
    }

    drag->exec(Qt::MoveAction);

    // disable animation when finally dropped
    m_dropThresholdTimer->stop();

    // disable auto scroll
    emit requestScrollStop();

    if (listModel->category() != AppsListModel::All)
        return;

    if (!m_lastFakeAni)
    {
        if (m_enableDropInside)
            listModel->dropSwap(m_dropToPos);
        else
            listModel->dropSwap(indexAt(m_dragStartPos).row());

        listModel->clearDragingIndex();
    }
    else
    {
        connect(m_lastFakeAni, &QPropertyAnimation::finished, listModel, &AppsListModel::clearDragingIndex);
    }

    m_enableDropInside = false;
}
Ejemplo n.º 17
0
void GroupListView::Copy()
{
    QMimeData *mime=0;

    if(!selectedIndexes().isEmpty())
        mime = model()->mimeData( selectedIndexes() );
    else if(currentIndex().isValid())
        mime = model()->mimeData( QModelIndexList() << currentIndex() );

    if(!mime)
        return;

    QApplication::clipboard()->setMimeData( mime );
}
Ejemplo n.º 18
0
QModelIndexList KNMusicModel::indexFromFilePath(const QString &filePath)
{
    //If the file path is empty, return a null index.
    if(filePath.isEmpty())
    {
        return QModelIndexList();
    }
    //Using match to find all pathes.
    return match(index(0, Name),
                 FilePathRole,
                 filePath,
                 1,
                 Qt::MatchFixedString);
}
Ejemplo n.º 19
0
/*!
    \reimp
 */
QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
{
    Q_D(const QIdentityProxyModel);
    Q_ASSERT(start.isValid() ? start.model() == this : true);
    if (!d->model)
        return QModelIndexList();

    const QModelIndexList sourceList = d->model->match(mapToSource(start), role, value, hits, flags);
    QModelIndexList::const_iterator it = sourceList.constBegin();
    const QModelIndexList::const_iterator end = sourceList.constEnd();
    QModelIndexList proxyList;
    for ( ; it != end; ++it)
        proxyList.append(mapFromSource(*it));
    return proxyList;
}
Ejemplo n.º 20
0
/** \fn EditMediaDialog::EditMediaDialog(QWidget *parent)
  * \brief class constructor
  * \param parent the inherited QWidget object
  */
EditMediaDialog::EditMediaDialog(QModelIndexList indexList, QDataWidgetMapper* mapper, QWidget *parent)
        : QDialog(parent)
        , ui_(new Ui::EditMediaDialog)
        , mapper_(mapper)
        , indexList_(QModelIndexList(indexList))
        , nMedia_(indexList_.count())
        , selectionPos_(indexList_.at(0).row())
        , originPos_(selectionPos_)
        , tagsSet_(new QStringList())
        , tagsUnset_(new QStringList())
        , statusBar_(new QStatusBar(this))
{
    Q_ASSERT(nMedia_>0);

    init();
    makeConnections();
}
Ejemplo n.º 21
0
Song LibraryPage::coverRequest() const
{
    QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...

    if (1==selected.count()) {
        QList<Song> songs=MpdLibraryModel::self()->songs(QModelIndexList() << selected.first(), false);
        if (!songs.isEmpty()) {
            Song s=songs.at(0);

            if (SqlLibraryModel::T_Artist==static_cast<SqlLibraryModel::Item *>(selected.first().internalPointer())->getType() && !s.useComposer()) {
                s.setArtistImageRequest();
            }
            return s;
        }
    }
    return Song();
}
Ejemplo n.º 22
0
void NickListWidget::currentChanged(const QModelIndex &current, const QModelIndex &previous) {
  BufferInfo::Type bufferType = (BufferInfo::Type)current.data(NetworkModel::BufferTypeRole).toInt();
  BufferId newBufferId = current.data(NetworkModel::BufferIdRole).value<BufferId>();
  BufferId oldBufferId = previous.data(NetworkModel::BufferIdRole).value<BufferId>();

  if(bufferType != BufferInfo::ChannelBuffer) {
    ui.stackedWidget->setCurrentWidget(ui.emptyPage);
    emit nickSelectionChanged(QModelIndexList());
    return;
  }

  // See NickListDock::NickListDock() below
//   if(bufferType != BufferInfo::ChannelBuffer) {
//     ui.stackedWidget->setCurrentWidget(ui.emptyPage);
//     QDockWidget *dock_ = dock();
//     if(dock_) {
//       dock_->close();
//     }
//     return;
//   } else {
//     QDockWidget *dock_ = dock();
//     if(dock_ && dock_->toggleViewAction()->isChecked()) {
//       dock_->show();
//     }
//   }

  if(newBufferId == oldBufferId)
    return;

  NickView *view;
  if(nickViews.contains(newBufferId)) {
    view = nickViews.value(newBufferId);
    ui.stackedWidget->setCurrentWidget(view);
  } else {
    view = new NickView(this);
    NickViewFilter *filter = new NickViewFilter(newBufferId, Client::networkModel());
    view->setModel(filter);
    QModelIndex source_current = Client::bufferModel()->mapToSource(current);
    view->setRootIndex(filter->mapFromSource(source_current));
    nickViews[newBufferId] = view;
    ui.stackedWidget->addWidget(view);
    ui.stackedWidget->setCurrentWidget(view);
    connect(view, SIGNAL(selectionUpdated()), SLOT(nickSelectionChanged()));
  }
  emit nickSelectionChanged(view->selectedIndexes());
}
Ejemplo n.º 23
0
const QModelIndexList LibraryModel::indexesForGroup(LibraryModel::GroupSelection group) const
{
    std::function<bool (const LibraryEntry*)> filter;
    switch((GroupSelection) group) {
    case AllTracks:
        filter = [](const LibraryEntry* entry) {
            return true;
        };
        break;
    case NewTracks:
        filter = [](const LibraryEntry* entry) {
            Library::FileStatus status = (Library::FileStatus) entry->record().value(Library::Status).toInt();
            return status.testFlag(Library::New);
        };
        break;
    case MissingTracks:
        filter = [](const LibraryEntry* entry) {
            Library::FileStatus status = (Library::FileStatus) entry->record().value(Library::Status).toInt();
            return status.testFlag(Library::FileNotFound);
        };
        break;
    case LinkedTracks:
        filter = [](const LibraryEntry* entry) {
            Library::FileStatus status = (Library::FileStatus) entry->record().value(Library::Status).toInt();
            bool hasLikedResult = !entry->record().value(Library::Bpid).isNull();
            return status.testFlag(Library::Searched) && hasLikedResult;
        };
        break;
    case SearchedAndNotLinkedTracks:
        filter = [](const LibraryEntry* entry) {
            Library::FileStatus status = (Library::FileStatus) entry->record().value(Library::Status).toInt();
            bool hasLikedResult = !entry->record().value(Library::Bpid).isNull();
            return status.testFlag(Library::Searched) && !hasLikedResult;
        };
        break;
    default:
        return QModelIndexList();
    }
    QModelIndexList indexesList;
    for(int i = 0 ; i < rowCount() ; ++i) {
        filteredIndexes(index(i, 0, QModelIndex()), filter, indexesList);
    }

    return indexesList;
}
Ejemplo n.º 24
0
Song LibraryPage::coverRequest() const
{
    QModelIndexList selected = view->selectedIndexes(false); // Dont need sorted selection here...

    if (1==selected.count()) {
        QModelIndex idx=proxy.mapToSource(selected.at(0));
        QList<Song> songs=MusicLibraryModel::self()->songs(QModelIndexList() << idx, false);
        if (!songs.isEmpty()) {
            Song s=songs.at(0);

            if (MusicLibraryItem::Type_Artist==static_cast<MusicLibraryItem *>(idx.internalPointer())->itemType() &&
                !static_cast<MusicLibraryItemArtist *>(idx.internalPointer())->isComposer()) {
                s.setArtistImageRequest();
            }
            return s;
        }
    }
    return Song();
}
Ejemplo n.º 25
0
QModelIndexList ModelChain::indexListForValue(const QVariant &value) const
{
    if (!Model || !KaduModel)
        return QModelIndexList();

    QModelIndexList indexes = KaduModel->indexListForValue(value);
    QModelIndexList result;

    const int size = indexes.size();
    result.reserve(size);

    for (int i = 0; i < size; i++)
    {
        QModelIndex index = indexes.at(i);
        for (auto proxyModel : ProxyModels)
            index = proxyModel->mapFromSource(index);
        result.append(index);
    }

    return result;
}
Ejemplo n.º 26
0
void ContactListUtil::removeContact(PsiContact* contact, QMimeData* _selection, ContactListDragModel* model, QWidget* widget, QObject* obj)
{
	Q_ASSERT(model);
	QModelIndexList indexes = model ? model->indexesFor(contact, _selection) : QModelIndexList();
	if (model && !indexes.isEmpty()) {
		QMimeData* selection = model->mimeData(indexes);
		QString selectionData = confirmationData(contact, _selection, model);

		// WARNING: selection could also contain groups. and when there are groups,
		// all groups' contacts are marked for deletion too
		QList<PsiContact*> contactsLost = model->contactsLostByRemove(selection);
		bool removeConfirmed = contactsLost.isEmpty();
		bool confirmWithoutPrompt = false;

		if (!removeConfirmed) {
			QStringList contactNames = contactNamesFor(contactsLost);

			QString destructiveActionName;
			QString msg;
			bool doPrompt = true;

			// don't prompt when removing single muc or not-in-list contacts
			if(contactsLost.count() == 1 && (contactsLost[0]->isPrivate() || !contactsLost[0]->inList())) {
				doPrompt = false;
			}

			if (!contactNames.isEmpty()) {
				msg = tr("This will permanently remove<br>"
						 "%1"
						 "<br>from your contact list."
                         ).arg(contactNames.join(", ").replace("\\40","@"));
			}

#ifdef YAPSI
			QString complimentaryActionName;
			const char* complimentaryActionSlot = 0;

			ContactListModelSelection contactListSelection(selection);
			if (contactNames.count() > 1 || contactListSelection.groups().count()) {
				QStringList tmp;
				QStringList tmpContactNames = contactNames;
				while (!tmpContactNames.isEmpty()) {
					if (tmp.count() >= 10)
						break;

					tmp << QString("%1. %2").arg(tmp.count() + 1).arg(tmpContactNames.takeFirst());
				}

				QString andNContacts;
				if (!tmpContactNames.isEmpty()) {
					andNContacts = tr("and %n contacts ", 0,
									  tmpContactNames.count());
				}

				if (contactListSelection.groups().count() > 1) {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2and %n groups from your contact list.",
							 0,
							 contactListSelection.groups().count()
							).arg(tmp.join("<br>"))
							 .arg(andNContacts);
				}
				else if (contactListSelection.groups().count() == 1) {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2and \"%3\" group from your contact list."
							).arg(tmp.join("<br>"))
							 .arg(andNContacts)
							 .arg(contactListSelection.groups().first().fullName);
				}
				else {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2from your contact list."
							).arg(tmp.join("<br>"))
							 .arg(andNContacts);
				}
			}

			if (indexes.count() == 1 && model->indexType(indexes.first()) == ContactListModel::GroupType) {
				if (YaContactListContactsModel::virtualUnremovableGroups().contains(contactListSelection.groups().first().fullName)) {
					msg = tr("This is a system group and can't be removed. "
							 "Permanently remove all its contacts from your contact list?");
					destructiveActionName = tr("Clear Group");
				}
				else {
					msg = tr("This will permanently remove<br>"
							 "%1"
							 "<br>group and all its contacts from your contact list.").arg(TextUtil::escape(indexes.first().data().toString()));
				}
			}
			else if (indexes.count() == 1 && model->indexType(indexes.first()) == ContactListModel::ContactType) {
				Q_ASSERT(contactListSelection.contacts().count() == 1);
				ContactListModelSelection::Contact c = contactListSelection.contacts().first();

				PsiAccount* account = contactList()->getAccount(c.account);
				PsiContact* psiContact = account ? account->findContact(c.jid) : 0;
				QStringList contactGroupsLostByRemove;
				if (psiContact) {
					contactGroupsLostByRemove = model->contactGroupsLostByRemove(psiContact, selection);
				}

				if (psiContact && !psiContact->inList() && psiContact->blockAvailable()) {
					msg = tr("This will permanently remove %1 from your contact list. "
							 "You could block it in order to avoid further messages.")
                            .arg(contactNames.join(", ").replace("\\40","@"));
					destructiveActionName = tr("Delete");
					complimentaryActionName = tr("Block");
					complimentaryActionSlot = "blockContactConfirmation";
				}
				else if (psiContact && psiContact->groups().count() > 1 && contactGroupsLostByRemove.count() == 1) {
					// TODO: needs to be translated
					msg = tr("This will remove %1 from \"%2\" group. "
							 "You could also remove it from all groups.")
						  .arg(contactNames.join(", "))
						  .arg(contactGroupsLostByRemove.first());
					destructiveActionName = tr("Delete");
					complimentaryActionName = tr("Delete From All Groups");
					// TODO: needs to be implemented
					complimentaryActionSlot = "removeContactFullyConfirmation";
				}
			}
#endif

			if (!msg.isEmpty()) {
				if (doPrompt) {
#ifdef YAPSI
					if (complimentaryActionSlot) {
						RemoveConfirmationMessageBoxManager::instance()->
							removeConfirmation(selectionData,
											   obj, "removeContactConfirmation",
											   obj, complimentaryActionSlot,
											   tr("Deleting contacts"),
											   msg,
											   widget,
											   destructiveActionName,
											   complimentaryActionName);
					}
#else
					if (false) {
					}
#endif
					else {
						RemoveConfirmationMessageBoxManager::instance()->
							removeConfirmation(selectionData,
											   obj, "removeContactConfirmation",
											   tr("Deleting contacts"),
											   msg,
											   widget,
											   destructiveActionName);
					}

					removeConfirmed = false;
				}
				else {
					confirmWithoutPrompt = true;
				}
			}
		}

		QMetaObject::invokeMethod(obj, "removeContactConfirmation", Qt::DirectConnection,
								  QGenericReturnArgument(),
								  Q_ARG(QString, selectionData), Q_ARG(bool, removeConfirmed));

		if(confirmWithoutPrompt) {
			QMetaObject::invokeMethod(obj, "removeContactConfirmation", Qt::QueuedConnection,
								  QGenericReturnArgument(),
								  Q_ARG(QString, selectionData), Q_ARG(bool, true));
		}

		delete selection;
	}
Ejemplo n.º 27
0
void RawModel::updateOperators() {
    updateOperators(QModelIndexList());
}
Ejemplo n.º 28
0
void ImapAccess::markMessageDeleted(const QModelIndex &message, bool marked)
{
    Q_ASSERT(message.isValid());
    m_imapModel->markMessagesDeleted(QModelIndexList() << message, marked ? Imap::Mailbox::FLAG_ADD : Imap::Mailbox::FLAG_REMOVE);
}
Ejemplo n.º 29
0
void FeedbackModel::removeFeedback( const QModelIndex& index )
{
	removeFeedbacks( QModelIndexList() << index );
}
Ejemplo n.º 30
0
void NickListWidget::hideEvent(QHideEvent *event) {
  emit nickSelectionChanged(QModelIndexList());
  AbstractItemView::hideEvent(event);
}