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