~ubuntu-branches/ubuntu/quantal/marble/quantal

« back to all changes in this revision

Viewing changes to src/lib/PluginItemDelegate.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Philip Muškovac
  • Date: 2011-07-11 15:43:02 UTC
  • Revision ID: james.westby@ubuntu.com-20110711154302-lq69ftcx125g1jx5
Tags: upstream-4.6.90+repack
Import upstream version 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// This file is part of the Marble Virtual Globe.
 
3
//
 
4
// This program is free software licensed under the GNU LGPL. You can
 
5
// find a copy of this license in LICENSE.txt in the top directory of
 
6
// the source code.
 
7
//
 
8
// Copyright 2009 Bastian Holst <bastianholst@gmx.de>
 
9
//
 
10
 
 
11
// Self
 
12
#include "PluginItemDelegate.h"
 
13
 
 
14
// Marble
 
15
#include "RenderPlugin.h"
 
16
#include "MarbleDebug.h"
 
17
 
 
18
// Qt
 
19
#include <QtCore/QEvent>
 
20
#include <QtCore/QSize>
 
21
#include <QtCore/QVariant>
 
22
#include <QtGui/QAbstractItemView>
 
23
#include <QtGui/QMouseEvent>
 
24
#include <QtGui/QStandardItemModel>
 
25
#include <QtGui/QApplication>
 
26
#include <QtGui/QPainter>
 
27
#include <QtGui/QStandardItem>
 
28
 
 
29
using namespace Marble;
 
30
/* TRANSLATOR Marble::PluginItemDelegate */
 
31
 
 
32
const QSize iconSize( 16, 16 );
 
33
 
 
34
PluginItemDelegate::PluginItemDelegate( QAbstractItemView *view, QObject * parent )
 
35
    : QAbstractItemDelegate( parent )
 
36
{
 
37
    // Enable mouse tracking of itemview makes it possible to find when the mouse if moved
 
38
    // without pressed buttons.
 
39
    view->setMouseTracking( true );
 
40
}
 
41
 
 
42
PluginItemDelegate::~PluginItemDelegate()
 
43
{
 
44
}
 
45
 
 
46
void PluginItemDelegate::paint( QPainter *painter,
 
47
                                const QStyleOptionViewItem& option,
 
48
                                const QModelIndex& index ) const
 
49
{
 
50
    Q_ASSERT( index.isValid() );
 
51
    QRect rect = option.rect;
 
52
    QStyle *style = QApplication::style();
 
53
 
 
54
    painter->save();
 
55
 
 
56
    // Drawing the background
 
57
    QStyleOption background = option;
 
58
    style->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter );
 
59
 
 
60
    painter->translate( rect.topLeft() );
 
61
 
 
62
    // rect is now represented in item coordinates
 
63
    rect.moveTopLeft( QPoint( 0, 0 ) );
 
64
    // The point at the top left of the available drawing area.
 
65
    QPoint topLeft( 0, 0 );
 
66
    // The point at the top right of the available drawing area.
 
67
    QPoint topRight( rect.topRight() );
 
68
 
 
69
    QRect nameRect = rect;
 
70
    
 
71
    // Painting the checkbox
 
72
    QStyleOptionButton checkBox = checkboxOption( option, index, topLeft.x(), Qt::AlignLeft );
 
73
    painter->save();
 
74
    style->drawControl( QStyle::CE_CheckBox, &checkBox, painter );
 
75
    painter->restore();
 
76
 
 
77
    nameRect.setLeft( checkBox.rect.right() + 1 );
 
78
    
 
79
    // Painting the About Button
 
80
    if ( index.data( RenderPlugin::AboutDialogAvailable ).toBool() ) {
 
81
        QStyleOptionButton button = buttonOption( option, index, PluginItemDelegate::About,
 
82
                                                  topRight.x(), Qt::AlignRight );
 
83
        style->drawControl( QStyle::CE_PushButton, &button, painter );
 
84
        topRight -= QPoint( button.rect.width(), 0 );
 
85
    }
 
