better motif editor
[mussa.git] / qui / motif_editor / MotifEditorDelegate.cpp
1 #include "qui/motif_editor/MotifEditorDelegate.hpp"
2
3 #include <Qt>
4 #include <QCheckBox>
5 #include <QColorDialog>
6 #include <QEvent>
7 #include <QKeyEvent>
8 #include <QLineEdit>
9 #include <QPainter>
10
11 MotifEditorDelegate::MotifEditorDelegate(QWidget *parent) :
12   QItemDelegate(parent)
13 {
14 }
15
16 QWidget *MotifEditorDelegate::createEditor(
17   QWidget *parent, 
18   const QStyleOptionViewItem & /* option */,
19   const QModelIndex &index) const
20 {
21   QWidget *widget = 0;
22   switch(index.column()) {
23     // case MotifModel::EnabledCell is handled in editorEvent
24     // case MotifModel::ColorCell:
25     // both of these should be text boxes
26     case MotifModel::NameCell:
27     case MotifModel::SequenceCell:
28       widget = new QLineEdit(parent);
29       widget->installEventFilter(const_cast<MotifEditorDelegate*>(this));
30       break;
31     default:
32       break;
33   }
34   return widget;
35 }
36
37 //! check to see if our event is something that should "activate" our cell
38 static bool is_cell_activated(QEvent *event)
39 {
40   // if a mouse releases on us we can toggle
41   if (event->type() == QEvent::MouseButtonRelease) {
42     return true;
43   // if we're a keypress
44   } else if (event->type() == QEvent::KeyPress) {
45     // try to convert to a KeyEvent
46     QKeyEvent *key_event = dynamic_cast<QKeyEvent *>(event);
47     // if we've gotten our key event, did the use hit the enter/return key?
48     if (key_event) {
49       if (key_event->key() == Qt::Key_Enter or key_event->key() == Qt::Key_Return) {
50         return true;
51       }
52     }
53   } 
54   // all other cases don't toggle
55   return false;  
56 }
57 bool MotifEditorDelegate::editorEvent(
58        QEvent *event, 
59        QAbstractItemModel *model, 
60        const QStyleOptionViewItem &option, 
61        const QModelIndex & index )
62 {
63   switch (index.column()) {
64     case MotifModel::EnabledCell:
65       if (is_cell_activated(event)) {
66         QVariant value = index.model()->data(index, Qt::DisplayRole);
67         value = not value.toBool();
68         model->setData(index, value);
69         return true;  
70       }
71       break;
72     case MotifModel::ColorCell:
73       if (is_cell_activated(event)) {
74         QVariant value = index.model()->data(index, Qt::DisplayRole);
75         QColor old_color = value.value<QColor>();
76         QColor new_color = QColorDialog::getColor(old_color);
77         // color is not valid if user hit the cancel button on the color dialog
78         if (new_color.isValid()) {
79           model->setData(index, QVariant(new_color));
80         } else {
81           model->setData(index, QVariant(old_color));
82         }
83         return true;
84       }
85       break;
86     default:
87       break;
88   }            
89   return this->QItemDelegate::editorEvent(event, model, option, index);
90
91
92 void MotifEditorDelegate::setEditorData(
93   QWidget *editor, 
94   const QModelIndex &index) const
95 {
96   QVariant value = index.model()->data(index, Qt::DisplayRole);
97   switch(index.column()) {
98     // toggling MotifModel::EnabledCell is handled by editorEvent
99     // case MotifModel::ColorCell is handled by paint and editorEvent
100
101     // both of these should be text boxes
102     case MotifModel::NameCell:
103     case MotifModel::SequenceCell:
104       static_cast<QLineEdit*>(editor)->setText(value.toString());
105       break;
106     default:
107       break;
108   }
109 }
110
111 void MotifEditorDelegate::setModelData(
112   QWidget *editor, 
113   QAbstractItemModel *model,
114   const QModelIndex &index) const
115 {
116   QVariant value;
117   switch(index.column()) {
118     // both of these should be text boxes
119     case MotifModel::NameCell:
120     case MotifModel::SequenceCell:
121       value = static_cast<QLineEdit*>(editor)->text();
122       model->setData(index, value);  
123       break;
124     default:
125       break;
126   }  
127 }
128
129 struct painter_save_restore {
130   painter_save_restore(QPainter *p) { painter = p; painter->save(); }
131   ~painter_save_restore() { painter->restore(); }
132   QPainter *painter;
133 };
134
135 static void drawHighlightIfNeeded(QPainter *painter, const QStyleOptionViewItem &option)
136 {
137     if (option.state & QStyle::State_Selected) { 
138         painter->setBrush(option.palette.highlight());
139         painter->drawRect(option.rect);         
140     } 
141 }
142
143 void MotifEditorDelegate::paint(
144   QPainter * painter, 
145   const QStyleOptionViewItem & option, 
146   const QModelIndex & index ) const
147 {
148   painter_save_restore saved(painter);
149   
150   QVariant value = index.model()->data(index, Qt::DisplayRole);
151   switch(index.column()) {
152     case MotifModel::EnabledCell:
153     {
154       painter->setPen(Qt::NoPen);
155       drawHighlightIfNeeded(painter, option);
156       Qt::CheckState state = (value.toBool()) ? Qt::Checked : Qt::Unchecked;
157       this->QItemDelegate::drawCheck(painter, option, option.rect, state);
158     }
159     break;
160     case MotifModel::ColorCell:
161     {
162       painter->setPen(Qt::NoPen);
163       drawHighlightIfNeeded(painter, option);       
164       QColor color(value.value<QColor>());
165       painter->setBrush(QBrush(color));
166       painter->drawRoundRect(option.rect, 60, 60);
167     }  
168     break;
169     default:
170       this->QItemDelegate::paint(painter, option, index);
171     break;
172   }
173 }
174
175 void MotifEditorDelegate::updateEditorGeometry(
176   QWidget *editor,
177   const QStyleOptionViewItem &option, 
178   const QModelIndex &index) const
179 {
180   editor->setGeometry(option.rect);
181 }
182