diff --git a/core/utilities/searchwindow/choicesearchutilities.cpp b/core/utilities/searchwindow/choicesearchutilities.cpp index 3c841d974a..20d46d9c9f 100644 --- a/core/utilities/searchwindow/choicesearchutilities.cpp +++ b/core/utilities/searchwindow/choicesearchutilities.cpp @@ -1,288 +1,294 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-04-18 * Description : User interface for searches * * Copyright (C) 2008-2012 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "choicesearchutilities.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "searchutilities.h" namespace Digikam { ChoiceSearchModel::Entry::Entry() : m_checkState(false) { } ChoiceSearchModel::Entry::Entry(const QVariant& key, const QString& userDisplay) : m_key(key), m_display(userDisplay), m_checkState(false) { } bool ChoiceSearchModel::Entry::operator==(const Entry& other) const { - return m_key == other.m_key; + return (m_key == other.m_key); } ChoiceSearchModel::ChoiceSearchModel(QObject* const parent) : QAbstractListModel(parent) { } void ChoiceSearchModel::setChoice(const QMap& data) { if (m_entries.size()) { beginResetModel(); m_entries.clear(); endResetModel(); } - for (QMap::const_iterator it = data.constBegin(); it != data.constEnd(); ++it) + for (QMap::const_iterator it = data.constBegin() ; it != data.constEnd() ; ++it) { m_entries << Entry(it.key(), it.value()); } } void ChoiceSearchModel::setChoice(const QVariantList& data) { if (m_entries.size()) { beginResetModel(); m_entries.clear(); endResetModel(); } Q_ASSERT(data.size() % 2 == 0); - for (QVariantList::const_iterator it = data.constBegin(); it != data.constEnd();) + for (QVariantList::const_iterator it = data.constBegin() ; it != data.constEnd() ; ) { QVariant key = *it; ++it; QString value = (*it).toString(); ++it; m_entries << Entry(key, value); } } void ChoiceSearchModel::setChoice(const QStringList& data) { if (m_entries.size()) { beginResetModel(); m_entries.clear(); endResetModel(); } Q_ASSERT(data.size() % 2 == 0); - for (QStringList::const_iterator it = data.constBegin(); it != data.constEnd();) + for (QStringList::const_iterator it = data.constBegin() ; it != data.constEnd() ; ) { QVariant key = *it; ++it; QString value = *it; ++it; m_entries << Entry(key, value); } } QVariantList ChoiceSearchModel::checkedKeys() const { QVariantList list; - for (QList::const_iterator it = m_entries.constBegin(); it != m_entries.constEnd(); ++it) + for (QList::const_iterator it = m_entries.constBegin() ; it != m_entries.constEnd() ; ++it) { if ((*it).m_checkState) { list << (*it).m_key; } } return list; } QStringList ChoiceSearchModel::checkedDisplayTexts() const { QStringList list; - for (QList::const_iterator it = m_entries.constBegin(); it != m_entries.constEnd(); ++it) + for (QList::const_iterator it = m_entries.constBegin() ; it != m_entries.constEnd() ; ++it) { if ((*it).m_checkState) { list << (*it).m_display; } } return list; } void ChoiceSearchModel::setChecked(int i, bool checked) { m_entries[i].m_checkState = checked; QModelIndex modelIndex = index(i); emit dataChanged(modelIndex, modelIndex); emit checkStateChanged(m_entries.at(i).m_key, checked); } void ChoiceSearchModel::resetChecked() { - for (int i = 0; i < m_entries.size(); ++i) + for (int i = 0 ; i < m_entries.size() ; ++i) { if (m_entries.at(i).m_checkState) { setChecked(i, false); } } } int ChoiceSearchModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } return m_entries.count(); } QVariant ChoiceSearchModel::data(const QModelIndex& index, int role) const { if (index.isValid()) { - if (role == Qt::DisplayRole) + if (role == Qt::DisplayRole) { return m_entries.at(index.row()).m_display; } else if (role == Qt::CheckStateRole) { return m_entries.at(index.row()).m_checkState ? Qt::Checked : Qt::Unchecked; } else if (role == IdRole) { return m_entries.at(index.row()).m_key; } } return QVariant(); } QModelIndex ChoiceSearchModel::index(int row, int column, const QModelIndex& parent) const { - if (parent.isValid() || column != 0 || row >= m_entries.size()) + if (parent.isValid() || (column != 0) || (row >= m_entries.size())) { return QModelIndex(); } return createIndex(row, 0); } Qt::ItemFlags ChoiceSearchModel::flags(const QModelIndex& index) const { return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable; } bool ChoiceSearchModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (role == Qt::CheckStateRole) { Qt::CheckState state = (Qt::CheckState)value.toInt(); setChecked(index.row(), state == Qt::Checked); + return true; } else { return QAbstractListModel::setData(index, value, role); } } // -------------------------------------------------------------------------------------- ChoiceSearchComboBox::ChoiceSearchComboBox(QWidget* const parent) : ListViewComboBox(parent), m_label(nullptr) { } void ChoiceSearchComboBox::setModel(ChoiceSearchModel* model) { ModelIndexBasedComboBox::setModel(model); installView(); } ChoiceSearchModel* ChoiceSearchComboBox::model() const { return static_cast(ListViewComboBox::model()); } DSqueezedClickLabel* ChoiceSearchComboBox::label() const { return m_label; } void ChoiceSearchComboBox::setLabelText(const QString& text) { m_label->setAdjustedText(text); } void ChoiceSearchComboBox::labelClicked() { qCDebug(DIGIKAM_GENERAL_LOG) << "labelClicked"; showPopup(); } void ChoiceSearchComboBox::installView(QAbstractItemView* v) { // make protected again - ListViewComboBox::installView(v); - //view()->setHeaderHidden(true); + ListViewComboBox::installView(v); +/* + view()->setHeaderHidden(true); +*/ view()->setAlternatingRowColors(true); // create the label + m_label = new DSqueezedClickLabel; m_label->setElideMode(Qt::ElideRight); // set a line edit that carries the label + ProxyClickLineEdit* const lineEdit = new ProxyClickLineEdit; lineEdit->setCursor(m_label->cursor()); lineEdit->setWidget(m_label); setLineEdit(lineEdit); // connect clicks on upper area (both line edit and widget within) to showPopup + connect(lineEdit, SIGNAL(leftClicked()), this, SLOT(labelClicked())); connect(m_label, SIGNAL(activated()), this, SLOT(labelClicked())); } } // namespace Digikam diff --git a/core/utilities/searchwindow/choicesearchutilities.h b/core/utilities/searchwindow/choicesearchutilities.h index 20232b64e0..b9ee21be41 100644 --- a/core/utilities/searchwindow/choicesearchutilities.h +++ b/core/utilities/searchwindow/choicesearchutilities.h @@ -1,234 +1,247 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-04-18 * Description : User interface for searches * * Copyright (C) 2008-2012 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_CHOICE_SEARCH_UTILITIES_H #define DIGIKAM_CHOICE_SEARCH_UTILITIES_H // Qt includes #include #include #include // Local includes #include "dexpanderbox.h" #include "coredbsearchxml.h" #include "comboboxutilities.h" namespace Digikam { class ChoiceSearchModel : public QAbstractListModel { Q_OBJECT public: enum CustomRoles { IdRole = Qt::UserRole }; public: explicit ChoiceSearchModel(QObject* const parent = nullptr); - /** Sets the data from the given map, with integer keys and QString user displayable value. + /** + * Sets the data from the given map, with integer keys and QString user displayable value. */ void setChoice(const QMap& data); - /** Sets the data from the given list, - * taking every first entry as the key, every second as the user displayable value. - * Ensure that the QVariants' type is correct (identical for all even entries, QString for all odd entries). + /** + * Sets the data from the given list, + * taking every first entry as the key, every second as the user displayable value. + * Ensure that the QVariants' type is correct (identical for all even entries, QString for all odd entries). */ void setChoice(const QVariantList& data); - /** Sets the data from the given list, - * taking every first entry as the key, every second as the user displayable value. + /** + * Sets the data from the given list, + * taking every first entry as the key, every second as the user displayable value. */ void setChoice(const QStringList& data); - /** Returns the keys of all entries that are selected (checked). + /** + * Returns the keys of all entries that are selected (checked). */ QVariantList checkedKeys() const; - /** Returns the keys of all entries that are selected (checked), converted to - * a list of the template type. Supported for Int and QString types. + /** + * Returns the keys of all entries that are selected (checked), converted to + * a list of the template type. Supported for Int and QString types. */ template QList checkedKeys() const; - /** Returns the display text of all entries that are selected. + /** + * Returns the display text of all entries that are selected. */ QStringList checkedDisplayTexts() const; - /** Sets the check state of the entry with given key. + /** + * Sets the check state of the entry with given key. */ template void setChecked(const T& key, bool checked = true); - /** Sets the check state of all the entries whose key is found in the list to checked. + /** + * Sets the check state of all the entries whose key is found in the list to checked. */ template void setChecked(const QList& keys, bool checked = true); - /** Sets the check state of all entries. The check state is determined by - * the key of an entry, the relation, and a constant value. - * Think of "Set to checked if key is less than 5". - * Supported for Int and QString types. + /** + * Sets the check state of all entries. The check state is determined by + * the key of an entry, the relation, and a constant value. + * Think of "Set to checked if key is less than 5". + * Supported for Int and QString types. */ template void setChecked(const T& value, SearchXml::Relation relation); - /** Sets all entries to unchecked. + /** + * Sets all entries to unchecked. */ void resetChecked(); virtual int rowCount(const QModelIndex& parent) const; virtual QVariant data(const QModelIndex& index, int role) const; virtual QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const; virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role); Q_SIGNALS: void checkStateChanged(const QVariant& key, bool isChecked); protected: void setChecked(int index, bool checked); protected: class Entry { public: Entry(); Entry(const QVariant& key, const QString& userDisplay); bool operator==(const Entry& other) const; /// @todo This function has no definition. bool operator==(const QVariant& other) const; public: QVariant m_key; QString m_display; bool m_checkState; }; protected: QList m_entries; }; template void ChoiceSearchModel::setChecked(const T& key, bool checked) { QVariant variantKey(key); - for (int i = 0; i < m_entries.size(); ++i) + for (int i = 0 ; i < m_entries.size() ; ++i) { if (m_entries[i].m_key == variantKey) { setChecked(i, checked); } } } template void ChoiceSearchModel::setChecked(const T& value, SearchXml::Relation relation) { - for (int i = 0; i < m_entries.size(); ++i) + for (int i = 0 ; i < m_entries.size() ; ++i) { setChecked(i, SearchXml::testRelation(m_entries.at(i).m_key.value(), value, relation)); } } template void ChoiceSearchModel::setChecked(const QList& keys, bool checked) { foreach (T key, keys) { setChecked(key, checked); } } template QList ChoiceSearchModel::checkedKeys() const { QList list; - for (QList::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it) + for (QList::const_iterator it = m_entries.begin() ; it != m_entries.end() ; ++it) { if ((*it).m_checkState) { list << (*it).m_key.value(); } } return list; } // ------------------------------------------------------------------------------------- class ChoiceSearchComboBox : public ListViewComboBox { Q_OBJECT public: - /** A combo box for entering a choice of values. - * Operates on a ChoiceSearchModel. - * After constructing the object, call setModel - * with your model. + /** + * A combo box for entering a choice of values. + * Operates on a ChoiceSearchModel. + * After constructing the object, call setModel + * with your model. */ explicit ChoiceSearchComboBox(QWidget* const parent = nullptr); - /** Sets the model and initializes the widget. - * Can only be called once for a widget. + /** + * Sets the model and initializes the widget. + * Can only be called once for a widget. */ void setModel(ChoiceSearchModel* model); - /** Updates the text on the line edit area. + /** + * Updates the text on the line edit area. */ void setLabelText(const QString& text); ChoiceSearchModel* model() const; DSqueezedClickLabel* label() const; Q_SIGNALS: void checkStateChanged(); protected Q_SLOTS: void labelClicked(); protected: virtual void installView(QAbstractItemView* view = nullptr); protected: DSqueezedClickLabel* m_label; }; } // namespace Digikam #endif // DIGIKAM_CHOICE_SEARCH_UTILITIES_H diff --git a/core/utilities/searchwindow/editablesearchtreeview.cpp b/core/utilities/searchwindow/editablesearchtreeview.cpp index 9a51b0003e..336d180878 100644 --- a/core/utilities/searchwindow/editablesearchtreeview.cpp +++ b/core/utilities/searchwindow/editablesearchtreeview.cpp @@ -1,127 +1,129 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-01-14 * Description : Basic search tree view with editing functionality * * Copyright (C) 2008-2020 by Gilles Caulier * Copyright (C) 2009-2010 by Johannes Wienke * Copyright (C) 2009 by Andi Clemens * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "editablesearchtreeview.h" // Qt includes #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "contextmenuhelper.h" namespace Digikam { class Q_DECL_HIDDEN EditableSearchTreeView::Private { public: explicit Private() : searchModificationHelper(nullptr), renameSearchAction(nullptr), deleteSearchAction(nullptr) { } SearchModificationHelper* searchModificationHelper; QAction* renameSearchAction; QAction* deleteSearchAction; }; EditableSearchTreeView::EditableSearchTreeView(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper) - : SearchTreeView(parent), d(new Private) + : SearchTreeView(parent), + d(new Private) { setAlbumModel(searchModel); d->searchModificationHelper = searchModificationHelper; - d->renameSearchAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")), i18n("Rename..."), this); - d->deleteSearchAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18n("Delete"), this); + d->renameSearchAction = new QAction(QIcon::fromTheme(QLatin1String("document-edit")), i18n("Rename..."), this); + d->deleteSearchAction = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18n("Delete"), this); setSortingEnabled(true); setSelectAlbumOnClick(true); setEnableContextMenu(true); } EditableSearchTreeView::~EditableSearchTreeView() { delete d; } QString EditableSearchTreeView::contextMenuTitle() const { return i18n("Searches"); } void EditableSearchTreeView::addCustomContextMenuActions(ContextMenuHelper& cmh, Album* album) { SAlbum* const searchAlbum = dynamic_cast(album); // disable actions if there is no album or the album is a temporary search + bool activate = false; if (searchAlbum) { activate = !searchAlbum->isTemporarySearch(); } d->renameSearchAction->setEnabled(activate); d->deleteSearchAction->setEnabled(activate); cmh.addAction(d->renameSearchAction); cmh.addAction(d->deleteSearchAction); } void EditableSearchTreeView::handleCustomContextMenuAction(QAction* action, AlbumPointer album) { Album* const a = album; SAlbum* const searchAlbum = dynamic_cast(a); if (!searchAlbum || !action) { return; } - if (action == d->renameSearchAction) + if (action == d->renameSearchAction) { d->searchModificationHelper->slotSearchRename(searchAlbum); } else if (action == d->deleteSearchAction) { d->searchModificationHelper->slotSearchDelete(searchAlbum); } } } // namespace Digikam diff --git a/core/utilities/searchwindow/editablesearchtreeview.h b/core/utilities/searchwindow/editablesearchtreeview.h index 21c9484af6..0af7fdc5cf 100644 --- a/core/utilities/searchwindow/editablesearchtreeview.h +++ b/core/utilities/searchwindow/editablesearchtreeview.h @@ -1,88 +1,90 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-01-14 * Description : Basic search tree view with editing functionality * * Copyright (C) 2008-2020 by Gilles Caulier * Copyright (C) 2009-2010 by Johannes Wienke * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_EDITABLE_SEARCH_TREE_VIEW_H #define DIGIKAM_EDITABLE_SEARCH_TREE_VIEW_H // Local includes #include "searchtreeview.h" #include "searchmodificationhelper.h" namespace Digikam { /** * This tree view for searches adds basic editing functionality via the context * menu. This is in detail deleting and renaming existing searches. * * @author jwienke */ class EditableSearchTreeView: public SearchTreeView { Q_OBJECT public: /** * Constructor. * * @param parent qt parent * @param searchModel the model this view should act on * @param searchModificationHelper the modification helper object used to * perform operations on the displayed * searches */ EditableSearchTreeView(QWidget* const parent, SearchModel* const searchModel, SearchModificationHelper* const searchModificationHelper); /** * Destructor. */ virtual ~EditableSearchTreeView(); protected: - // implemented hook methods for context menus. + /** + * implemented hook methods for context menus. + */ virtual QString contextMenuTitle() const; /** * Adds actions to delete or rename existing searches. */ virtual void addCustomContextMenuActions(ContextMenuHelper& cmh, Album* album); /** * Handles deletion and renaming actions. */ virtual void handleCustomContextMenuAction(QAction* action, AlbumPointer album); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_EDITABLE_SEARCH_TREE_VIEW_H diff --git a/core/utilities/searchwindow/ratingsearchutilities.cpp b/core/utilities/searchwindow/ratingsearchutilities.cpp index fa1c45af84..206c07847a 100644 --- a/core/utilities/searchwindow/ratingsearchutilities.cpp +++ b/core/utilities/searchwindow/ratingsearchutilities.cpp @@ -1,436 +1,453 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-03-14 * Description : User interface for searches * * Copyright (C) 2008-2012 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "ratingsearchutilities.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "ratingwidget.h" namespace Digikam { RatingStarDrawer::RatingStarDrawer() + : m_starPolygon(RatingWidget::starPolygon()), + m_starPolygonSize(QSize(15, 15)) { - m_starPolygon = RatingWidget::starPolygon(); - m_starPolygonSize = QSize(15, 15); } QRect RatingStarDrawer::drawStarPolygons(QPainter* painter, int numberOfStars) const { QRect drawnRect(0, 0, 0, 0); QPolygon polygon(m_starPolygon); if (numberOfStars) { drawnRect.adjust(0, 0, 0, m_starPolygonSize.height()); } - for (int i = 0; i < numberOfStars; ++i) + for (int i = 0 ; i < numberOfStars ; ++i) { painter->drawPolygon(polygon, Qt::WindingFill); polygon.translate(m_starPolygonSize.width(), 0); drawnRect.adjust(0, 0, m_starPolygonSize.width(), 0); } return drawnRect; } // ------------------------------------------------------------------------- RatingComboBoxDelegate::RatingComboBoxDelegate(QObject* const parent) : QItemDelegate(parent) { } QSize RatingComboBoxDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { QVariant value = index.data(Qt::DisplayRole); if (value.type() == QVariant::Int) { return QSize(RatingMax * (m_starPolygonSize.width() + 1), m_starPolygonSize.height()); } else { return QItemDelegate::sizeHint(option, index); } } void RatingComboBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QVariant value = index.data(Qt::DisplayRole); bool selectable = index.flags() & Qt::ItemIsSelectable; if (value.type() == QVariant::Int) { painter->save(); drawBackground(painter, option, index); drawDisplay(painter, option, option.rect, QString()); // our custom painting + drawRating(painter, option.rect, value.toInt(), selectable); drawFocus(painter, option, option.rect); painter->restore(); } else { return QItemDelegate::paint(painter, option, index); } } void RatingComboBoxDelegate::drawRating(QPainter* painter, const QRect& rect, int rating, bool selectable) const { painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); - //pen.setJoinStyle(Qt::MiterJoin); +/* + pen.setJoinStyle(Qt::MiterJoin); +*/ painter->setPen(qApp->palette().color(QPalette::Text)); if (!selectable) { painter->setOpacity(.1); } painter->setBrush(qApp->palette().color(QPalette::Link)); + // move painter while drawing polygons + painter->translate(rect.topLeft()); QRect drawRect = drawStarPolygons(painter, rating); painter->translate(drawRect.topRight()); painter->setBrush(QBrush()); drawStarPolygons(painter, RatingMax - rating); painter->restore(); } // ------------------------------------------------------------------------- RatingComboBoxModel::RatingComboBoxModel(QObject* const parent) : QAbstractListModel(parent) { - for (int value = RatingComboBox::Null; value <= RatingComboBox::Rating5; ++value) + for (int value = RatingComboBox::Null ; value <= RatingComboBox::Rating5 ; ++value) { m_entries << (RatingComboBox::RatingValue)value; } } int RatingComboBoxModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } return m_entries.size(); } QVariant RatingComboBoxModel::data(const QModelIndex& index, int role) const { if (index.isValid()) { RatingComboBox::RatingValue value = (RatingComboBox::RatingValue)index.internalId(); - if (role == Qt::DisplayRole) + if (role == Qt::DisplayRole) { return ratingValueToDisplay(value); } else if (role == RatingRole) { return (int)value; } } return QVariant(); } QVariant RatingComboBoxModel::ratingValueToDisplay(RatingComboBox::RatingValue value) const { switch (value) { case RatingComboBox::Null: return i18n("(No Value Selected)"); case RatingComboBox::NoRating: return i18n("No Rating assigned"); case RatingComboBox::Rating0: case RatingComboBox::Rating1: case RatingComboBox::Rating2: case RatingComboBox::Rating3: case RatingComboBox::Rating4: case RatingComboBox::Rating5: return (int)value; } return QVariant(); } QModelIndex RatingComboBoxModel::index(int row, int column, const QModelIndex& parent) const { - if (parent.isValid() || column != 0 || row >= m_entries.size()) + if (parent.isValid() || (column != 0) || (row >= m_entries.size())) { return QModelIndex(); } // third argument: RatingValue as internal data + return createIndex(row, column, m_entries.at(row)); } QModelIndex RatingComboBoxModel::indexForRatingValue(RatingComboBox::RatingValue value) const { int row = m_entries.indexOf(value); if (row != -1) { return createIndex(row, 0, value); } return QModelIndex(); } // ------------------------------------------------------------------------- RatingComboBoxWidget::RatingComboBoxWidget(QWidget* const parent) : RatingWidget(parent) { m_value = RatingComboBox::Null; // generate paint event on mouse enter/leave + setAttribute(Qt::WA_Hover); + // set lineedit-like background, also for cached pixmaps + setBackgroundRole(QPalette::Base); regeneratePixmaps(); connect(this, SIGNAL(signalRatingChanged(int)), this, SLOT(slotRatingChanged(int))); } RatingComboBox::RatingValue RatingComboBoxWidget::ratingValue() const { return m_value; } void RatingComboBoxWidget::setRatingValue(RatingComboBox::RatingValue value) { if (m_value == value) { return; } m_value = value; // sync with base class + blockSignals(true); if (m_value >= RatingComboBox::Rating0) { setRating(value); } else { setRating(0); } blockSignals(false); update(); emit ratingValueChanged(m_value); } void RatingComboBoxWidget::slotRatingChanged(int rating) { RatingComboBox::RatingValue newValue = (RatingComboBox::RatingValue)rating; if (m_value != newValue) { m_value = newValue; emit ratingValueChanged(m_value); } } void RatingComboBoxWidget::paintEvent(QPaintEvent* e) { - if (m_value >= RatingComboBox::Rating0) + if (m_value >= RatingComboBox::Rating0) { //qCDebug(DIGIKAM_GENERAL_LOG) << "m_value" << m_value << "defaulting paint to parent" << this; + RatingWidget::paintEvent(e); } else if (m_value == RatingComboBox::NoRating) { QPainter p(this); QPixmap pix = starPixmap(); int width = pix.width(); p.drawPixmap(0, 0, pix); + // draw red cross + p.setPen(Qt::red); p.drawLine(0, 0, width, width); p.drawLine(0, width, width, 0); } else if (m_value == RatingComboBox::Null) { QPainter p(this); if (underMouse() && isEnabled()) { QPixmap pix = starPixmap(); - int x = 0; + int x = 0; - for (int i = 0; i < RatingMax; ++i) + for (int i = 0 ; i < RatingMax ; ++i) { p.drawPixmap(x, 0, pix); x += pix.width(); } } else { p.setRenderHint(QPainter::Antialiasing, true); +/* //pen.setJoinStyle(Qt::MiterJoin); - +*/ QColor foreground = palette().color(QPalette::Active, QPalette::WindowText); QColor background = palette().color(QPalette::Active, QPalette::Window); foreground.setAlphaF(foreground.alphaF() * 0.5); background.setAlphaF(background.alphaF() * 0.5); QColor foregroundEnd(foreground), backgroundEnd(background); foregroundEnd.setAlphaF(0); backgroundEnd.setAlphaF(0); QLinearGradient grad(QPointF(0, (double)rect().height() / 2), QPointF(width(), (double)rect().height() / 2)); grad.setColorAt(0, foreground); grad.setColorAt(1, foregroundEnd); p.setPen(QPen(grad, 0)); grad.setColorAt(0, background); grad.setColorAt(1, backgroundEnd); p.setBrush(grad); drawStarPolygons(&p, 5); } } } // ------------------------------------------------------------------------- RatingComboBox::RatingComboBox(QWidget* const parent) : ModelIndexBasedComboBox(parent) { m_syncing = false; // create a custom model that contains the rating values + m_model = new RatingComboBoxModel(this); setModel(m_model); // set a custom delegate which draws rating stars + RatingComboBoxDelegate* delegate = new RatingComboBoxDelegate(this); view()->setItemDelegate(delegate); // set a line edit that carries a RatingWidget + ProxyLineEdit* lineEdit = new ProxyLineEdit; m_ratingWidget = new RatingComboBoxWidget; lineEdit->setWidget(m_ratingWidget); setLineEdit(lineEdit); connect(view()->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentValueChanged(QModelIndex,QModelIndex))); connect(m_ratingWidget, SIGNAL(ratingValueChanged(int)), this, SLOT(ratingWidgetChanged(int))); } void RatingComboBox::setRatingValue(RatingComboBox::RatingValue value) { - if (value > Rating5) + if (value > Rating5) { value = Rating5; } else if (value < Null) { value = Null; } setCurrentIndex(m_model->indexForRatingValue(value)); } RatingComboBox::RatingValue RatingComboBox::ratingValue() const { return (RatingValue)view()->currentIndex().data(RatingComboBoxModel::RatingRole).toInt(); } void RatingComboBox::currentValueChanged(const QModelIndex& current, const QModelIndex&) { if (m_syncing) { return; } RatingValue value = (RatingValue)current.data(RatingComboBoxModel::RatingRole).toInt(); - m_syncing = true; + m_syncing = true; m_ratingWidget->setRatingValue(value); - m_syncing = false; + m_syncing = false; emit ratingValueChanged(value); } void RatingComboBox::ratingWidgetChanged(int rv) { if (m_syncing) { return; } RatingValue value = (RatingValue)rv; QModelIndex index = m_model->indexForRatingValue(value); - m_syncing = true; + m_syncing = true; setCurrentIndex(index); - m_syncing = false; + m_syncing = false; emit ratingValueChanged(value); } } // namespace Digikam diff --git a/core/utilities/searchwindow/ratingsearchutilities.h b/core/utilities/searchwindow/ratingsearchutilities.h index 4b2ae2533d..1c35a8dcc6 100644 --- a/core/utilities/searchwindow/ratingsearchutilities.h +++ b/core/utilities/searchwindow/ratingsearchutilities.h @@ -1,196 +1,198 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2008-03-14 * Description : User interface for searches * * Copyright (C) 2008-2012 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_RATING_SEARCH_UTILITIES_H #define DIGIKAM_RATING_SEARCH_UTILITIES_H // Qt includes #include #include #include #include // Local includes #include "ratingwidget.h" #include "comboboxutilities.h" class QTreeView; class QVBoxLayout; namespace Digikam { class RatingComboBoxModel; class RatingComboBoxWidget; class RatingComboBox : public ModelIndexBasedComboBox { Q_OBJECT public: - /** An advanced widget for entering a rating, - * including support for Null and NoRating values + /** + * An advanced widget for entering a rating, + * including support for Null and NoRating values */ enum RatingValue { - /** The rating value. All values except Null correspond to - * the integers used by the database. + /** + * The rating value. All values except Null correspond to + * the integers used by the database. */ Null = -2, NoRating = -1, Rating0 = 0, Rating1 = 1, Rating2 = 2, Rating3 = 3, Rating4 = 4, Rating5 = 5 }; public: explicit RatingComboBox(QWidget* const parent = nullptr); void setRatingValue(RatingValue value); RatingValue ratingValue() const; Q_SIGNALS: void ratingValueChanged(int value); protected Q_SLOTS: void currentValueChanged(const QModelIndex& current, const QModelIndex& previous); void ratingWidgetChanged(int); protected: RatingComboBoxModel* m_model; RatingComboBoxWidget* m_ratingWidget; private: bool m_syncing; }; // -- Internal classes ---------------------------------------------------------------- class RatingStarDrawer { public: RatingStarDrawer(); QRect drawStarPolygons(QPainter* p, int numberOfStars) const; protected: QPolygon m_starPolygon; QSize m_starPolygonSize; }; // ------------------------------------------------------------------------- class RatingComboBoxWidget : public RatingWidget, public RatingStarDrawer { Q_OBJECT public: - /// Internal - // Sub-classing the classic RatingWidget, - // this provides support for the Null and NoRating states. - + /** + * Internal sub-classing the classic RatingWidget, + * this provides support for the Null and NoRating states. + */ explicit RatingComboBoxWidget(QWidget* const parent = nullptr); RatingComboBox::RatingValue ratingValue() const; void setRatingValue(RatingComboBox::RatingValue value); Q_SIGNALS: void ratingValueChanged(int value); protected Q_SLOTS: void slotRatingChanged(int); protected: virtual void paintEvent(QPaintEvent*) override; protected: RatingComboBox::RatingValue m_value; }; // ------------------------------------------------------------------------- class RatingComboBoxModel : public QAbstractListModel { public: enum CustomRoles { RatingRole = Qt::UserRole }; public: explicit RatingComboBoxModel(QObject* const parent = nullptr); QModelIndex indexForRatingValue(RatingComboBox::RatingValue value) const; virtual int rowCount(const QModelIndex& parent) const override; virtual QVariant data(const QModelIndex& index, int role) const override; virtual QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const override; protected: QVariant ratingValueToDisplay(RatingComboBox::RatingValue value) const; protected: QList m_entries; }; // ------------------------------------------------------------------------- class RatingComboBoxDelegate : public QItemDelegate, public RatingStarDrawer { public: explicit RatingComboBoxDelegate(QObject* const parent = nullptr); virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; protected: void drawRating(QPainter* painter, const QRect& rect, int rating, bool selectable) const; }; } // namespace Digikam #endif // DIGIKAM_RATING_SEARCH_UTILITIES_H