86
 
 
87
    // Painting the Configure Button
 
88
    if ( index.data( RenderPlugin::ConfigurationDialogAvailable ).toBool() ) {
 
89
        QStyleOptionButton button = buttonOption( option, index, PluginItemDelegate::Configure,
 
90
                                                  topRight.x(), Qt::AlignRight );
 
91
        style->drawControl( QStyle::CE_PushButton, &button, painter );
 
92
        topRight -= QPoint( button.rect.width(), 0 );
 
93
        
 
94
        nameRect.setRight( button.rect.left() -1 );
 
95
    }
 
96
 
 
97
    // Painting the Name string
 
98
    QString name = index.data( Qt::DisplayRole ).toString();
 
99
    
 
100
    style->drawItemText( painter,
 
101
                         nameRect,
 
102
                         Qt::AlignLeft | Qt::AlignVCenter,
 
103
                         option.palette,
 
104
                         true,
 
105
                         name );
 
106
 
 
107
    painter->restore();
 
108
}
 
109
 
 
110
QSize PluginItemDelegate::sizeHint( const QStyleOptionViewItem& option,
 
111
                                    const QModelIndex & index ) const
 
112
{
 
113
    QSize size;
 
114
 
 
115
    QStyleOptionViewItem opt = option;
 
116
    opt.rect = QRect( 0, 0, 0, 0 );
 
117
    QList<QSize> elementSize;
 
118
    QStyleOptionButton checkBox = checkboxOption( opt, index );
 
119
    elementSize.append( checkBox.rect.size() );
 
120
    QStyleOptionButton aboutButton = buttonOption( opt, index, PluginItemDelegate::About );
 
121
    elementSize.append( aboutButton.rect.size() );
 
122
    QStyleOptionButton configButton = buttonOption( opt, index, PluginItemDelegate::Configure );
 
123
    elementSize.append( configButton.rect.size() );
 
124
    elementSize.append( nameSize( index ) );
 
125
 
 
126
    foreach( const QSize& buttonSize, elementSize ) {
 
127
        if( buttonSize.height() > size.height() )
 
128
            size.setHeight( buttonSize.height() );
 
129
        size.setWidth( size.width() + buttonSize.width() );
 
130
    }
 
131
 
 
132
    return size;
 
133
}
 
134
 
 
135
void PluginItemDelegate::setAboutIcon( const QIcon& icon )
 
136
{
 
137
    m_aboutIcon = icon;
 
138
}
 
139
 
 
140
void PluginItemDelegate::setConfigIcon( const QIcon& icon )
 
141
{
 
142
    m_configIcon = icon;
 
143
}
 
144
 
 
145
bool PluginItemDelegate::editorEvent( QEvent *event,
 
146
                                      QAbstractItemModel *model,
 
147
                                      const QStyleOptionViewItem &option,
 
148
                                      const QModelIndex &index )
 
