1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2009-04-30
7 * Description : rating icon view item at mouse hover
8 *
9 * Copyright (C) 2008 by Peter Penz <peter dot penz at gmx dot at>
10 * Copyright (C) 2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11 * Copyright (C) 2009-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12 *
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software Foundation;
16 * either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * ============================================================ */
25
26 #include "itemratingoverlay.h"
27
28 // Local includes
29
30 #include "itemdelegate.h"
31 #include "itemmodel.h"
32 #include "itemcategorizedview.h"
33 #include "ratingwidget.h"
34
35 namespace Digikam
36 {
37
ItemRatingOverlay(QObject * const parent)38 ItemRatingOverlay::ItemRatingOverlay(QObject* const parent)
39 : AbstractWidgetDelegateOverlay(parent)
40 {
41 }
42
ratingWidget() const43 RatingWidget* ItemRatingOverlay::ratingWidget() const
44 {
45 return static_cast<RatingWidget*>(m_widget);
46 }
47
createWidget()48 QWidget* ItemRatingOverlay::createWidget()
49 {
50 RatingWidget* const w = new RatingWidget(parentWidget());
51 w->setFading(true);
52 w->setTracking(false);
53
54 return w;
55 }
56
setActive(bool active)57 void ItemRatingOverlay::setActive(bool active)
58 {
59 AbstractWidgetDelegateOverlay::setActive(active);
60
61 if (active)
62 {
63 connect(ratingWidget(), SIGNAL(signalRatingChanged(int)),
64 this, SLOT(slotRatingChanged(int)));
65
66 if (view()->model())
67 {
68 connect(view()->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
69 this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
70 }
71 }
72 else
73 {
74 // widget is deleted
75
76 if (view() && view()->model())
77 {
78 disconnect(view()->model(), nullptr, this, nullptr);
79 }
80 }
81 }
82
visualChange()83 void ItemRatingOverlay::visualChange()
84 {
85 if (m_widget &&
86 m_widget->isVisible())
87 {
88 updatePosition();
89 }
90 }
91
widgetEnterEvent()92 void ItemRatingOverlay::widgetEnterEvent()
93 {
94 widgetEnterNotifyMultiple(m_index);
95 }
96
widgetLeaveEvent()97 void ItemRatingOverlay::widgetLeaveEvent()
98 {
99 widgetLeaveNotifyMultiple();
100 }
101
hide()102 void ItemRatingOverlay::hide()
103 {
104 delegate()->setRatingEdited(QModelIndex());
105 AbstractWidgetDelegateOverlay::hide();
106 }
107
updatePosition()108 void ItemRatingOverlay::updatePosition()
109 {
110 if (!m_index.isValid() || !m_widget)
111 {
112 return;
113 }
114
115 QRect rect = delegate()->ratingRect();
116
117 if (rect.width() > ratingWidget()->maximumVisibleWidth())
118 {
119 int offset = (rect.width() - ratingWidget()->maximumVisibleWidth()) / 2;
120 rect.adjust(offset, 0, -offset, 0);
121 }
122
123 QRect visualRect = m_view->visualRect(m_index);
124 rect.translate(visualRect.topLeft());
125
126 m_widget->setFixedSize(rect.width() + 1, rect.height() + 1);
127 m_widget->move(rect.topLeft());
128 }
129
updateRating()130 void ItemRatingOverlay::updateRating()
131 {
132 if (!m_index.isValid() || !m_widget)
133 {
134 return;
135 }
136
137 ItemInfo info = ItemModel::retrieveItemInfo(m_index);
138 ratingWidget()->setRating(info.rating());
139 }
140
slotRatingChanged(int rating)141 void ItemRatingOverlay::slotRatingChanged(int rating)
142 {
143 if (m_widget &&
144 m_widget->isVisible() &&
145 m_index.isValid())
146 {
147 emit ratingEdited(affectedIndexes(m_index), rating);
148 }
149 }
150
slotEntered(const QModelIndex & index)151 void ItemRatingOverlay::slotEntered(const QModelIndex& index)
152 {
153 AbstractWidgetDelegateOverlay::slotEntered(index);
154
155 // See bug 228810, this is a small workaround
156 if (m_widget &&
157 m_widget->isVisible() &&
158 m_index.isValid() &&
159 index == m_index)
160 {
161 ratingWidget()->setVisibleImmediately();
162 }
163
164 m_index = index;
165
166 updatePosition();
167 updateRating();
168
169 delegate()->setRatingEdited(m_index);
170 view()->update(m_index);
171 }
172
slotDataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)173 void ItemRatingOverlay::slotDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
174 {
175 if (m_widget &&
176 m_widget->isVisible() &&
177 QItemSelectionRange(topLeft, bottomRight).contains(m_index))
178 {
179 updateRating();
180 }
181 }
182
183 } // namespace Digikam
184