OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / libs / utils / detailswidget.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "detailswidget.h"
34 #include "detailsbutton.h"
35
36 #include <QtCore/QStack>
37 #include <QtCore/QPropertyAnimation>
38
39 #include <QtGui/QGridLayout>
40 #include <QtGui/QLabel>
41 #include <QtGui/QCheckBox>
42 #include <QtGui/QPainter>
43 #include <QtGui/QScrollArea>
44 #include <QtGui/QApplication>
45
46 /*!
47     \class Utils::DetailsWidget
48
49     \brief Widget a button to expand a 'Details' area.
50
51     This widget is using a grid layout and places the items
52     in the following way:
53
54     \code
55 +------------+-------------------------+---------------+
56 +summaryLabel|              toolwidget | detailsButton |
57 +------------+-------------------------+---------------+
58 +                additional summary                    |
59 +------------+-------------------------+---------------+
60 |                  widget                              |
61 +------------+-------------------------+---------------+
62     \endcode
63 */
64
65 namespace Utils {
66
67     static const int MARGIN=8;
68
69     struct DetailsWidgetPrivate {
70         DetailsWidgetPrivate(QWidget *parent);
71
72         DetailsButton *m_detailsButton;
73         QGridLayout *m_grid;
74         QLabel *m_summaryLabel;
75         QCheckBox *m_summaryCheckBox;
76         QLabel *m_additionalSummaryLabel;
77         Utils::FadingPanel *m_toolWidget;
78         QWidget *m_widget;
79
80         QPixmap m_collapsedPixmap;
81         QPixmap m_expandedPixmap;
82
83         DetailsWidget::State m_state;
84         bool m_hovered;
85         bool m_useCheckBox;
86     };
87
88     DetailsWidgetPrivate::DetailsWidgetPrivate(QWidget * parent) :
89             m_detailsButton(new DetailsButton),
90             m_grid(new QGridLayout),
91             m_summaryLabel(new QLabel(parent)),
92             m_summaryCheckBox(new QCheckBox(parent)),
93             m_additionalSummaryLabel(new QLabel(parent)),
94             m_toolWidget(0),
95             m_widget(0),
96             m_state(DetailsWidget::Collapsed),
97             m_hovered(false),
98             m_useCheckBox(false)
99     {
100     }
101
102     DetailsWidget::DetailsWidget(QWidget *parent) :
103             QWidget(parent),
104             d(new DetailsWidgetPrivate(this))
105     {
106         d->m_summaryLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
107         d->m_summaryLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
108         d->m_summaryLabel->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
109
110         d->m_summaryCheckBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
111         d->m_summaryCheckBox->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
112         d->m_summaryCheckBox->setAttribute(Qt::WA_LayoutUsesWidgetRect); /* broken layout on mac otherwise */
113         d->m_summaryCheckBox->setVisible(false);
114
115         d->m_additionalSummaryLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
116         d->m_additionalSummaryLabel->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
117         d->m_additionalSummaryLabel->setWordWrap(true);
118         d->m_additionalSummaryLabel->setVisible(false);
119
120         d->m_grid->setContentsMargins(0, 0, 0, 0);
121         d->m_grid->setSpacing(0);
122         d->m_grid->addWidget(d->m_summaryLabel, 0, 0);
123         d->m_grid->addWidget(d->m_detailsButton, 0, 2);
124         d->m_grid->addWidget(d->m_additionalSummaryLabel, 1, 0, 1, 3);
125         setLayout(d->m_grid);
126
127         connect(d->m_detailsButton, SIGNAL(toggled(bool)),
128                 this, SLOT(setExpanded(bool)));
129         connect(d->m_summaryCheckBox, SIGNAL(toggled(bool)),
130                 this, SIGNAL(checked(bool)));
131         updateControls();
132     }
133
134     DetailsWidget::~DetailsWidget()
135     {
136         delete d;
137     }
138
139     bool DetailsWidget::useCheckBox()
140     {
141         return d->m_useCheckBox;
142     }
143
144     void DetailsWidget::setUseCheckBox(bool b)
145     {
146         d->m_useCheckBox = b;
147         QWidget *widget = b ? static_cast<QWidget *>(d->m_summaryCheckBox) : static_cast<QWidget *>(d->m_summaryLabel);
148         d->m_grid->addWidget(widget, 0, 0);
149         d->m_summaryLabel->setVisible(b);
150         d->m_summaryCheckBox->setVisible(!b);
151     }
152
153     void DetailsWidget::setChecked(bool b)
154     {
155         d->m_summaryCheckBox->setChecked(b);
156     }
157
158     bool DetailsWidget::isChecked() const
159     {
160         return d->m_useCheckBox && d->m_summaryCheckBox->isChecked();
161     }
162
163     void DetailsWidget::setSummaryFontBold(bool b)
164     {
165         QFont f;
166         f.setBold(b);
167         d->m_summaryCheckBox->setFont(f);
168         d->m_summaryLabel->setFont(f);
169     }
170
171     void DetailsWidget::setIcon(const QIcon &icon)
172     {
173         d->m_summaryCheckBox->setIcon(icon);
174     }
175
176     void DetailsWidget::paintEvent(QPaintEvent *paintEvent)
177     {
178         QWidget::paintEvent(paintEvent);
179
180         QPainter p(this);
181
182         QWidget *topLeftWidget = d->m_useCheckBox ? static_cast<QWidget *>(d->m_summaryCheckBox) : static_cast<QWidget *>(d->m_summaryLabel);
183         QPoint topLeft(topLeftWidget->geometry().left(), contentsRect().top());
184         const QRect paintArea(topLeft, contentsRect().bottomRight());
185
186         if (d->m_state != Expanded) {
187             if (d->m_collapsedPixmap.isNull() ||
188                 d->m_collapsedPixmap.size() != size())
189                 d->m_collapsedPixmap = cacheBackground(paintArea.size(), false);
190             p.drawPixmap(paintArea, d->m_collapsedPixmap);
191         } else {
192             if (d->m_expandedPixmap.isNull() ||
193                 d->m_expandedPixmap.size() != size())
194                 d->m_expandedPixmap = cacheBackground(paintArea.size(), true);
195             p.drawPixmap(paintArea, d->m_expandedPixmap);
196         }
197     }
198
199     void DetailsWidget::enterEvent(QEvent * event)
200     {
201         QWidget::enterEvent(event);
202         changeHoverState(true);
203     }
204
205     void DetailsWidget::leaveEvent(QEvent * event)
206     {
207         QWidget::leaveEvent(event);
208         changeHoverState(false);
209     }
210
211     void DetailsWidget::setSummaryText(const QString &text)
212     {
213         d->m_summaryLabel->setText(text);
214         d->m_summaryCheckBox->setText(text);
215     }
216
217     QString DetailsWidget::summaryText() const
218     {
219         return d->m_summaryLabel->text();
220     }
221
222     QString DetailsWidget::additionalSummaryText() const
223     {
224         return d->m_additionalSummaryLabel->text();
225     }
226
227     void DetailsWidget::setAdditionalSummaryText(const QString &text)
228     {
229         d->m_additionalSummaryLabel->setText(text);
230         d->m_additionalSummaryLabel->setVisible(!text.isEmpty());
231     }
232
233     DetailsWidget::State DetailsWidget::state() const
234     {
235         return d->m_state;
236     }
237
238     void DetailsWidget::setState(State state)
239     {
240         if (state == d->m_state)
241             return;
242         d->m_state = state;
243         updateControls();
244     }
245
246     void DetailsWidget::setExpanded(bool expanded)
247     {
248         setState(expanded ? Expanded : Collapsed);
249     }
250
251     void DetailsWidget::updateControls()
252     {
253         if (d->m_widget)
254             d->m_widget->setVisible(d->m_state == Expanded || d->m_state == NoSummary);
255         d->m_detailsButton->setChecked(d->m_state == Expanded && d->m_widget);
256         //d->m_summaryLabel->setEnabled(d->m_state == Collapsed && d->m_widget);
257         d->m_detailsButton->setVisible(d->m_state != NoSummary);
258         d->m_summaryLabel->setVisible(d->m_state != NoSummary && !d->m_useCheckBox);
259         d->m_summaryCheckBox->setVisible(d->m_state != NoSummary && d->m_useCheckBox);
260         {
261             QWidget *w = this;
262             while (w) {
263                 if (w->layout())
264                     w->layout()->activate();
265                 if (QScrollArea *area = qobject_cast<QScrollArea*>(w)) {
266                     QEvent e(QEvent::LayoutRequest);
267                     QCoreApplication::sendEvent(area, &e);
268                 }
269                 w = w->parentWidget();
270             }
271         }
272     }
273
274     QWidget *DetailsWidget::widget() const
275     {
276         return d->m_widget;
277     }
278
279     void DetailsWidget::setWidget(QWidget *widget)
280     {
281         if (d->m_widget == widget)
282             return;
283
284         if (d->m_widget) {
285             d->m_grid->removeWidget(d->m_widget);
286             delete d->m_widget;
287         }
288
289         d->m_widget = widget;
290
291         if (d->m_widget) {
292             d->m_widget->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
293             d->m_grid->addWidget(d->m_widget, 2, 0, 1, 3);
294         }
295         updateControls();
296     }
297
298     void DetailsWidget::setToolWidget(Utils::FadingPanel *widget)
299     {
300         if (d->m_toolWidget == widget)
301             return;
302
303         d->m_toolWidget = widget;
304
305         if (!d->m_toolWidget)
306             return;
307
308         d->m_toolWidget->adjustSize();
309         d->m_grid->addWidget(d->m_toolWidget, 0, 1, 1, 1, Qt::AlignRight);
310
311 #ifdef Q_WS_MAC
312         d->m_toolWidget->setOpacity(1.0);
313 #endif
314         changeHoverState(d->m_hovered);
315     }
316
317     QWidget *DetailsWidget::toolWidget() const
318     {
319         return d->m_toolWidget;
320     }
321
322     QPixmap DetailsWidget::cacheBackground(const QSize &size, bool expanded)
323     {
324         QPixmap pixmap(size);
325         pixmap.fill(Qt::transparent);
326         QPainter p(&pixmap);
327
328         int topHeight = qMax(d->m_detailsButton->height(),
329                              d->m_useCheckBox ? d->m_summaryCheckBox->height() : d->m_summaryLabel->height());
330         QRect topRect(0, 0, size.width(), topHeight);
331         QRect fullRect(0, 0, size.width(), size.height());
332 #ifdef Q_WS_MAC
333         p.fillRect(fullRect, qApp->palette().window().color());
334 #endif
335         p.fillRect(fullRect, QColor(255, 255, 255, 40));
336
337         QColor highlight = palette().highlight().color();
338         highlight.setAlpha(0.5);
339         if (expanded) {
340             p.fillRect(topRect, highlight);
341         }
342
343         QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
344         lg.setColorAt(0, QColor(255, 255, 255, 130));
345         lg.setColorAt(1, QColor(255, 255, 255, 0));
346         p.fillRect(topRect, lg);
347         p.setRenderHint(QPainter::Antialiasing, true);
348         p.translate(0.5, 0.5);
349         p.setPen(QColor(0, 0, 0, 40));
350         p.setBrush(Qt::NoBrush);
351         p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
352         p.setBrush(Qt::NoBrush);
353         p.setPen(QColor(255,255,255,140));
354         p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
355         p.setPen(QPen(palette().color(QPalette::Mid)));
356
357         return pixmap;
358     }
359
360     void DetailsWidget::changeHoverState(bool hovered)
361     {
362         if (!d->m_toolWidget)
363             return;
364 #ifdef Q_OS_MAC
365         d->m_toolWidget->setVisible(hovered);
366 #else
367         d->m_toolWidget->fadeTo(hovered ? 1.0 : 0);
368 #endif
369         d->m_hovered = hovered;
370     }
371
372 } // namespace Utils