149
{
 
150
    Q_ASSERT(event);
 
151
    Q_ASSERT(model);
 
152
 
 
153
    if ( ( event->type() == QEvent::MouseButtonRelease )
 
154
         || ( event->type() == QEvent::MouseButtonDblClick )
 
155
         || ( event->type() == QEvent::MouseButtonPress )
 
156
         || ( event->type() == QEvent::MouseMove ) )
 
157
    {
 
158
        QMouseEvent *me = static_cast<QMouseEvent*>(event);
 
159
        QPoint mousePosition = me->pos() - option.rect.topLeft();
 
160
 
 
161
        if ( ( event->type() == QEvent::MouseMove )
 
162
             && !( me->buttons() & Qt::LeftButton ) )
 
163
        {
 
164
            // If the mouse moves around and no left button is pressed, no pushbutton is pressed
 
165
            // and no other event will be successful.
 
166
            m_aboutPressedPluginId.clear();
 
167
            m_configPressedPluginId.clear();
 
168
            return true;
 
169
        }
 
170
 
 
171
        // Handle checkbox
 
172
        QRect checkRect = checkboxOption( option, index, 0, Qt::AlignLeft ).rect;
 
173
        if ( checkRect.contains( mousePosition )
 
174
             && ( ( event->type() == QEvent::MouseButtonDblClick )
 
175
                   || ( event->type() == QEvent::MouseButtonRelease ) ) )
 
176
        {
 
177
            // make sure that the item is checkable
 
178
            Qt::ItemFlags flags = model->flags(index);
 
179
            if ( !( flags & Qt::ItemIsUserCheckable ) || !( option.state & QStyle::State_Enabled )
 
180
                || !( flags & Qt::ItemIsEnabled ) )
 
181
                return false;
 
182
 
 
183
            // make sure that we have a check state
 
184
            QVariant checkValue = index.data( Qt::CheckStateRole );
 
185
            if ( !checkValue.isValid() )
 
186
                return false;
 
187
 
 
188
            // eat the double click events inside the check rect
 
189
            if ( event->type() == QEvent::MouseButtonDblClick )
 
190
                return true;
 
191
 
 
192
            Qt::CheckState state = ( static_cast<Qt::CheckState>( checkValue.toInt() ) == Qt::Checked
 
193
                                     ? Qt::Unchecked : Qt::Checked );
 
194
            return model->setData(index, state, Qt::CheckStateRole);
 
195
        }
 
196
 
 
197
        if ( ( event->type() == QEvent::MouseMove )
 
198
             && !( me->buttons() & Qt::LeftButton ) )
 
199
        {
 
200
            m_aboutPressedPluginId.clear();
 
201
            m_configPressedPluginId.clear();
 
202
            return true;
 
203
        }
 
204
 
 
205
        QPoint topRight = option.rect.topRight();
 
206
 
 
207
        // Handle aboutButton
 
208
        // make sure we have a about button
 
209
        if ( index.data( RenderPlugin::AboutDialogAvailable ).toBool() ) {
 
210
            QRect aboutRect = buttonOption( option,
 
211
                                            index,
 
212
                                            PluginItemDelegate::About,
 
213
                                            topRight.x(),
 
214
                                            Qt::AlignRight ).rect;
 
215
            QString nameId = index.data( RenderPlugin::NameId ).toString();
 
216
            if ( aboutRect.contains( mousePosition ) ) {
 
217
                if ( event->type() == QEvent::MouseButtonDblClick )
 
218
                    return true;
 
219
                if ( event->type() == QEvent::MouseButtonPress ) {
 
220
                    m_aboutPressedPluginId = nameId;
 
221
                    m_configPressedPluginId.clear();
 
222
                    return true;
 
223
                }
 
224
                if ( event->type() == QEvent::MouseButtonRelease ) {
 
225
                    m_aboutPressedPluginId.clear();
 
226
                    m_configPressedPluginId.clear();
 
227
                    emit aboutPluginClicked( nameId );
 
228
                    return true;
 
229
                }
 
230
                if ( event->type() == QEvent::MouseMove ) {
 
231
                    if ( me->buttons() & Qt::LeftButton ) {
 
232
                        m_aboutPressedPluginId = nameId;
 
233
                        m_configPressedPluginId.clear();
 
234
                        return true;
 
235
                    }
 
236
                    else {
 
237
                        m_aboutPressedPluginId.clear();
 
238
                        m_configPressedPluginId.clear();
 
239
                        return true;
 
240
                    }
 
241
                }
 
242
            }
 
243
            else {
 
244
                // If the mouse is on the item and the mouse isn't above the button.
 
245
                // no about button is pressed.
 
246
                m_aboutPressedPluginId.clear();
 
247
            }
 
248
            topRight -= QPoint( aboutRect.width(), 0 );
 
249
        }
 
250
        else {
 
251
            // If we don't have an about dialog shown and the mouse is over this item,
 
252
            // no about button is pressed.
 
253
            m_aboutPressedPluginId.clear();
 
254
        }
 
255
 
 
256
        // Handle configButton
 
257
        // make sure we have config button
 
258
        if ( index.data( RenderPlugin::ConfigurationDialogAvailable ).toBool() ) {
 
259
            QRect configRect = buttonOption( option,
 
260
                                             index,
 
261
                                             PluginItemDelegate::Configure,
 
262
                                             topRight.x(),
 
263
                                             Qt::AlignRight ).rect;
 
264
            QString nameId = index.data( RenderPlugin::NameId ).toString();
 
265
            if( configRect.contains( mousePosition ) ) {
 
266
                if ( event->type() == QEvent::MouseButtonDblClick )
 
267
                    return true;
 
268
 
 
269
                if ( event->type() == QEvent::MouseButtonPress ) {
 
270
                    m_aboutPressedPluginId.clear();
 
271
                    m_configPressedPluginId = nameId;
 
272
                    return true;
 
273
                }
 
274
                if ( event->type() == QEvent::MouseButtonRelease ) {
 
275
                    m_aboutPressedPluginId.clear();
 
276
                    m_configPressedPluginId.clear();
 
277
                    emit configPluginClicked( nameId );
 
278
                    return true;
 
279
                }
 
280
                if ( event->type() == QEvent::MouseMove ) {
 
281
                    if ( me->buttons() & Qt::LeftButton ) {
 
282
                        m_aboutPressedPluginId.clear();
 
283
                        m_configPressedPluginId = nameId;
 
284
                        return true;
 
285
                    }
 
286
                    else {
 
287
                        m_aboutPressedPluginId.clear();
 
288
                        m_configPressedPluginId.clear();
 
289
                        return true;
 
290
                    }
 
291
                }
 
292
            }
 
293
            else {
 
294
                // If the mouse is on the item and the mouse isn't above the button.
 
295
                // no config button is pressed.
 
296
                m_configPressedPluginId.clear();
 
297
            }
 
298
 
 
299
            topRight -= QPoint( configRect.width(), 0 );
 
300
        }
 
301
        else {
 
302
            // If we don't have an config dialog shown and the mouse is over this item,
 
303
            // no config button is pressed.
 
304
            m_configPressedPluginId.clear();
 
305
        }
 
306
    }
 
307
 
 
308
    return false;
 
309
}
 
