X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcontrib%2Flibqxt-2007-10-24%2Fsrc%2Fgui%2Fqxtcheckcombobox.cpp;fp=src%2Fcontrib%2Flibqxt-2007-10-24%2Fsrc%2Fgui%2Fqxtcheckcombobox.cpp;h=52b22e860035ea8378ea3d4b9bf3751b07d8acd5;hp=0000000000000000000000000000000000000000;hb=a634acadbcf6017474f68a3eaf7cb632660e9e49;hpb=cd122ca8e0d2c0ffc5397e0a813c75d791a7e6e3 diff --git a/src/contrib/libqxt-2007-10-24/src/gui/qxtcheckcombobox.cpp b/src/contrib/libqxt-2007-10-24/src/gui/qxtcheckcombobox.cpp new file mode 100644 index 00000000..52b22e86 --- /dev/null +++ b/src/contrib/libqxt-2007-10-24/src/gui/qxtcheckcombobox.cpp @@ -0,0 +1,380 @@ +/**************************************************************************** +** +** Copyright (C) Qxt Foundation. Some rights reserved. +** +** This file is part of the QxtGui module of the Qt eXTension library +** +** This library is free software; you can redistribute it and/or modify it +** under the terms of th Common Public License, version 1.0, as published by +** IBM. +** +** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY +** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY +** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR +** FITNESS FOR A PARTICULAR PURPOSE. +** +** You should have received a copy of the CPL along with this file. +** See the LICENSE file and the cpl1.0.txt file included with the source +** distribution for more information. If you did not receive a copy of the +** license, contact the Qxt Foundation. +** +** +** +****************************************************************************/ +#include "qxtcheckcombobox.h" +#include "qxtcheckcombobox_p.h" +#include +#include +#include +#include + +QxtCheckComboBoxPrivate::QxtCheckComboBoxPrivate() +{ + separator = QLatin1String(","); +} + +void QxtCheckComboBoxPrivate::hidePopup() +{ + qxt_p().hidePopup(); +} + +void QxtCheckComboBoxPrivate::updateCheckedItems() +{ + checkedItems.clear(); + for (int i = 0; i < qxt_p().model()->rowCount(); ++i) + { + const QModelIndex& index = qxt_p().model()->index(i, 0); + const QVariant& data = index.data(Qt::CheckStateRole); + const Qt::CheckState state = static_cast(data.toInt()); + if (state == Qt::Checked) + { + checkedItems += index.data().toString(); + } + } + + if (checkedItems.count() > 0) + qxt_p().lineEdit()->setText(checkedItems.join(separator)); + else + qxt_p().lineEdit()->setText(defaultText); + + // TODO: find a way to recalculate a meaningful size hint + + emit qxt_p().checkedItemsChanged(checkedItems); +} + +QxtCheckComboView::QxtCheckComboView(QWidget* parent) + : QListView(parent), mode(QxtCheckComboBox::CheckIndicator) +{} + +QxtCheckComboView::~QxtCheckComboView() +{} + +bool QxtCheckComboView::eventFilter(QObject* object, QEvent* event) +{ + Q_UNUSED(object); + if (event->type() == QEvent::MouseButtonRelease) + { + QMouseEvent* mouse = static_cast(event); + const QModelIndex& index = indexAt(mouse->pos()); + if (index.isValid()) + { + bool change = false; + switch (mode) + { + case QxtCheckComboBox::CheckIndicator: + change = handleIndicatorRelease(mouse, index); + break; + + case QxtCheckComboBox::CheckWholeItem: + change = handleItemRelease(mouse, index); + break; + + default: + qWarning("QxtCheckComboView::eventFilter(): unknown mode"); + break; + } + + if (change) + { + // the check state is about to change, bypass + // combobox and deliver the event just for the listview + QListView::mouseReleaseEvent(mouse); + } + else + { + // otherwise it's ok to close + emit hideRequested(); + } + return true; + } + } + return false; +} + +bool QxtCheckComboView::handleIndicatorRelease(QMouseEvent* event, const QModelIndex& index) +{ + // check if the mouse was released over the checkbox + QStyleOptionButton option; + option.QStyleOption::operator=(viewOptions()); + option.rect = visualRect(index); + const QRect& rect = style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option); + return rect.contains(event->pos()); +} + +bool QxtCheckComboView::handleItemRelease(QMouseEvent* event, const QModelIndex& index) +{ + // check if the mouse was released outside the checkbox + QStyleOptionButton option; + option.QStyleOption::operator=(viewOptions()); + option.rect = visualRect(index); + const QRect& rect = style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option); + if (!rect.contains(event->pos())) + { + Qt::CheckState state = (Qt::CheckState) index.data(Qt::CheckStateRole).toInt(); + switch (state) + { + case Qt::Unchecked: + state = Qt::Checked; + break; + + case Qt::Checked: + state = Qt::Unchecked; + break; + + default: + qWarning("QxtCheckComboView::handleItemRelease(): partially checked item"); + break; + } + model()->setData(index, state, Qt::CheckStateRole); + } + return true; +} + +QxtCheckComboModel::QxtCheckComboModel(QObject* parent) + : QStandardItemModel(0, 1, parent) // rows,cols +{ +} + +QxtCheckComboModel::~QxtCheckComboModel() +{} + +Qt::ItemFlags QxtCheckComboModel::flags(const QModelIndex& index) const +{ + return QStandardItemModel::flags(index) | Qt::ItemIsUserCheckable; +} + +QVariant QxtCheckComboModel::data(const QModelIndex& index, int role) const +{ + QVariant value = QStandardItemModel::data(index, role); + if (role == Qt::CheckStateRole && !value.isValid()) + value = Qt::Unchecked; + return value; +} + +bool QxtCheckComboModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + bool ok = QStandardItemModel::setData(index, value, role); + if (ok) + { + if (role == Qt::CheckStateRole) + { + emit checkStateChanged(); + } + } + return ok; +} + +/*! + \class QxtCheckComboBox QxtCheckComboBox + \ingroup QxtGui + \brief An extended QComboBox with checkable items. + + QxtComboBox is a specialized combo box with checkable items. + Checked items are collected together in the line edit. + + \image html qxtcheckcombobox.png "QxtCheckComboBox in Plastique style." + */ + +/*! + \enum QxtCheckComboBox::CheckMode + + This enum describes the check mode. + + \sa QxtCheckComboBox::checkMode + */ + +/*! + \var QxtCheckComboBox::CheckMode QxtCheckComboBox::CheckIndicator + + The check state changes only via the check indicator (like in item views). + */ + +/*! + \var QxtCheckComboBox::CheckMode QxtCheckComboBox::CheckWholeItem + + The check state changes via the whole item (like with a combo box). + */ + +/*! + \fn QxtCheckComboBox::checkedItemsChanged(const QStringList& items) + + This signal is emitted whenever the checked items have been changed. + */ + +/*! + Constructs a new QxtCheckComboBox with \a parent. + */ +QxtCheckComboBox::QxtCheckComboBox(QWidget* parent) : QComboBox(parent) +{ + QXT_INIT_PRIVATE(QxtCheckComboBox); + QxtCheckComboModel* model = new QxtCheckComboModel(this); + QxtCheckComboView* view = new QxtCheckComboView(this); + qxt_d().view = view; + setModel(model); + setView(view); + + // these 2 lines below are important and must be + // applied AFTER QComboBox::setView() because + // QComboBox installs its own filter on the view + view->installEventFilter(view); // <--- !!! + view->viewport()->installEventFilter(view); // <--- !!! + + // read-only contents + QLineEdit* lineEdit = new QLineEdit(this); + lineEdit->setReadOnly(true); + setLineEdit(lineEdit); + + connect(view, SIGNAL(hideRequested()), &qxt_d(), SLOT(hidePopup())); + connect(model, SIGNAL(checkStateChanged()), &qxt_d(), SLOT(updateCheckedItems())); + QTimer::singleShot(0, &qxt_d(), SLOT(updateCheckedItems())); +} + +/*! + Destructs the combo box. + */ +QxtCheckComboBox::~QxtCheckComboBox() +{} + +/*! + Returns the check state of the item at \a index. + */ +Qt::CheckState QxtCheckComboBox::itemCheckState(int index) const +{ + return static_cast(itemData(index, Qt::CheckStateRole).toInt()); +} + +/*! + Sets the check state of the item at \a index to \a state. + */ +void QxtCheckComboBox::setItemCheckState(int index, Qt::CheckState state) +{ + setItemData(index, state, Qt::CheckStateRole); +} + +/*! + \property QxtCheckComboBox::checkedItems + \brief This property holds the checked items. + */ +QStringList QxtCheckComboBox::checkedItems() const +{ + return qxt_d().checkedItems; +} + +void QxtCheckComboBox::setCheckedItems(const QStringList& items) +{ + // not the most efficient solution but most likely nobody + // will put too many items into a combo box anyway so... + foreach (const QString& text, items) + { + const int index = findText(text); + setItemCheckState(index, index != -1 ? Qt::Checked : Qt::Unchecked); + } +} + +/*! + \property QxtCheckComboBox::defaultText + \brief This property holds the default text. + + The default text is shown when there are no checked items. + The default value is an empty string. + */ +QString QxtCheckComboBox::defaultText() const +{ + return qxt_d().defaultText; +} + +void QxtCheckComboBox::setDefaultText(const QString& text) +{ + if (qxt_d().defaultText != text) + { + qxt_d().defaultText = text; + qxt_d().updateCheckedItems(); + } +} + +/*! + \property QxtCheckComboBox::separator + \brief This property holds the default separator. + + The checked items are joined together with the separator string. + The default value is a comma (","). + */ +QString QxtCheckComboBox::separator() const +{ + return qxt_d().separator; +} + +void QxtCheckComboBox::setSeparator(const QString& separator) +{ + if (qxt_d().separator != separator) + { + qxt_d().separator = separator; + qxt_d().updateCheckedItems(); + } +} + +/*! + \property QxtCheckComboBox::checkMode + \brief This property holds the check mode. + + The check mode describes item checking behaviour. + The default value is \b QxtCheckComboBox::CheckIndicator. + + \sa QxtCheckComboBox::CheckMode + */ +QxtCheckComboBox::CheckMode QxtCheckComboBox::checkMode() const +{ + return qxt_d().view->mode; +} + +void QxtCheckComboBox::setCheckMode(QxtCheckComboBox::CheckMode mode) +{ + if (qxt_d().view->mode != mode) + { + qxt_d().view->mode = mode; + } +} + +void QxtCheckComboBox::keyPressEvent(QKeyEvent* event) +{ + if (event->key() != Qt::Key_Up && event->key() != Qt::Key_Down) + { + QComboBox::keyPressEvent(event); + } + else + { + showPopup(); + } +} + +void QxtCheckComboBox::keyReleaseEvent(QKeyEvent* event) +{ + if (event->key() != Qt::Key_Up && event->key() != Qt::Key_Down) + { + QComboBox::keyReleaseEvent(event); + } + else + { + showPopup(); + } +}