1 /*
2
3 Copyright (c) 2003-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33 #include "customwidgets.h"
34
35 #include <cstdlib>
36 #include <cctype>
37
38 #include "qtgettext.h"
39
40 #include <QtCore/QPointer>
41 #if QT_VERSION < 0x050000
42 # include <QtGui/QFileDialog>
43 # include <QtGui/QHeaderView>
44 # include <QtGui/QLabel>
45 # include <QtGui/QPushButton>
46 # include <QtGui/QTableWidget>
47 # include <QtGui/QTreeWidget>
48 # include <QtGui/QTreeWidgetItem>
49 # include <QtGui/QVBoxLayout>
50 #else
51 # include <QtWidgets/QFileDialog>
52 # include <QtWidgets/QHeaderView>
53 # include <QtWidgets/QLabel>
54 # include <QtWidgets/QPushButton>
55 # include <QtWidgets/QTableWidget>
56 # include <QtWidgets/QTreeWidget>
57 # include <QtWidgets/QTreeWidgetItem>
58 # include <QtWidgets/QVBoxLayout>
59 #endif
60
_FU8(const char string[])61 inline static QString _FU8( const char string[] )
62 {
63 return QString::fromUtf8(string);
64 }
65
66 static const int DEBUG_KEY_EDIT = 0;
67 static QString unicodeKeyToSymStr( QChar c );
68
CustomCheckBox(struct uim_custom * c,QWidget * parent)69 CustomCheckBox::CustomCheckBox( struct uim_custom *c, QWidget *parent )
70 : QCheckBox( parent ),
71 UimCustomItemIface( c )
72 {
73 connect( this, SIGNAL(toggled(bool)),
74 this, SLOT(slotCustomToggled(bool)) );
75
76 update();
77 }
78
update()79 void CustomCheckBox::update()
80 {
81 if( !m_custom || m_custom->type != UCustom_Bool )
82 return;
83
84 setText( _FU8(m_custom->label) );
85 setChecked( m_custom->value->as_bool );
86
87 setEnabled( m_custom->is_active );
88 }
89
setDefault()90 void CustomCheckBox::setDefault()
91 {
92 m_custom->value->as_bool = m_custom->default_value->as_bool;
93
94 setCustom( m_custom );
95 update();
96 }
97
slotCustomToggled(bool check)98 void CustomCheckBox::slotCustomToggled( bool check )
99 {
100 Q_ASSERT( m_custom->type == UCustom_Bool );
101
102 m_custom->value->as_bool = check;
103 setCustom( m_custom );
104 }
105
106 //----------------------------------------------------------------------------------------
CustomSpinBox(struct uim_custom * c,QWidget * parent)107 CustomSpinBox::CustomSpinBox( struct uim_custom *c, QWidget *parent )
108 : QSpinBox( parent ),
109 UimCustomItemIface( c )
110 {
111 setMinimum( c->range->as_int.min );
112 setMaximum( c->range->as_int.max );
113 setSingleStep( 1 );
114 connect( this, SIGNAL(valueChanged(int)),
115 this, SLOT(slotCustomValueChanged(int)) );
116 update();
117 }
118
update()119 void CustomSpinBox::update()
120 {
121 if( !m_custom || m_custom->type != UCustom_Int )
122 return;
123
124 setValue( m_custom->value->as_int );
125 setMinimum( m_custom->range->as_int.min );
126 setMaximum( m_custom->range->as_int.max );
127
128 /* sync with Label */
129 parentWidget()->setEnabled( m_custom->is_active );
130 }
131
setDefault()132 void CustomSpinBox::setDefault()
133 {
134 m_custom->value->as_int = m_custom->default_value->as_int;
135
136 setCustom( m_custom );
137 update();
138 }
139
slotCustomValueChanged(int value)140 void CustomSpinBox::slotCustomValueChanged( int value )
141 {
142 Q_ASSERT( m_custom->type == UCustom_Int );
143
144 m_custom->value->as_int = value;
145 setCustom( m_custom );
146 }
147
148 //----------------------------------------------------------------------------------------
CustomLineEdit(struct uim_custom * c,QWidget * parent)149 CustomLineEdit::CustomLineEdit( struct uim_custom *c, QWidget *parent )
150 : QLineEdit( parent ),
151 UimCustomItemIface( c )
152 {
153 connect( this, SIGNAL(textChanged(const QString&)),
154 this, SLOT(slotCustomTextChanged(const QString&)) );
155
156 setAttribute( Qt::WA_InputMethodEnabled, false );
157 update();
158 }
159
update()160 void CustomLineEdit::update()
161 {
162 if( !m_custom || m_custom->type != UCustom_Str )
163 return;
164
165 setText( _FU8(m_custom->value->as_str) );
166
167 /* sync with Label */
168 parentWidget()->setEnabled( m_custom->is_active );
169 }
170
setDefault()171 void CustomLineEdit::setDefault()
172 {
173 free( m_custom->value->as_str );
174 m_custom->value->as_str = strdup( m_custom->default_value->as_str );
175
176 setCustom( m_custom );
177 update();
178 }
179
slotCustomTextChanged(const QString & text)180 void CustomLineEdit::slotCustomTextChanged( const QString &text )
181 {
182 Q_ASSERT( m_custom->type == UCustom_Str );
183
184 free( m_custom->value->as_str );
185 m_custom->value->as_str = strdup( text.toUtf8().data() );
186
187 setCustom( m_custom );
188 }
189
190 //----------------------------------------------------------------------------------------
CustomPathnameEdit(struct uim_custom * c,QWidget * parent)191 CustomPathnameEdit::CustomPathnameEdit( struct uim_custom *c, QWidget *parent )
192 : QFrame( parent ),
193 UimCustomItemIface( c )
194 {
195 const char *button;
196
197 m_lineEdit = new QLineEdit( this );
198 connect( m_lineEdit, SIGNAL(textChanged(const QString &)),
199 this, SLOT(slotCustomTextChanged(const QString &)) );
200
201 m_fileButton = new QPushButton( this );
202 /* Since both pathname type opens the file dialog to select an item rather
203 * than open it, the label should always be "Select..." here. The type is
204 * obvious for uses even if the button label does not indicate
205 * it. Information about the action the button causes is more important.
206 * -- YamaKen 2006-01-21 */
207 switch (m_custom->value->as_pathname->type) {
208 case UCustomPathnameType_Directory:
209 button = N_( "Select..." );
210 break;
211 case UCustomPathnameType_RegularFile:
212 default:
213 button = N_( "Select..." );
214 break;
215 }
216 m_fileButton->setText( mygettext(button) );
217 connect( m_fileButton, SIGNAL(clicked()),
218 this, SLOT(slotPathnameButtonClicked()) );
219
220 QHBoxLayout *layout = new QHBoxLayout;
221 layout->setMargin( 0 );
222 layout->setSpacing( 3 );
223 layout->addWidget( m_lineEdit );
224 layout->addWidget( m_fileButton );
225
226 setLayout( layout );
227
228 update();
229 }
230
update()231 void CustomPathnameEdit::update()
232 {
233 if( !m_custom || m_custom->type != UCustom_Pathname )
234 return;
235
236 m_lineEdit->setText( _FU8(m_custom->value->as_pathname->str) );
237
238 /* sync with Label */
239 parentWidget()->setEnabled( m_custom->is_active );
240 }
241
setDefault()242 void CustomPathnameEdit::setDefault()
243 {
244 free( m_custom->value->as_pathname->str );
245 m_custom->value->as_pathname->str = strdup( m_custom->default_value->as_pathname->str );
246 m_custom->value->as_pathname->type = m_custom->default_value->as_pathname->type;
247
248 setCustom( m_custom );
249 update();
250 }
251
slotPathnameButtonClicked()252 void CustomPathnameEdit::slotPathnameButtonClicked()
253 {
254 m_fileDialog = new QFileDialog( this, _("Specify file") );
255
256 switch (m_custom->value->as_pathname->type) {
257 case UCustomPathnameType_Directory:
258 m_fileDialog->setFileMode( QFileDialog::Directory );
259 break;
260 case UCustomPathnameType_RegularFile:
261 default:
262 m_fileDialog->setFileMode( QFileDialog::ExistingFile );
263 break;
264 }
265 if ( m_fileDialog->exec() == QDialog::Accepted )
266 {
267 QString fileName = m_fileDialog->selectedFiles()[ 0 ];
268 m_lineEdit->setText( fileName );
269 }
270 delete m_fileDialog;
271 }
272
slotCustomTextChanged(const QString & text)273 void CustomPathnameEdit::slotCustomTextChanged( const QString & text )
274 {
275 Q_ASSERT( m_custom->type == UCustom_Pathname );
276
277 free( m_custom->value->as_pathname->str );
278 m_custom->value->as_pathname->str = strdup( text.toUtf8().data() );
279
280 setCustom( m_custom );
281 }
282
283 //----------------------------------------------------------------------------------------
CustomChoiceCombo(struct uim_custom * c,QWidget * parent)284 CustomChoiceCombo::CustomChoiceCombo( struct uim_custom *c, QWidget *parent )
285 : QComboBox( parent ),
286 UimCustomItemIface( c )
287 {
288 setEditable( false );
289 connect( this, SIGNAL(activated(int)),
290 this, SLOT(slotActivated(int)) );
291
292 update();
293 }
294
update()295 void CustomChoiceCombo::update()
296 {
297 if( !m_custom || m_custom->type != UCustom_Choice )
298 return;
299
300 clear();
301 char *default_symbol = m_custom->value->as_choice->symbol;
302 int default_index = -1;
303 int index = 0;
304 struct uim_custom_choice **item = m_custom->range->as_choice.valid_items;
305 while( *item )
306 {
307 int count = this->count();
308 insertItem( count, _FU8((*item)->label) ); // insert item at last
309
310 if( QString::compare( default_symbol, (*item)->symbol ) == 0 )
311 default_index = index;
312
313 index++;
314 item++;
315 }
316 setCurrentIndex( default_index );
317
318 /* sync with Label */
319 parentWidget()->setEnabled( m_custom->is_active );
320 }
321
setDefault()322 void CustomChoiceCombo::setDefault()
323 {
324 free( m_custom->value->as_choice->symbol );
325 free( m_custom->value->as_choice->label );
326 free( m_custom->value->as_choice->desc );
327
328 m_custom->value->as_choice->symbol = strdup( m_custom->default_value->as_choice->symbol );
329 m_custom->value->as_choice->label = strdup( m_custom->default_value->as_choice->label );
330 m_custom->value->as_choice->desc = strdup( m_custom->default_value->as_choice->desc );
331
332 setCustom( m_custom );
333 update();
334 }
335
slotActivated(int index)336 void CustomChoiceCombo::slotActivated( int index )
337 {
338 Q_ASSERT( m_custom->type == UCustom_Choice );
339
340 struct uim_custom_choice **valid_items = m_custom->range->as_choice.valid_items;
341 struct uim_custom_choice *choice = 0;
342 if( valid_items )
343 {
344 for( int i = 0; valid_items[i]; i++ )
345 {
346 if( i == index )
347 choice = valid_items[i];
348 }
349 }
350
351 free( m_custom->value->as_choice->symbol );
352 free( m_custom->value->as_choice->label );
353 free( m_custom->value->as_choice->desc );
354
355 if ( choice ) {
356 m_custom->value->as_choice->symbol = strdup( choice->symbol );
357 m_custom->value->as_choice->label = strdup( choice->label );
358 m_custom->value->as_choice->desc = strdup( choice->desc );
359 } else {
360 m_custom->value->as_choice->symbol = strdup( "" );
361 m_custom->value->as_choice->label = strdup( "" );
362 m_custom->value->as_choice->desc = strdup( "" );
363 }
364
365 setCustom( m_custom );
366 }
367
368 //----------------------------------------------------------------------------------------
CustomOrderedListEdit(struct uim_custom * c,QWidget * parent)369 CustomOrderedListEdit::CustomOrderedListEdit( struct uim_custom *c, QWidget *parent )
370 : QFrame( parent ),
371 UimCustomItemIface( c )
372 {
373
374 m_lineEdit = new QLineEdit( this );
375 m_lineEdit->setAttribute( Qt::WA_InputMethodEnabled, false );
376 m_lineEdit->setReadOnly( true );
377
378 m_editButton = new QPushButton( this );
379 m_editButton->setText( _("Edit...") );
380 connect( m_editButton, SIGNAL(clicked()),
381 this, SLOT(slotEditButtonClicked()) );
382
383 QHBoxLayout *layout = new QHBoxLayout;
384 layout->setMargin( 0 );
385 layout->setSpacing( 3 );
386 layout->addWidget( m_lineEdit );
387 layout->addWidget( m_editButton );
388
389 setLayout( layout );
390
391 update();
392 }
393
update()394 void CustomOrderedListEdit::update()
395 {
396 if( !m_custom || m_custom->type != UCustom_OrderedList )
397 return;
398
399 updateText();
400
401 /* sync with Label */
402 parentWidget()->setEnabled( m_custom->is_active );
403 }
404
setDefault()405 void CustomOrderedListEdit::setDefault()
406 {
407 /* free old items */
408 int num = 0;
409 for( num = 0; m_custom->value->as_olist[num]; num++ )
410 ;
411
412 for( int i = 0; i < num; i++ )
413 {
414 free( m_custom->value->as_olist[i]->symbol );
415 free( m_custom->value->as_olist[i]->label );
416 free( m_custom->value->as_olist[i]->desc );
417 free( m_custom->value->as_olist[i] );
418 }
419
420 /* copy default_value to value */
421 int default_num = 0;
422 for( default_num = 0; m_custom->default_value->as_olist[default_num]; default_num++ )
423 ;
424
425 m_custom->value->as_olist = (struct uim_custom_choice **)realloc( m_custom->value->as_olist,
426 sizeof(struct uim_custom_choice *) * (default_num + 1) );
427
428 for( int i = 0; i < default_num; i++ )
429 {
430 struct uim_custom_choice *default_item = m_custom->default_value->as_olist[i];
431 struct uim_custom_choice *item = (struct uim_custom_choice *)malloc(sizeof(struct uim_custom_choice));
432
433 item->symbol = default_item->symbol ? strdup(default_item->symbol) : 0;
434 item->label = default_item->label ? strdup(default_item->label) : 0;
435 item->desc = default_item->desc ? strdup(default_item->desc) : 0;
436
437 m_custom->value->as_olist[i] = item;
438 }
439 m_custom->value->as_olist[default_num] = 0; /* NULL-terminated */
440
441 setCustom( m_custom );
442 initPtrList();
443 update();
444 }
445
initPtrList()446 void CustomOrderedListEdit::initPtrList()
447 {
448 m_itemList.clear();
449 m_validItemList.clear();
450
451 if( m_custom->value->as_olist )
452 {
453 struct uim_custom_choice *item = 0;
454 int i = 0;
455 for( item = m_custom->value->as_olist[0], i = 0;
456 item;
457 item = m_custom->value->as_olist[++i] )
458 {
459 m_itemList.append( item );
460 }
461 }
462
463 if( m_custom->value->as_olist && m_custom->range->as_olist.valid_items )
464 {
465 struct uim_custom_choice *item = 0;
466 int i = 0;
467 for( item = m_custom->range->as_olist.valid_items[0], i = 0;
468 item;
469 item = m_custom->range->as_olist.valid_items[++i] )
470 {
471 m_validItemList.append( item );
472 }
473 }
474 }
475
slotEditButtonClicked()476 void CustomOrderedListEdit::slotEditButtonClicked()
477 {
478 OListEditForm *d = new OListEditForm( this );
479 d->setWindowTitle( _FU8( m_custom->label ) );
480 initPtrList();
481
482 /*
483 * Adding Enabled Items
484 */
485 foreach( const struct uim_custom_choice *item, m_itemList )
486 {
487 d->addCheckItem( true, _FU8(item->label) );
488 }
489 /*
490 * Adding Disabled Items
491 */
492 foreach ( const struct uim_custom_choice *valid_item, m_validItemList )
493 {
494 /* Exclude Enabled Item */
495 bool isActive = false;
496 foreach ( const struct uim_custom_choice *item, m_itemList )
497 {
498 if( QString::compare( valid_item->symbol, item->symbol ) == 0 )
499 {
500 isActive = true;
501 break;
502 }
503 }
504
505 if( isActive == false )
506 {
507 d->addCheckItem( false, _FU8(valid_item->label) );
508 }
509 }
510
511 /* Exec Dialog */
512 if( d->exec() == OListEditForm::Accepted )
513 {
514 /* search active item's ptr, realloc it, and store in activeItemList */
515 QList<struct uim_custom_choice *> activeItemList;
516
517 QStringList activeItemLabelList = d->activeItemLabels();
518 for( int i = 0; i < activeItemLabelList.count(); i++ )
519 {
520 struct uim_custom_choice *item = 0;
521 int j = 0;
522 for( item = m_custom->range->as_olist.valid_items[0], j = 0;
523 item;
524 item = m_custom->range->as_olist.valid_items[++j] )
525 {
526 if( QString::compare( activeItemLabelList[i], _FU8(item->label) ) == 0 )
527 {
528 /* allocate new struct because we will free the old struct */
529 struct uim_custom_choice *activeItem = (struct uim_custom_choice *)malloc(sizeof(struct uim_custom_choice));
530 activeItem->symbol = item->symbol ? strdup(item->symbol) : 0;
531 activeItem->label = item->label ? strdup(item->label) : 0;
532 activeItem->desc = item->desc ? strdup(item->desc) : 0;
533 activeItemList.append( activeItem );
534 break;
535 }
536 }
537 }
538
539 /* free old items */
540 for( int i = 0; i < m_itemList.count(); i++ )
541 {
542 free( m_custom->value->as_olist[i]->symbol );
543 free( m_custom->value->as_olist[i]->label );
544 free( m_custom->value->as_olist[i]->desc );
545 free( m_custom->value->as_olist[i] );
546 }
547
548 /* create null-terminated new olist */
549 m_custom->value->as_olist = (struct uim_custom_choice **)realloc( m_custom->value->as_olist,
550 sizeof(struct uim_custom_choice *) * (activeItemList.count() + 1) );
551 for( int i = 0; i < activeItemList.count(); i++ )
552 {
553 m_custom->value->as_olist[i] = activeItemList.at(i);
554 }
555 m_custom->value->as_olist[activeItemList.count()] = 0;
556
557 /* save */
558 setCustom( m_custom );
559
560 /* reload */
561 update();
562 }
563
564 delete d;
565 }
566
updateText()567 void CustomOrderedListEdit::updateText()
568 {
569 QString str;
570 if( m_custom->value->as_olist )
571 {
572 struct uim_custom_choice *item = 0;
573 int i = 0;
574 for( item = m_custom->value->as_olist[0], i = 0;
575 item;
576 item = m_custom->value->as_olist[++i] )
577 {
578 if( i != 0 )
579 str.append(", ");
580 str.append( _FU8(item->label) );
581 }
582 }
583 m_lineEdit->setText( str );
584 }
585
OListEditForm(QWidget * parent)586 OListEditForm::OListEditForm( QWidget *parent ) : OListEditFormBase( parent )
587 {
588 m_listView->setRootIsDecorated( false );
589 connect( m_upButton, SIGNAL(clicked()),
590 this, SLOT(upItem()) );
591 connect( m_downButton, SIGNAL(clicked()),
592 this, SLOT(downItem()) );
593 }
594
~OListEditForm()595 OListEditForm::~OListEditForm()
596 {
597 }
598
addCheckItem(bool isActive,const QString & str)599 void OListEditForm::addCheckItem( bool isActive, const QString &str )
600 {
601 QTreeWidgetItem *item = new QTreeWidgetItem( QStringList() << str );
602 m_listView->addTopLevelItem( item );
603
604 if( item )
605 item->setCheckState( 0, isActive ? Qt::Checked : Qt::Unchecked );
606 }
607
upItem()608 void OListEditForm::upItem()
609 {
610 QList<QTreeWidgetItem *> items = m_listView->selectedItems();
611 if ( items.isEmpty() )
612 return;
613 QTreeWidgetItem *item = items[ 0 ];
614 int index = m_listView->indexOfTopLevelItem( item );
615 if ( index == 0 )
616 return;
617 m_listView->takeTopLevelItem( index );
618 m_listView->insertTopLevelItem ( index - 1, item );
619 m_listView->setCurrentItem( item );
620 }
621
downItem()622 void OListEditForm::downItem()
623 {
624 QList<QTreeWidgetItem *> items = m_listView->selectedItems();
625 if ( items.isEmpty() )
626 return;
627 QTreeWidgetItem *item = items[ 0 ];
628 int index = m_listView->indexOfTopLevelItem( item );
629 if ( index == m_listView->topLevelItemCount() - 1 )
630 return;
631 m_listView->takeTopLevelItem( index );
632 m_listView->insertTopLevelItem ( index + 1, item );
633 m_listView->setCurrentItem( item );
634 }
635
activeItemLabels() const636 QStringList OListEditForm::activeItemLabels() const
637 {
638 QStringList activeItemLabelList;
639 for ( int i = 0; i < m_listView->topLevelItemCount(); i++)
640 {
641 QTreeWidgetItem *item = m_listView->topLevelItem( i );
642 if ( item->checkState( 0 ) == Qt::Checked )
643 activeItemLabelList << item->text ( 0 );
644 }
645 return activeItemLabelList;
646 }
647
648 //----------------------------------------------------------------------------------------
CustomKeyEdit(struct uim_custom * c,QWidget * parent)649 CustomKeyEdit::CustomKeyEdit( struct uim_custom *c, QWidget *parent )
650 : QFrame( parent ),
651 UimCustomItemIface( c )
652 {
653 m_lineEdit = new QLineEdit( this );
654 m_lineEdit->setAttribute( Qt::WA_InputMethodEnabled, false );
655 m_lineEdit->setReadOnly( true );
656
657 m_editButton = new QPushButton( this );
658 m_editButton->setText( _("Edit...") );
659 connect( m_editButton, SIGNAL(clicked()),
660 this, SLOT(slotKeyButtonClicked()) );
661
662 QHBoxLayout *layout = new QHBoxLayout;
663 layout->setMargin( 0 );
664 layout->setSpacing( 3 );
665 layout->addWidget( m_lineEdit );
666 layout->addWidget( m_editButton );
667
668 setLayout( layout );
669
670 update();
671 }
672
update()673 void CustomKeyEdit::update()
674 {
675 if( !m_custom || m_custom->type != UCustom_Key )
676 return;
677
678 updateText();
679
680 /* sync with Label */
681 parentWidget()->setEnabled( m_custom->is_active );
682 }
683
updateText()684 void CustomKeyEdit::updateText()
685 {
686 QString str;
687 if (m_custom->value->as_key) {
688 struct uim_custom_key *key = 0;
689 int i = 0;
690 for (key = m_custom->value->as_key[0], i = 0;
691 key;
692 key = m_custom->value->as_key[++i])
693 {
694 if( i != 0 )
695 str.append(", ");
696 str.append( key->literal );
697 }
698 } else {
699 /* error message */
700 }
701 m_lineEdit->setText( str );
702 }
703
704
setDefault()705 void CustomKeyEdit::setDefault()
706 {
707 /* free old items */
708 int num = 0;
709 for( num = 0; m_custom->value->as_key[num]; num++ )
710 ;
711
712 for( int i = 0; i < num; i++ )
713 {
714 free( m_custom->value->as_key[i]->literal );
715 free( m_custom->value->as_key[i]->label );
716 free( m_custom->value->as_key[i]->desc );
717 free( m_custom->value->as_key[i] );
718 }
719
720 /* copy default_value to value */
721 int default_num = 0;
722 for( default_num = 0; m_custom->default_value->as_key[default_num]; default_num++ )
723 ;
724
725 m_custom->value->as_key = (struct uim_custom_key **)realloc( m_custom->value->as_key,
726 sizeof(struct uim_custom_key *) * (default_num + 1) );
727
728 for( int i = 0; i < default_num; i++ )
729 {
730 struct uim_custom_key *default_item = m_custom->default_value->as_key[i];
731 struct uim_custom_key *item = (struct uim_custom_key *)malloc(sizeof(struct uim_custom_key));
732
733 item->type = default_item->type;
734 item->editor_type = default_item->editor_type;
735 item->literal = default_item->literal ? strdup(default_item->literal) : 0;
736 item->label = default_item->label ? strdup(default_item->label) : 0;
737 item->desc = default_item->desc ? strdup(default_item->desc) : 0;
738
739 m_custom->value->as_key[i] = item;
740 }
741 m_custom->value->as_key[default_num] = 0; /* NULL-terminated */
742
743 setCustom( m_custom );
744 update();
745 }
746
slotKeyButtonClicked()747 void CustomKeyEdit::slotKeyButtonClicked()
748 {
749 KeyEditForm *d = new KeyEditForm( this );
750 d->setWindowTitle(
751 _( "%1 - key configuration" ).arg( _FU8( m_custom->label ) ) );
752
753 /* add items */
754 QString str;
755 if (m_custom->value->as_key) {
756 struct uim_custom_key *key = 0;
757 int i = 0;
758 for (key = m_custom->value->as_key[0], i = 0;
759 key;
760 key = m_custom->value->as_key[++i])
761 {
762 d->addKeyItem( key->literal );
763 }
764 }
765
766 if( d->exec() == KeyEditForm::Accepted )
767 {
768 const QStringList keyStrList = d->getKeyStrList();
769
770 /* free old items */
771 int num = 0;
772 for( num = 0; m_custom->value->as_key[num]; num++ )
773 ;
774
775 for( int i = 0; i < num; i++ )
776 {
777 free( m_custom->value->as_key[i]->literal );
778 free( m_custom->value->as_key[i]->label );
779 free( m_custom->value->as_key[i]->desc );
780 free( m_custom->value->as_key[i] );
781 }
782
783
784 /* add new items */
785 num = keyStrList.count();
786 m_custom->value->as_key = (struct uim_custom_key **)realloc( m_custom->value->as_key,
787 sizeof(struct uim_custom_key *) * (num + 1) );
788
789 for( int i = 0; i < num; i++ )
790 {
791 const char *keystr = keyStrList[i].toLatin1().data();
792
793 struct uim_custom_key *item = (struct uim_custom_key *)malloc(sizeof(struct uim_custom_key));
794 item->type = UCustomKey_Regular;
795 item->editor_type = UCustomKeyEditor_Basic;
796 item->literal = strdup( keystr );
797 item->label = strdup( "" );
798 item->desc = strdup( "" );
799
800 m_custom->value->as_key[i] = item;
801 }
802 m_custom->value->as_key[num] = 0;
803
804 setCustom( m_custom );
805 update();
806 }
807
808 delete d;
809 }
810
KeyEditForm(QWidget * parent)811 KeyEditForm::KeyEditForm( QWidget *parent ) : KeyEditFormBase( parent )
812 {
813 m_listView->setRootIsDecorated( false );
814 m_removeButton->setEnabled( false );
815 m_editButton->setEnabled( false );
816
817 connect( m_addButton, SIGNAL(clicked()),
818 this, SLOT(slotAddClicked()) );
819 connect( m_removeButton, SIGNAL(clicked()),
820 this, SLOT(slotRemoveClicked()) );
821 connect( m_editButton, SIGNAL(clicked()),
822 this, SLOT(slotEditClicked()) );
823
824 connect( m_listView, SIGNAL(itemSelectionChanged()),
825 this, SLOT(slotItemSelectionChanged()) );
826 }
827
~KeyEditForm()828 KeyEditForm::~KeyEditForm()
829 {
830 }
831
addKeyItem(const QString & str)832 void KeyEditForm::addKeyItem( const QString &str )
833 {
834 QTreeWidgetItem *item = new QTreeWidgetItem( QStringList() << str );
835 m_listView->addTopLevelItem( item );
836 }
837
getKeyStrList()838 const QStringList KeyEditForm::getKeyStrList()
839 {
840 QStringList keyStrList;
841 for ( int i = 0; i < m_listView->topLevelItemCount(); i++)
842 {
843 keyStrList << m_listView->topLevelItem( i )->text ( 0 );
844 }
845 return keyStrList;
846 }
847
slotAddClicked()848 void KeyEditForm::slotAddClicked()
849 {
850 QPointer<KeyGrabDialog> d = new KeyGrabDialog( this );
851 if( d->exec() == KeyGrabDialog::Accepted )
852 {
853 QString keystr = d->getKeyStr();
854 if( !keystr.isEmpty() )
855 {
856 addKeyItem( keystr );
857 }
858 }
859 delete d;
860 }
861
slotRemoveClicked()862 void KeyEditForm::slotRemoveClicked()
863 {
864 QList<QTreeWidgetItem *> selectedItems = m_listView->selectedItems();
865 if( !selectedItems.isEmpty() )
866 {
867 m_listView->takeTopLevelItem(
868 m_listView->indexOfTopLevelItem( selectedItems[ 0 ] ) );
869 }
870 }
871
slotEditClicked()872 void KeyEditForm::slotEditClicked()
873 {
874 QList<QTreeWidgetItem *> selectedItems = m_listView->selectedItems();
875 if( selectedItems.isEmpty() )
876 return;
877 QPointer<KeyGrabDialog> d = new KeyGrabDialog( this );
878 if( d->exec() == KeyGrabDialog::Accepted )
879 {
880 QString keystr = d->getKeyStr();
881 if( !keystr.isEmpty() )
882 {
883 selectedItems[ 0 ]->setText( 0, keystr );
884 }
885 }
886 delete d;
887 }
888
slotItemSelectionChanged()889 void KeyEditForm::slotItemSelectionChanged()
890 {
891 QList<QTreeWidgetItem *> selectedItems = m_listView->selectedItems();
892 if( !selectedItems.isEmpty() )
893 {
894 m_removeButton->setEnabled( true );
895 m_editButton->setEnabled( true );
896 }
897 else
898 {
899 m_removeButton->setEnabled( false );
900 m_editButton->setEnabled( false );
901 }
902 }
903
KeyGrabDialog(QWidget * parent)904 KeyGrabDialog::KeyGrabDialog( QWidget *parent )
905 : QDialog( parent ),
906 pressed_keyval( 0 ),
907 pressed_keystate( Qt::NoModifier ),
908 pressed_unichar ( 0 )
909 {
910 QLabel *l = new QLabel( _("Press keys to grab (e.g. <Control>a)"), this );
911
912 QVBoxLayout *vboxLayout = new QVBoxLayout( this );
913 vboxLayout->addWidget( l );
914
915 setWindowTitle( _("Key Grab Dialog") );
916 }
917
keyPressEvent(QKeyEvent * e)918 void KeyGrabDialog::keyPressEvent( QKeyEvent *e )
919 {
920 pressed_keyval = e->key();
921 pressed_keystate = e->modifiers();
922 pressed_unichar = e->text().at(0);
923 }
924
keyReleaseEvent(QKeyEvent * e)925 void KeyGrabDialog::keyReleaseEvent( QKeyEvent *e )
926 {
927 Q_UNUSED( e )
928 // create keystr
929 setKeyStr();
930
931 // end this dialog
932 accept();
933 }
934
setKeyStr()935 void KeyGrabDialog::setKeyStr()
936 {
937 QString keystr;
938 int keyval = pressed_keyval;
939 Qt::KeyboardModifiers mod = pressed_keystate;
940
941 /*
942 * Ignore Shift modifier for printable char keys for
943 * easy-to-recognize key configuration. uim-custom performs
944 * implicit shift key encoding/decoding appropriately.
945 */
946 if( ((keyval >= 256) || !isgraph(keyval)) &&
947 (mod & Qt::ShiftModifier) )
948 keystr += "<Shift>";
949 if( mod & Qt::ControlModifier )
950 keystr += "<Control>";
951 if( mod & Qt::AltModifier )
952 keystr += "<Alt>";
953 if( mod & Qt::MetaModifier )
954 keystr += "<Meta>";
955
956 switch( keyval ) {
957 case Qt::Key_Space:
958 keystr += "space";
959 break;
960 case Qt::Key_Backspace:
961 keystr += "backspace";
962 break;
963 case Qt::Key_Delete:
964 keystr += "delete";
965 break;
966 case Qt::Key_Insert:
967 keystr += "insert";
968 break;
969 case Qt::Key_Escape:
970 keystr += "escape";
971 break;
972 case Qt::Key_Tab:
973 keystr += "tab";
974 break;
975 case Qt::Key_Return:
976 keystr += "return";
977 break;
978 case Qt::Key_Left:
979 keystr += "left";
980 break;
981 case Qt::Key_Up:
982 keystr += "up";
983 break;
984 case Qt::Key_Right:
985 keystr += "right";
986 break;
987 case Qt::Key_Down:
988 keystr += "down";
989 break;
990 case Qt::Key_PageUp:
991 keystr += "prior";
992 break;
993 case Qt::Key_PageDown:
994 keystr += "next";
995 break;
996 case Qt::Key_Home:
997 keystr += "home";
998 break;
999 case Qt::Key_End:
1000 keystr += "end";
1001 break;
1002 #ifdef QT4_IMMODULE
1003 case Qt::Key_Multi_key:
1004 keystr += "Multi_key";
1005 break;
1006 case Qt::Key_Codeinput:
1007 keystr += "codeinput";
1008 break;
1009 case Qt::Key_SingleCandidate:
1010 keystr += "single-candidate";
1011 break;
1012 case Qt::Key_MultipleCandidate:
1013 keystr += "multiple-candidate";
1014 break;
1015 case Qt::Key_PreviousCandidate:
1016 keystr += "previous-candidate";
1017 break;
1018 case Qt::Key_Mode_switch:
1019 keystr += "Mode_switch";
1020 break;
1021 case Qt::Key_Kanji:
1022 keystr += "Kanji";
1023 break;
1024 case Qt::Key_Muhenkan:
1025 keystr += "Muhenkan";
1026 break;
1027 case Qt::Key_Henkan:
1028 keystr += "Henkan_Mode";
1029 break;
1030 case Qt::Key_Romaji:
1031 keystr += "romaji";
1032 break;
1033 case Qt::Key_Hiragana:
1034 keystr += "hiragana";
1035 break;
1036 case Qt::Key_Katakana:
1037 keystr += "katakana";
1038 break;
1039 case Qt::Key_Hiragana_Katakana:
1040 keystr += "hiragana-katakana";
1041 break;
1042 case Qt::Key_Zenkaku:
1043 keystr += "zenkaku";
1044 break;
1045 case Qt::Key_Hankaku:
1046 keystr += "hankaku";
1047 break;
1048 case Qt::Key_Zenkaku_Hankaku:
1049 keystr += "zenkaku-hankaku";
1050 break;
1051 case Qt::Key_Touroku:
1052 keystr += "touroku";
1053 break;
1054 case Qt::Key_Massyo:
1055 keystr += "massyo";
1056 break;
1057 case Qt::Key_Kana_Lock:
1058 keystr += "kana-lock";
1059 break;
1060 case Qt::Key_Kana_Shift:
1061 keystr += "kana-shift";
1062 break;
1063 case Qt::Key_Eisu_Shift:
1064 keystr += "eisu-shift";
1065 break;
1066 case Qt::Key_Eisu_toggle:
1067 keystr += "eisu-toggle";
1068 break;
1069 case Qt::Key_Hangul:
1070 keystr += "hangul";
1071 break;
1072 case Qt::Key_Hangul_Start:
1073 keystr += "hangul-start";
1074 break;
1075 case Qt::Key_Hangul_End:
1076 keystr += "hangul-end";
1077 break;
1078 case Qt::Key_Hangul_Hanja:
1079 keystr += "hangul-hanja";
1080 break;
1081 case Qt::Key_Hangul_Jamo:
1082 keystr += "hangul-jamo";
1083 break;
1084 case Qt::Key_Hangul_Romaja:
1085 keystr += "hangul-romaja";
1086 break;
1087 case Qt::Key_Hangul_Jeonja:
1088 keystr += "hangul-jeonja";
1089 break;
1090 case Qt::Key_Hangul_Banja:
1091 keystr += "hangul-banja";
1092 break;
1093 case Qt::Key_Hangul_PreHanja:
1094 keystr += "hangul-prehanja";
1095 break;
1096 case Qt::Key_Hangul_PostHanja:
1097 keystr += "hangul-prosthanja";
1098 break;
1099 case Qt::Key_Hangul_Special:
1100 keystr += "hangul-special";
1101 break;
1102 case Qt::Key_Dead_Grave:
1103 keystr += "dead-grave";
1104 break;
1105 case Qt::Key_Dead_Acute:
1106 keystr += "dead-acute";
1107 break;
1108 case Qt::Key_Dead_Circumflex:
1109 keystr += "dead-circumflex";
1110 break;
1111 case Qt::Key_Dead_Tilde:
1112 keystr += "dead-tilde";
1113 break;
1114 case Qt::Key_Dead_Macron:
1115 keystr += "dead-macron";
1116 break;
1117 case Qt::Key_Dead_Breve:
1118 keystr += "dead-breve";
1119 break;
1120 case Qt::Key_Dead_Abovedot:
1121 keystr += "dead-abovedot";
1122 break;
1123 case Qt::Key_Dead_Diaeresis:
1124 keystr += "dead-diaeresis";
1125 break;
1126 case Qt::Key_Dead_Abovering:
1127 keystr += "dead-abovering";
1128 break;
1129 case Qt::Key_Dead_Doubleacute:
1130 keystr += "dead-doubleacute";
1131 break;
1132 case Qt::Key_Dead_Caron:
1133 keystr += "dead-caron";
1134 break;
1135 case Qt::Key_Dead_Cedilla:
1136 keystr += "dead-cedilla";
1137 break;
1138 case Qt::Key_Dead_Ogonek:
1139 keystr += "dead-ogonek";
1140 break;
1141 case Qt::Key_Dead_Iota:
1142 keystr += "dead-iota";
1143 break;
1144 case Qt::Key_Dead_Voiced_Sound:
1145 keystr += "dead-voiced-sound";
1146 break;
1147 case Qt::Key_Dead_Semivoiced_Sound:
1148 keystr += "dead-semivoiced-sound";
1149 break;
1150 case Qt::Key_Dead_Belowdot:
1151 keystr += "dead-belowdot";
1152 break;
1153 case Qt::Key_Dead_Hook:
1154 keystr += "dead-hook";
1155 break;
1156 case Qt::Key_Dead_Horn:
1157 keystr += "dead-horn";
1158 break;
1159 #endif /* Def: QT4_IMMODULE */
1160 case Qt::Key_Shift:
1161 keystr += "Shift_key";
1162 break;
1163 case Qt::Key_Control:
1164 keystr += "Control_key";
1165 break;
1166 case Qt::Key_Alt:
1167 keystr += "Alt_key";
1168 break;
1169 case Qt::Key_Meta:
1170 keystr += "Meta_key";
1171 break;
1172 case Qt::Key_Super_L:
1173 case Qt::Key_Super_R:
1174 keystr += "Super_key";
1175 break;
1176 case Qt::Key_Hyper_L:
1177 case Qt::Key_Hyper_R:
1178 keystr += "Hyper_key";
1179 break;
1180 case Qt::Key_CapsLock:
1181 keystr += "caps-lock";
1182 break;
1183 case Qt::Key_NumLock:
1184 keystr += "num-lock";
1185 break;
1186 case Qt::Key_ScrollLock:
1187 keystr += "scroll-lock";
1188 break;
1189 case Qt::Key_unknown:
1190 keystr += unicodeKeyToSymStr ( pressed_unichar );
1191 break;
1192 default:
1193 if( keyval >= Qt::Key_F1 && keyval <= Qt::Key_F35 )
1194 {
1195 keystr += 'F' + QString::number( keyval - Qt::Key_F1 + 1 );
1196 break;
1197 }
1198 else if( keyval < 256 )
1199 {
1200 QChar ch = QChar( keyval );
1201
1202 if( mod & Qt::ShiftModifier )
1203 ch = ch.toUpper();
1204 else
1205 ch = ch.toLower();
1206
1207 keystr += ch;
1208 }
1209 }
1210
1211 m_keystr = keystr;
1212
1213 }
1214
1215 //----------------------------------------------------------------------------------------
CustomTable(struct uim_custom * c,QWidget * parent)1216 CustomTable::CustomTable( struct uim_custom *c, QWidget *parent )
1217 : QFrame( parent ),
1218 UimCustomItemIface( c )
1219 {
1220 QPushButton *editButton = new QPushButton;
1221 editButton->setText( _("Edit...") );
1222 connect( editButton, SIGNAL(clicked()),
1223 this, SLOT(slotEditButtonClicked()) );
1224
1225 QHBoxLayout *layout = new QHBoxLayout;
1226 layout->setMargin( 0 );
1227 layout->setSpacing( 3 );
1228 layout->addStretch();
1229 layout->addWidget( editButton );
1230
1231 setLayout( layout );
1232
1233 update();
1234 }
1235
update()1236 void CustomTable::update()
1237 {
1238 if( !m_custom || m_custom->type != UCustom_Table )
1239 return;
1240 /* sync with Label */
1241 parentWidget()->setEnabled( m_custom->is_active );
1242 }
1243
setDefault()1244 void CustomTable::setDefault()
1245 {
1246 char ***custom_table = m_custom->value->as_table;
1247 for ( int row = 0; custom_table[row]; row++ ) {
1248 for ( int column = 0; custom_table[row][column]; column++ ) {
1249 free( custom_table[row][column] );
1250 }
1251 free( custom_table[row] );
1252 }
1253 char ***default_table = m_custom->default_value->as_table;
1254 int row;
1255 for ( row = 0; default_table[row]; row++ )
1256 ;
1257 custom_table = (char ***)malloc( sizeof(char **) * ( row + 1 ) );
1258 custom_table[row] = 0;
1259
1260 m_custom->value->as_table = custom_table;
1261
1262 for ( int row = 0; default_table[row]; row++ ) {
1263 int column;
1264 // the number of column may differ from row to row
1265 for ( column = 0; default_table[row][column]; column++ )
1266 ;
1267 custom_table[row] = (char **)malloc( sizeof(char *) * ( column + 1 ) );
1268 custom_table[row][column] = 0;
1269 for ( int column = 0; default_table[row][column]; column++ )
1270 custom_table[row][column] = strdup( default_table[row][column] );
1271 }
1272
1273 setCustom( m_custom );
1274 update();
1275 }
1276
slotEditButtonClicked()1277 void CustomTable::slotEditButtonClicked()
1278 {
1279 QPointer<TableEditForm> d = new TableEditForm( this );
1280 d->setWindowTitle( _FU8( m_custom->label ) );
1281 d->setTable( m_custom->value->as_table );
1282 int column = 0;
1283 for ( struct uim_custom_choice **item
1284 = m_custom->range->as_table_header.valid_items;
1285 *item; item++ ) {
1286 d->setTableHeaderItem( _FU8( ( *item )->label ), column );
1287 column++;
1288 }
1289 if ( d->exec() == QDialog::Accepted ) {
1290 m_custom->value->as_table = d->table();
1291 setCustom( m_custom );
1292 update();
1293 }
1294 delete d;
1295 }
1296
TableEditForm(QWidget * parent)1297 TableEditForm::TableEditForm( QWidget *parent )
1298 : QDialog( parent )
1299 {
1300 m_table = new QTableWidget;
1301 m_table->setSelectionMode( QAbstractItemView::SingleSelection );
1302 QHeaderView *verticalHeader = m_table->verticalHeader();
1303 verticalHeader->setVisible( false );
1304 verticalHeader->setDefaultSectionSize(
1305 QFontMetrics( m_table->font() ).height() + 2 );
1306 QHeaderView *horizontalHeader = m_table->horizontalHeader();
1307 #if QT_VERSION < 0x050000
1308 horizontalHeader->setResizeMode( QHeaderView::ResizeToContents );
1309 #else
1310 horizontalHeader->setSectionResizeMode( QHeaderView::ResizeToContents );
1311 #endif
1312 horizontalHeader->setStretchLastSection( true );
1313 connect( m_table, SIGNAL( itemSelectionChanged() ),
1314 this, SLOT( slotItemSelectionChanged() ) );
1315
1316 QPushButton *addButton = new QPushButton;
1317 addButton->setText( _("Add") );
1318 connect( addButton, SIGNAL( clicked() ),
1319 this, SLOT( slotAddClicked() ) );
1320
1321 m_removeButton = new QPushButton;
1322 m_removeButton->setEnabled( false );
1323 m_removeButton->setText( _("Remove") );
1324 connect( m_removeButton, SIGNAL( clicked() ),
1325 this, SLOT( slotRemoveClicked() ) );
1326
1327 m_upButton = new QPushButton;
1328 m_upButton->setEnabled( false );
1329 m_upButton->setText( _("Up") );
1330 connect( m_upButton, SIGNAL( clicked() ),
1331 this, SLOT( slotUpClicked() ) );
1332
1333 m_downButton = new QPushButton;
1334 m_downButton->setEnabled( false );
1335 m_downButton->setText( _("Down") );
1336 connect( m_downButton, SIGNAL( clicked() ),
1337 this, SLOT( slotDownClicked() ) );
1338
1339 QPushButton *okButton = new QPushButton;
1340 okButton->setText( _("OK") );
1341 connect( okButton, SIGNAL( clicked() ), this, SLOT( accept() ) );
1342
1343 QPushButton *cancelButton = new QPushButton;
1344 cancelButton->setText( _("Cancel") );
1345 connect( cancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
1346
1347 QVBoxLayout *buttonLayout = new QVBoxLayout;
1348 buttonLayout->addWidget( addButton );
1349 buttonLayout->addWidget( m_removeButton );
1350 buttonLayout->addWidget( m_upButton );
1351 buttonLayout->addWidget( m_downButton );
1352 buttonLayout->addStretch();
1353 buttonLayout->addWidget( okButton );
1354 buttonLayout->addWidget( cancelButton );
1355
1356 QHBoxLayout *layout = new QHBoxLayout;
1357 layout->addWidget( m_table );
1358 layout->addLayout( buttonLayout );
1359
1360 setLayout( layout );
1361
1362 m_table->horizontalHeader()->adjustSize();
1363 }
1364
setTable(char *** custom_table)1365 void TableEditForm::setTable( char ***custom_table )
1366 {
1367 if ( !custom_table )
1368 return;
1369 // the number of column may differ from row to row
1370 int max_column = -1;
1371 int row;
1372 for ( row = 0; custom_table[row]; row++ ) {
1373 for ( int column = 0; custom_table[row][column]; column++ ) {
1374 if ( max_column < column )
1375 max_column = column;
1376 }
1377 }
1378 m_table->setRowCount( row );
1379 m_table->setColumnCount( max_column + 1 );
1380
1381 for ( int row = 0; custom_table[row]; row++ ) {
1382 bool expanded = false;
1383 for ( int column = 0; column < max_column + 1; column++ ) {
1384 if ( !custom_table[row][column] )
1385 expanded = true;
1386 QTableWidgetItem *item = new QTableWidgetItem( expanded ?
1387 "" : _FU8( custom_table[row][column] ) );
1388 if ( expanded )
1389 item->setFlags( Qt::NoItemFlags );
1390 m_table->setItem( row, column, item );
1391 }
1392 }
1393 m_customTable = custom_table;
1394 }
1395
table() const1396 char ***TableEditForm::table() const
1397 {
1398 char ***custom_table = m_customTable;
1399 for ( int row = 0; custom_table[row]; row++ ) {
1400 for ( int column = 0; custom_table[row][column]; column++ ) {
1401 free( custom_table[row][column] );
1402 }
1403 free( custom_table[row] );
1404 }
1405
1406 int rowCount = m_table->rowCount();
1407 custom_table = (char ***)malloc( sizeof(char **) * ( rowCount + 1 ) );
1408 custom_table[rowCount] = 0;
1409
1410 int columnCount = m_table->columnCount();
1411
1412 for ( int row = 0; row < rowCount; row++ ) {
1413 int columnCountForRow = columnCount;
1414 // the number of column may differ from row to row
1415 for ( int column = 0; column < columnCount; column++ ) {
1416 if ( !( m_table->item( row, column )->flags() ) ) {
1417 columnCountForRow = column;
1418 break;
1419 }
1420 }
1421 custom_table[row]
1422 = (char **)malloc( sizeof(char *) * ( columnCountForRow + 1 ) );
1423 custom_table[row][columnCountForRow] = 0;
1424 for ( int column = 0; column < columnCountForRow; column++ )
1425 custom_table[row][column] = strdup(
1426 m_table->item( row, column )->text().toUtf8().data() );
1427 }
1428
1429 return custom_table;
1430 }
1431
setTableHeaderItem(const QString & item,int column)1432 void TableEditForm::setTableHeaderItem( const QString &item, int column )
1433 {
1434 if ( column < m_table->columnCount() ) {
1435 m_table->setHorizontalHeaderItem( column,
1436 new QTableWidgetItem( item ) );
1437 }
1438 }
1439
slotItemSelectionChanged()1440 void TableEditForm::slotItemSelectionChanged()
1441 {
1442 bool itemSelected = ( m_table->selectedItems().count() == 1 );
1443 m_removeButton->setEnabled( itemSelected );
1444 m_upButton->setEnabled( itemSelected );
1445 m_downButton->setEnabled( itemSelected );
1446 }
1447
slotAddClicked()1448 void TableEditForm::slotAddClicked()
1449 {
1450 QList<QTableWidgetItem *> items = m_table->selectedItems();
1451 int row = ( items.count() > 0 ) ? items[0]->row() + 1 : m_table->rowCount();
1452 m_table->insertRow( row );
1453 for ( int i = 0; i < m_table->columnCount(); i++ )
1454 m_table->setItem( row, i, new QTableWidgetItem( "" ) );
1455 m_table->scrollToItem( m_table->item( row, 0 ) );
1456 }
1457
slotRemoveClicked()1458 void TableEditForm::slotRemoveClicked()
1459 {
1460 QList<QTableWidgetItem *> items = m_table->selectedItems();
1461 if ( items.count() != 1 )
1462 return;
1463 m_table->removeRow( items[0]->row() );
1464 }
1465
slotUpClicked()1466 void TableEditForm::slotUpClicked()
1467 {
1468 QList<QTableWidgetItem *> items = m_table->selectedItems();
1469 if ( items.count() != 1 )
1470 return;
1471 QTableWidgetItem *item = items[0];
1472 const int row = item->row();
1473 if ( row < 1 || row > m_table->rowCount() - 1 )
1474 return;
1475 const int newRow = row - 1;
1476 m_table->insertRow( newRow );
1477 for ( int column = 0; column < m_table->columnCount(); column++ ) {
1478 m_table->setItem( newRow, column,
1479 m_table->takeItem( row + 1, column ) );
1480 }
1481 m_table->removeRow( row + 1 );
1482
1483 m_table->setCurrentItem( item );
1484 m_table->scrollToItem( item );
1485 }
1486
slotDownClicked()1487 void TableEditForm::slotDownClicked()
1488 {
1489 QList<QTableWidgetItem *> items = m_table->selectedItems();
1490 if ( items.count() != 1 )
1491 return;
1492 QTableWidgetItem *item = items[0];
1493 const int row = item->row();
1494 if ( row < 0 || row >= m_table->rowCount() - 1 )
1495 return;
1496 const int newRow = row + 2;
1497 m_table->insertRow( newRow );
1498 for ( int column = 0; column < m_table->columnCount(); column++ ) {
1499 m_table->setItem( newRow, column, m_table->takeItem( row, column ) );
1500 }
1501 m_table->removeRow( row );
1502
1503 m_table->setCurrentItem( item );
1504 m_table->scrollToItem( item );
1505 }
1506
unicodeKeyToSymStr(QChar c)1507 static QString unicodeKeyToSymStr ( QChar c )
1508 {
1509 QString str;
1510
1511 switch ( c.unicode() ) {
1512 case 0x00A5: str = "yen"; break;
1513 case 0x3002: str = "kana-fullstop"; break;
1514 case 0x300C: str = "kana-opening-bracket"; break;
1515 case 0x300D: str = "kana-closing-bracket"; break;
1516 case 0x3001: str = "kana-comma"; break;
1517 case 0x30FB: str = "kana-conjunctive"; break;
1518 case 0x30F2: str = "kana-WO"; break;
1519 case 0x30A1: str = "kana-a"; break;
1520 case 0x30A3: str = "kana-i"; break;
1521 case 0x30A5: str = "kana-u"; break;
1522 case 0x30A7: str = "kana-e"; break;
1523 case 0x30A9: str = "kana-o"; break;
1524 case 0x30E3: str = "kana-ya"; break;
1525 case 0x30E5: str = "kana-yu"; break;
1526 case 0x30E7: str = "kana-yo"; break;
1527 case 0x30C3: str = "kana-tsu"; break;
1528 case 0x30FC: str = "kana-prolonged-sound"; break;
1529 case 0x30A2: str = "kana-A"; break;
1530 case 0x30A4: str = "kana-I"; break;
1531 case 0x30A6: str = "kana-U"; break;
1532 case 0x30A8: str = "kana-E"; break;
1533 case 0x30AA: str = "kana-O"; break;
1534 case 0x30AB: str = "kana-KA"; break;
1535 case 0x30AD: str = "kana-KI"; break;
1536 case 0x30AF: str = "kana-KU"; break;
1537 case 0x30B1: str = "kana-KE"; break;
1538 case 0x30B3: str = "kana-KO"; break;
1539 case 0x30B5: str = "kana-SA"; break;
1540 case 0x30B7: str = "kana-SHI"; break;
1541 case 0x30B9: str = "kana-SU"; break;
1542 case 0x30BB: str = "kana-SE"; break;
1543 case 0x30BD: str = "kana-SO"; break;
1544 case 0x30BF: str = "kana-TA"; break;
1545 case 0x30C1: str = "kana-CHI"; break;
1546 case 0x30C4: str = "kana-TSU"; break;
1547 case 0x30C6: str = "kana-TE"; break;
1548 case 0x30C8: str = "kana-TO"; break;
1549 case 0x30CA: str = "kana-NA"; break;
1550 case 0x30CB: str = "kana-NI"; break;
1551 case 0x30CC: str = "kana-NU"; break;
1552 case 0x30CD: str = "kana-NE"; break;
1553 case 0x30CE: str = "kana-NO"; break;
1554 case 0x30CF: str = "kana-HA"; break;
1555 case 0x30D2: str = "kana-HI"; break;
1556 case 0x30D5: str = "kana-FU"; break;
1557 case 0x30D8: str = "kana-HE"; break;
1558 case 0x30DB: str = "kana-HO"; break;
1559 case 0x30DE: str = "kana-MA"; break;
1560 case 0x30DF: str = "kana-MI"; break;
1561 case 0x30E0: str = "kana-MU"; break;
1562 case 0x30E1: str = "kana-ME"; break;
1563 case 0x30E2: str = "kana-MO"; break;
1564 case 0x30E4: str = "kana-YA"; break;
1565 case 0x30E6: str = "kana-YU"; break;
1566 case 0x30E8: str = "kana-YO"; break;
1567 case 0x30E9: str = "kana-RA"; break;
1568 case 0x30EA: str = "kana-RI"; break;
1569 case 0x30EB: str = "kana-RU"; break;
1570 case 0x30EC: str = "kana-RE"; break;
1571 case 0x30ED: str = "kana-RO"; break;
1572 case 0x30EF: str = "kana-WA"; break;
1573 case 0x30F3: str = "kana-N"; break;
1574 case 0x309B: str = "kana-voiced-sound"; break;
1575 case 0x309C: str = "kana-semivoiced-sound"; break;
1576 default:
1577 break;
1578 }
1579
1580 return str;
1581 }
1582