310
 
 
311
QStyleOptionButton PluginItemDelegate::checkboxOption( const QStyleOptionViewItem& option,
 
312
                                                       const QModelIndex& index,
 
313
                                                       int position,
 
314
                                                       Qt::AlignmentFlag alignment ) const
 
315
{
 
316
    QStyleOptionButton checkboxOption;
 
317
    if ( index.data( Qt::CheckStateRole ).toBool() )
 
318
        checkboxOption.state = option.state | QStyle::State_On;
 
319
    else
 
320
        checkboxOption.state = option.state | QStyle::State_Off;
 
321
    QSize size = QApplication::style()->sizeFromContents( QStyle::CT_CheckBox, &option, QSize() );
 
322
    if ( size.isEmpty() ) {
 
323
        // A checkbox has definitely a size != 0
 
324
        checkboxOption.rect.setSize( QSize( 22, 22 ) );
 
325
    }
 
326
    else {
 
327
        checkboxOption.rect.setSize( QSize( size.width(), size.height() ) );
 
328
    }
 
329
    checkboxOption.rect = alignRect( checkboxOption.rect, option.rect, position, alignment );
 
330
    return checkboxOption;
 
331
}
 
332
 
 
333
QStyleOptionButton PluginItemDelegate::buttonOption( const QStyleOptionViewItem& option,
 
334
                                                     const QModelIndex& index,
 
335
                                                     PluginItemDelegate::ButtonType type,
 
336
                                                     int position, 
 
337
                                                     Qt::AlignmentFlag alignment ) const
 
338
{
 
339
    QStyleOptionButton buttonOption;
 
340
    buttonOption.state = option.state;
 
341
    buttonOption.state &= ~QStyle::State_HasFocus;
 
342
 
 
343
    buttonOption.rect.setTopLeft( QPoint( 0, 0 ) );
 
344
    buttonOption.palette = option.palette;
 
345
    buttonOption.features = QStyleOptionButton::None;
 
346
 
 
347
    QSize contentSize;
 
348
    if ( type == PluginItemDelegate::About ) {
 
349
        if ( m_aboutIcon.isNull() ) {
 
350
            buttonOption.text = tr( "About" );
 
351
            contentSize = buttonOption.fontMetrics.size( 0, buttonOption.text ) + QSize( 4, 4 );
 
352
        }
 
353
        else {
 
354
            buttonOption.icon = m_aboutIcon;
 
355
            buttonOption.iconSize = iconSize;
 
356
            contentSize = iconSize;
 
357
        }
 
358
 
 
359
        if ( m_aboutPressedPluginId == index.data( RenderPlugin::NameId ).toString() ) {
 
360
            buttonOption.state |= QStyle::State_Sunken;
 
361
        }
 
362
    }
 
363
    else if ( type == PluginItemDelegate::Configure ) {
 
364
        if ( m_configIcon.isNull() ) {
 
365
            buttonOption.text = tr( "Configure" );
 
366
            contentSize = buttonOption.fontMetrics.size( 0, buttonOption.text ) + QSize( 4, 4 );
 
367
        }
 
368
        else {
 
369
            buttonOption.icon = m_configIcon;
 
370
            buttonOption.iconSize = iconSize;
 
371
            contentSize = iconSize;
 
372
        }
 
373
        if ( m_configPressedPluginId == index.data( RenderPlugin::NameId ).toString() ) {
 
374
            buttonOption.state |= QStyle::State_Sunken;
 
375
        }
 
376
    }
 
377
 
 
378
    QSize buttonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton,
 
379
                                                                &buttonOption,
 
380
                                                                contentSize );
 
381
    buttonOption.rect.setSize( buttonSize );
 
382
    buttonOption.rect = alignRect( buttonOption.rect, option.rect, position, alignment );
 
383
    return buttonOption;
 
384
}
 
385
 
 
386
QSize PluginItemDelegate::nameSize( const QModelIndex& index ) const
 
387
{
 
388
    QString name = index.data( Qt::DisplayRole ).toString();
 
389
    // FIXME: QApplication::fontMetrics() doesn't work for non-application fonts
 
390
    QSize nameSize( QApplication::fontMetrics().size( 0, name ) );
 
391
    return nameSize;
 
392
}
 
393
 
 
394
QRect PluginItemDelegate::alignRect( QRect object,
 
395
                                     QRect frame,
 
396
                                     int position,
 
397
                                     Qt::AlignmentFlag alignment ) const
 
398
{
 
399
    QRect rect = object;
 
400
    
 
401
    rect.setTopLeft( QPoint( 0, 0 ) );
 
402
    // Moves the object to the middle of the item.
 
403
    if ( rect.height() < frame.height() ) {
 
404
        rect.moveTop( ( frame.height() - rect.height() ) / 2 );
 
405
    }
 
406
 
 
407
    if ( alignment & Qt::AlignLeft ) {
 
408
        rect.moveLeft( position );
 
409
    }
 
410
    else if ( alignment & Qt::AlignRight ) {
 
411
        rect.moveRight( position );
 
412
    }
 
413
    
 
414
    return rect;
 
415
}
 
416
 
 
417
 
 
418
#include "PluginItemDelegate.moc"