root/trunk/orca/qt/qorca.cpp

Revision 416, 34.7 kB (checked in by krobillard, 18 months ago)

Orca Qt - Fixed subtle QApplication argc reference bug.

Line 
1/*============================================================================
2    ORCA Qt Module
3    Copyright (C) 2005-2006  Karl Robillard
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License
7    as published by the Free Software Foundation; either version 2
8    of the License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA.
19============================================================================*/
20
21
22#include <assert.h>
23#include <QCloseEvent>
24#include <QEventLoop>
25#include <QFileDialog>
26#include <QHBoxLayout>
27#include <QVBoxLayout>
28#include <QMessageBox>
29#include <QTextCursor>
30#include "qorca.h"
31#include "cbparse.h"
32
33
34inline bool qEnvExists() { return qEnv.atom_close > 0; }
35
36
37struct LayoutInfo
38{
39    LayoutInfo() : box(0), grid(0) {}
40
41    QLayout* layout()
42    {
43        if( box )
44            return box;
45        return grid;
46    }
47
48    void addLayout( QLayout* );
49    void addWidget( QWidget* );
50
51    QBoxLayout*  box;
52    QGridLayout* grid;
53    int columns;
54    int colN;
55    int rowN;
56};
57
58
59QtEnv qEnv;
60
61
62//----------------------------------------------------------------------------
63
64
65void LayoutInfo::addLayout( QLayout* lo )
66{
67    if( box )
68    {
69        box->addLayout( lo );
70    }
71    else
72    {
73        grid->addLayout( lo, rowN, colN );
74
75        ++colN;
76        if( colN == columns )
77        {
78            colN = 0;
79            ++rowN;
80        }
81    }
82}
83
84
85void LayoutInfo::addWidget( QWidget* wid )
86{
87    if( box )
88    {
89        box->addWidget( wid );
90    }
91    else
92    {
93        grid->addWidget( wid, rowN, colN );
94
95        ++colN;
96        if( colN == columns )
97        {
98            colN = 0;
99            ++rowN;
100        }
101    }
102}
103
104
105//----------------------------------------------------------------------------
106
107
108/**
109  Returns REC id.
110*/
111int WIDPool::add( QObject* ptr, int type, int flags )
112{
113    int index;
114    if( _freeCount )
115    {
116        index = _freeIndex;
117        REC& rec = _records[ index ];
118
119        _freeIndex = rec.type;
120
121        rec.type   = type;
122        rec.flags  = flags;
123        rec.object = ptr;
124
125        --_freeCount;
126    }
127    else
128    {
129        index = _records.size();
130        REC rec;
131        rec.type   = type;
132        rec.flags  = flags;
133        rec.object = ptr;
134        _records.push_back( rec );
135    }
136    return index;
137}
138
139
140void WIDPool::remove( int id )
141{
142    if( qEnvExists() )
143    {
144        REC& rec = _records[ id ];
145
146        assert( rec.widget );
147
148        rec.type = _freeIndex;
149        _freeIndex = id;
150        rec.object = 0;
151
152        ++_freeCount;
153    }
154}
155
156
157WIDPool::REC* WIDPool::record( int id )
158{
159    if( (id > -1) && id < _records.size() )
160    {
161        REC* rec = &_records[ id ];
162        if( rec->object )
163            return rec;
164    }
165    return 0;
166}
167
168
169//----------------------------------------------------------------------------
170
171
172struct AOString : public OString
173{
174    AOString()       { orArrayInit( this, sizeof(char), 0 ); }
175    AOString(int n)  { orArrayInit( this, sizeof(char), n ); }
176    ~AOString()      { orArrayFree( this ); }
177
178    const char* mold( const OValue* val )
179    {
180        orMold( this, val );    // Calls orTermCStr() for us.
181        return charArray;
182    }
183
184    const char* form( const OValue* val )
185    {
186        orForm( this, val );    // Calls orTermCStr() for us.
187        return charArray;
188    }
189};
190
191
192//----------------------------------------------------------------------------
193
194
195/*
196  Note that argc is a reference!  If it is not, QApplication will
197  store the stack position of the local argc and crash when argc is used
198  after the constructor exits.
199*/
200QOrcaApp::QOrcaApp( int& argc, char** argv ) : QApplication( argc, argv )
201{
202    setQuitOnLastWindowClosed( false );
203}
204
205
206/*
207   Returns non-zero if error thrown.
208*/
209int qoError()
210{
211    if( orErrorThrown )
212    {
213        switch( orErrorType(orErrorThrown) )
214        {
215            case OR_ERROR_THROW:
216                return 1;
217
218            case OR_ERROR_QUIT:
219                qApp->quit();
220                return 1;
221
222            //case OR_ERROR_HALT:
223            default:
224#ifdef _WIN32
225            {
226                QString msg;
227                AOString str;
228
229                if( str.form( orErrorThrown ) )
230                    msg = str.charArray;
231
232                QMessageBox::warning( 0, "Script Error", msg,
233                                      QMessageBox::Ok, QMessageBox::NoButton );
234            }
235#else
236                orPrintNative( orErrorThrown );
237#endif
238                break;
239        }
240
241        orErrorClear;
242    }
243    return 0;
244}
245
246
247#if 0
248static void comboBlock( QComboBox* combo, OValue* it, OValue* end )
249{
250    while( it != end )
251    {
252        if( it->type == OT_STRING )
253        {
254            OString* str = orSTRING(it);
255            const char* cp = str->charArray + it->series.it;
256            combo->addItem( cp );
257        }
258        ++it;
259    }
260}
261#endif
262
263
264QLayout* qoLayout( LayoutInfo& parent, OIndex blkN, OIndex si );
265
266static void tabBlock( QTabWidget* tab, OValue* it, const char* label )
267{
268    LayoutInfo layout;
269    QLayout* lo;
270    QWidget* wid = new QWidget;
271
272    lo = qoLayout( layout, it->index, it->series.it );
273    wid->setLayout( lo );
274
275    tab->addTab( wid, QString(label) );
276}
277
278
279static void tabWidgetBlock( QTabWidget* tab, OValue* it, OValue* end )
280{
281    const char* label = 0;
282
283    while( it != end )
284    {
285        if( it->type == OT_STRING )
286        {
287            OString* str = orSTRING(it);
288            label = str->charArray + it->series.it;
289        }
290        else if( it->type == OT_WORD )
291        {
292            OValue* val;
293            OBlock* ctx;
294            orWordVal( it, ctx, val );
295
296            if( label && (val->type == OT_BLOCK) )
297            {
298                tabBlock( tab, val, label );
299                label = 0;
300            }
301            //printf( "KR word\n" );
302        }
303        else if( it->type == OT_BLOCK )
304        {
305            if( label )
306            {
307                tabBlock( tab, it, label );
308                label = 0;
309            }
310        }
311
312        ++it;
313    }
314}
315
316
317static void setWID( OValue*& prev, int id )
318{
319    if( prev )
320    {
321        OValue* val;
322        OBlock* ctx;
323        orWordVal( prev, ctx, val );
324        orSetTF( val, OT_INTEGER );
325        val->integer = id;
326        prev = 0;
327    }
328}
329
330
331static void valueToQString( const OValue* val, QString& str )
332{
333    if( orIsString( val->type ) )
334    {
335        str = cstring( val );
336    }
337    else if( val->type == OT_INTEGER )
338    {
339        str.setNum( val->integer );
340    }
341    else if( val->type == OT_DECIMAL )
342    {
343        str.setNum( val->num.decimal );
344    }
345    else if( val->type == OT_NONE )
346    {
347        str.clear();
348    }
349    else
350    {
351        AOString ts;
352        str = ts.mold( val );
353    }
354}
355
356
357#define LD_HBOX         0
358#define LD_VBOX         1
359#define LD_SPACER       2
360#define LD_LABEL        3
361#define LD_BUTTON       4
362#define LD_CHECKBOX     5
363#define LD_COMBO        6
364#define LD_COMBO_BLK    7
365#define LD_TIP          8
366#define LD_TITLE        9
367#define LD_RESIZE       10
368#define LD_LINE_EDITS   11
369#define LD_LINE_EDIT    12
370#define LD_TEXT_EDITS   13
371#define LD_TEXT_EDIT    14
372#define LD_GROUP        15
373#define LD_READ_ONLY    16
374#define LD_ON_EVENT     17
375#define LD_TAB          18
376#define LD_STRING       19
377#define LD_BLOCK        20
378#define LD_SET_WORD     21
379#define LD_GRID         22
380#define LD_PROGRESS     23
381#define LD_WEIGHT       24
382
383
384/*
385   Layout Dialect
386*/
387QLayout* qoLayout( LayoutInfo& parent, OIndex blkN, OIndex si )
388{
389    CBParser cbp;
390    OBlock* ruleSet;
391    OValue* match;
392    OBlock* blk;
393    OValue* val;
394    OValue* setWord = 0;
395    LayoutInfo lo;
396    QWidget* wid = 0;
397
398    blk = orBlockPtr( blkN );
399
400    ruleSet = orBlockPtr( qEnv.layoutRulesBlkN );
401
402    cbp_beginParse( &cbp, blk->values + si, blk->values + blk->used, ruleSet );
403    while( (match = cbp_matchRule( &cbp )) )
404    {
405        switch( match->integer )
406        {
407            case LD_HBOX:
408            case LD_VBOX:
409            {
410                wid = 0;
411
412                lo.grid = 0;
413                lo.box  = new QBoxLayout( (match->integer == LD_HBOX) ?
414                                          QBoxLayout::LeftToRight :
415                                          QBoxLayout::TopToBottom );
416                if( parent.layout() )
417                    parent.addLayout( lo.box );
418
419                val = cbp.values + 1;
420                qoLayout( lo, val->index, val->series.it );
421            }
422                break;
423
424            case LD_SPACER:
425                if( ! parent.box )
426                    goto no_layout;
427
428                parent.box->addStretch( 1 );
429                break;
430
431            case LD_LABEL:
432            {
433                if( ! parent.layout() )
434                    goto no_layout;
435
436                SLabel* pw = new SLabel;
437                parent.addWidget( pw );
438                setWID( setWord, pw->_wid );
439
440                val = cbp.values + 1;
441                if( orIs(val, OT_WORD) )
442                {
443                    orWordVal( val, blk, val );
444                }
445                QString txt;
446                valueToQString( val, txt );
447                pw->setText( txt );
448
449                wid = pw;
450            }
451                break;
452
453            case LD_BUTTON:
454            {
455                if( ! parent.layout() )
456                    goto no_layout;
457
458                SButton* pw = new SButton;
459                parent.addWidget( pw );
460                setWID( setWord, pw->_wid );
461                pw->setText( cstring( cbp.values + 1 ) );
462                pw->setBlock( cbp.values + 2 );
463                wid = pw;
464            }
465                break;
466
467            case LD_CHECKBOX:
468            {
469                if( ! parent.layout() )
470                    goto no_layout;
471
472                SCheck* pw = new SCheck;
473                parent.addWidget( pw );
474                setWID( setWord, pw->_wid );
475                pw->setText( cstring( cbp.values + 1 ) );
476                wid = pw;
477            }
478                break;
479
480            case LD_COMBO:
481            case LD_COMBO_BLK:
482            {
483                if( ! parent.layout() )
484                    goto no_layout;
485
486                SCombo* pw = new SCombo;
487                parent.addWidget( pw );
488                setWID( setWord, pw->_wid );
489                wid = pw;
490
491                val = cbp.values + 1;
492                if( orIs(val, OT_BLOCK) )
493                {
494                    OBlock* blk = orBLOCK(val);
495                    OValue* it  = blk->values + val->series.it;
496                    OValue* end = blk->values + blk->used;
497                    while( it != end )
498                    {
499                        if( orIs(it, OT_STRING) )
500                            pw->addItem( cstring( it ) );
501                        ++it;
502                    }
503                }
504                else
505                {
506                    pw->addItem( cstring( val ) );
507                }
508            }
509                break;
510
511            case LD_TAB:
512            {
513                if( ! parent.layout() )
514                    goto no_layout;
515
516                STabWidget* pw = new STabWidget;
517                parent.addWidget( pw );
518                setWID( setWord, pw->_wid );
519                wid = pw;
520
521                val = cbp.values + 1;
522                OBlock* blk = orBLOCK( val );
523                tabWidgetBlock( pw, blk->values + val->series.it,
524                                    blk->values + blk->used );
525            }
526                break;
527
528            case LD_TIP:
529                if( wid )
530                    wid->setToolTip( cstring(cbp.values + 1) );
531                break;
532
533            case LD_TITLE:
534            {
535                if( qEnv.curWidget )
536                    qEnv.curWidget->setWindowTitle( cstring(cbp.values + 1) );
537            }
538                break;
539
540            case LD_RESIZE:
541            {
542                if( qEnv.curWidget )
543                {
544                    val = cbp.values + 1;
545                    qEnv.curWidget->resize( val->pair[0], val->pair[1] );
546                }
547            }
548                break;
549
550            case LD_LINE_EDITS:
551            case LD_LINE_EDIT:
552            {
553                if( ! parent.layout() )
554                    goto no_layout;
555
556                SLineEdit* pw = new SLineEdit;
557                parent.addWidget( pw );
558                setWID( setWord, pw->_wid );
559                wid = pw;
560
561                if( match->integer == LD_LINE_EDITS )
562                    pw->setText( cstring( cbp.values + 1 ) );
563            }
564                break;
565
566            case LD_TEXT_EDITS:
567            case LD_TEXT_EDIT:
568            {
569                if( ! parent.layout() )
570                    goto no_layout;
571
572                STextEdit* pw = new STextEdit;
573                parent.addWidget( pw );
574                setWID( setWord, pw->_wid );
575                wid = pw;
576
577                if( match->integer == LD_TEXT_EDITS )
578                {
579                    const char* str = cstring( cbp.values + 1 );
580                    if( *str == '<' )
581                        pw->setHtml( str );
582                    else
583                        pw->setPlainText( str );
584                }
585            }
586                break;
587
588            case LD_GROUP:
589            {
590                if( ! parent.layout() )
591                    goto no_layout;
592
593                SGroup* pw = new SGroup;
594                parent.addWidget( pw );
595                setWID( setWord, pw->_wid );
596                wid = pw;
597
598                val = cbp.values + 1;
599                pw->setTitle( cstring( val ) );
600
601                ++val;
602
603                LayoutInfo lo2;
604                pw->setLayout( qoLayout(lo2, val->index, val->series.it) );
605            }
606                break;
607
608            case LD_READ_ONLY:
609                if( wid )
610                {
611                    QTextEdit* tedit = qobject_cast<QTextEdit*>( wid );
612                    if( tedit )
613                        tedit->setReadOnly( true );
614                }
615                break;
616
617            case LD_ON_EVENT:
618                if( qEnv.curWidget )
619                {
620                    SWidget* sw = qobject_cast<SWidget*>( qEnv.curWidget );
621                    if( sw )
622                        sw->setEventBlock( cbp.values + 1 );
623                }
624                break;
625
626            case LD_STRING:
627                if( wid )
628                {
629                    SCombo* combo = qobject_cast<SCombo*>( wid );
630                    if( combo )
631                    {
632                        combo->addItem( cstring( cbp.values ) );
633                        break;
634                    }
635
636                    QTextEdit* texted = qobject_cast<QTextEdit*>( wid );
637                    if( texted )
638                    {
639                        const char* str = cstring( cbp.values );
640                        if( *str == '<' )
641                            texted->setHtml( str );
642                        else
643                            texted->setPlainText( str );
644                    }
645                }
646                break;
647
648            case LD_BLOCK:
649                if( wid )
650                {
651                    SCombo* combo = qobject_cast<SCombo*>( wid );
652                    if( combo )
653                        combo->setBlock( cbp.values );
654                }
655                break;
656
657            case LD_SET_WORD:
658                setWord = cbp.values;
659                break;
660
661            case LD_GRID:
662                val = cbp.values + 1;
663
664                wid = 0;
665
666                lo.box     = 0;
667                lo.grid    = new QGridLayout;
668                lo.columns = val->integer;
669                lo.colN    = 0;
670                lo.rowN    = 0;
671
672                if( parent.layout() )
673                    parent.addLayout( lo.grid );
674
675                ++val;
676                qoLayout( lo, val->index, val->series.it );
677                break;
678
679            case LD_PROGRESS:
680            {
681                if( ! parent.layout() )
682                    goto no_layout;
683
684                SProgress* pw = new SProgress;
685                parent.addWidget( pw );
686                setWID( setWord, pw->_wid );
687                pw->setRange( 0, cbp.values[1].integer );
688                wid = pw;
689            }
690                break;
691
692            case LD_WEIGHT:
693                if( parent.box && wid )
694                {
695                    parent.box->setStretchFactor(wid, cbp.values[1].integer);
696                }
697                break;
698        }
699    }
700
701    if( cbp.error )
702    {
703        orError( "layout parse error" );
704        blk = orBlockPtr( blkN );
705        orSetErrorLoc( blkN, cbp.error - blk->values );
706    }
707
708    return lo.layout();
709
710no_layout:
711
712    orError( "layout requires hbox or vbox" );
713    return 0;
714}
715
716
717static int catchExit( OValue* a1 )
718{
719    if( orErrorThrown && orErrorIsType( OR_ERROR_THROW ) )
720    {
721        if( orErrorThrown->error.msg == qEnv.atom_exec_exit )
722        {
723            orCopyV( a1, *(orErrorThrown + 1) );
724            orErrorClear;
725            return qEnv.atom_exec_exit;
726        }
727        else if( orErrorThrown->error.msg == qEnv.atom_close )
728        {
729            orCopyV( a1, *(orErrorThrown + 1) );
730            orErrorClear;
731            return qEnv.atom_close;
732        }
733    }
734    return 0;
735}
736
737
738OR_NATIVE( execNative )
739{
740    if( a1->type == OT_INTEGER )
741    {
742        WIDPool::REC* rec = qEnv.pool.record( a1->integer );
743        if( rec )
744        {
745            if( rec->type == WT_Dialog )
746            {
747                QDialog* saveDialog = qEnv.dialog;
748
749                qEnv.dialog = (QDialog*) rec->widget;
750                qEnv.dialog->exec();
751                qEnv.dialog = saveDialog;
752
753                catchExit( a1 );
754            }
755            else if( rec->type == WT_Widget )
756            {
757                QWidget* widget = rec->widget;
758
759                widget->show();
760                qEnv.loop->exec();
761                if( catchExit( a1 ) == qEnv.atom_close )
762                    widget->hide();
763            }
764            else
765            {
766                rec = 0;
767            }
768        }
769        if( ! rec )
770        {
771            orError( "Invalid widget ID %d", a1->integer );
772            return;
773        }
774    }
775    else
776    {
777        // Update.
778        qEnv.loop->processEvents();
779        catchExit( a1 );
780    }
781}
782
783
784static void execExit( OAtom word, OValue* a1 )
785{
786    if( qEnv.dialog )
787        qEnv.dialog->accept();
788    else
789        qEnv.loop->quit();
790
791    // Only allowing simple values - complex ones will become invalid if
792    // garbage collection occurs.
793
794    // Same as orThrowNative (throw/name a1 'close)
795    {
796    a1[1] = *a1;
797
798    orSetError( a1, OR_ERROR_THROW );
799
800    a1->error.msg     = word;
801    a1->error.block   = 0;
802    a1->error.nearVal = 0;
803    }
804}
805
806
807OR_NATIVE( execExitNative )
808{
809    execExit( qEnv.atom_exec_exit, a1 );
810}
811
812
813OR_NATIVE( closeNative )
814{
815    execExit( qEnv.atom_close, a1 );
816}
817
818
819OR_NATIVE( showNative )
820{
821    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
822    if( rec )
823    {
824        if( rec->type == WT_Widget )
825        {
826            rec->widget->show();
827
828            // Update.
829            qEnv.loop->processEvents();
830            catchExit( a1 );
831        }
832    }
833}
834
835
836static int layoutWidget( QWidget* wid, OValue* a1 )
837{
838    LayoutInfo li;
839    QLayout* lo;
840
841    QWidget* saveWidget = qEnv.curWidget;
842    qEnv.curWidget = wid;
843
844    lo = qoLayout( li, a1->index, a1->series.it );
845
846    qEnv.curWidget = saveWidget;
847
848    if( orErrorThrown )
849    {
850        delete wid;
851        qoError();
852        return 0;
853    }
854
855    if( lo )
856    {
857        wid->setLayout( lo );
858    }
859    else
860    {
861        orError( "Invalid widget layout" );
862        qoError();
863        return 0;
864    }
865
866    return 1;
867}
868
869
870OR_NATIVE( dialogNative )
871{
872    SDialog* dlg = new SDialog;
873    dlg->setModal( true );
874    if( layoutWidget( dlg, a1 ) )
875    {
876        orResult( OT_INTEGER, dlg->_wid );
877    }
878}
879
880
881OR_NATIVE( widgetNative )
882{
883    SWidget* wid = new SWidget;
884    if( layoutWidget( wid, a1 ) )
885    {
886        orResult( OT_INTEGER, wid->_wid );
887    }
888}
889
890
891OR_NATIVE( destroyNative )
892{
893    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
894    if( rec )
895    {
896        delete rec->object;
897    }
898    orResultNONE;
899}
900
901
902#define REF_RF_SAVE    a1+1
903#define REF_RF_DIR     a1+2
904#define REF_RF_INIT    a1+3
905#define REF_RF_PATH    a1+4
906
907OR_NATIVE( requestFileNative )
908{
909    QString fn;
910    QString dir;
911    OString* str;
912    const char* cp;
913
914    if( orRefineSet( REF_RF_INIT ) )
915    {
916        OValue* ref = REF_RF_PATH;
917        str = orSTRING( ref );
918        orTermCStr( str );
919        dir = orStrChars( str, ref );
920    }
921    else
922    {
923        dir = qEnv.filePath;
924    }
925
926    str = orSTRING(a1);
927    orTermCStr( str );
928    cp = orStrChars( str, a1 );
929
930    if( orRefineSet( REF_RF_DIR ) )
931    {
932        fn = QFileDialog::getExistingDirectory(0, QString(cp), dir );
933    }
934    else if( orRefineSet( REF_RF_SAVE ) )
935    {
936        fn = QFileDialog::getSaveFileName( 0, QString(cp), dir );
937    }
938    else
939    {
940        fn = QFileDialog::getOpenFileName( 0, QString(cp), dir );
941    }
942
943    if( fn.isEmpty() )
944    {
945        orResultNONE;
946    }
947    else
948    {
949        qEnv.filePath = fn;
950        OIndex index = orMakeCString( (const char*) fn.toAscii(), -1 );
951        orResultFILE( index );
952    }
953}
954
955
956OR_NATIVE( enableNative )
957{
958    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
959    if( rec )
960    {
961        QWidget* widget = qobject_cast<QWidget*>( rec->object );
962        if( widget )
963            widget->setEnabled( true );
964    }
965}
966
967
968OR_NATIVE( disableNative )
969{
970    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
971    if( rec )
972    {
973        QWidget* widget = qobject_cast<QWidget*>( rec->object );
974        if( widget )
975            widget->setEnabled( false );
976    }
977}
978
979
980OR_NATIVE( widgetValueNative )
981{
982    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
983    if( rec )
984    {
985        switch( rec->type )
986        {
987            case WT_CheckBox:
988            {
989                Qt::CheckState state = ((QCheckBox*) rec->widget)->checkState();
990                orResult( OT_LOGIC, (state == Qt::Unchecked) ? 0 : 1 );
991            }
992                break;
993
994            case WT_Combo:
995                orResult( OT_INTEGER,
996                          ((QComboBox*) rec->widget)->currentIndex() + 1 );
997                break;
998
999            case WT_LineEdit:
1000            {
1001                QString text = ((QLineEdit*) rec->widget)->text();
1002                orResultSTRING( orMakeCString( text.toAscii(), -1 ) );
1003            }
1004                break;
1005
1006            case WT_TextEdit:
1007            {
1008                QString text = ((QTextEdit*) rec->widget)->toPlainText();
1009                orResultSTRING( orMakeCString( text.toAscii(), -1 ) );
1010            }
1011                break;
1012
1013            default:
1014                break;
1015        }
1016    }
1017}
1018
1019
1020OR_NATIVE( setWidgetValueNative )
1021{
1022    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
1023    if( rec )
1024    {
1025        const OValue* a2 = a1 + 1;
1026
1027        switch( rec->type )
1028        {
1029            case WT_CheckBox:
1030            {
1031                Qt::CheckState state;
1032
1033                if( (a2->type == OT_NONE) ||
1034                    ((a2->type == OT_LOGIC) && (a2->integer == OR_FALSE)) )
1035                    state = Qt::Unchecked;
1036                else
1037                    state = Qt::Checked;
1038
1039                ((QCheckBox*) rec->widget)->setCheckState( state );
1040            }
1041                break;
1042
1043            case WT_Combo:
1044                if( a2->type == OT_INTEGER )
1045                {
1046                    ((QComboBox*)rec->widget)->setCurrentIndex( a2->integer-1 );
1047                }
1048                else if( a2->type == OT_LOGIC )
1049                {
1050                    ((QComboBox*)rec->widget)->setCurrentIndex( a2->integer );
1051                }
1052                break;
1053
1054            case WT_Label:
1055            {
1056                QString txt;
1057                valueToQString( a2, txt );
1058                ((QLabel*) rec->widget)->setText( txt );
1059            }
1060                break;
1061
1062            case WT_LineEdit:
1063            {
1064                QString txt;
1065                valueToQString( a2, txt );
1066                ((QLineEdit*) rec->widget)->setText( txt );
1067            }
1068                break;
1069
1070            case WT_TextEdit:
1071            {
1072                QString txt;
1073                valueToQString( a2, txt );
1074                ((QTextEdit*) rec->widget)->setPlainText( txt );
1075            }
1076                break;
1077
1078            case WT_Progress:
1079                if( a2->type == OT_INTEGER )
1080                {
1081                    ((QProgressBar*) rec->widget)->setValue( a2->integer );
1082                }
1083                else if( a2->type == OT_NONE )
1084                {
1085                    ((QProgressBar*) rec->widget)->reset();
1086                }
1087                break;
1088
1089            default:
1090                break;
1091        }
1092    }
1093}
1094
1095
1096OR_NATIVE( appendTextNative )
1097{
1098    WIDPool::REC* rec = qEnv.pool.record( a1->integer );
1099    if( rec )
1100    {
1101        const OValue* a2 = a1 + 1;
1102
1103        switch( rec->type )
1104        {
1105            case WT_LineEdit:
1106            {
1107                QString cur;
1108                QString txt;
1109                valueToQString( a2, txt );
1110                cur = ((QLineEdit*) rec->widget)->text();
1111                cur.append( txt );
1112                ((QLineEdit*) rec->widget)->setText( cur );
1113            }
1114                break;
1115
1116            case WT_TextEdit:
1117            {
1118                QString txt;
1119                QTextCursor cursor;
1120
1121                valueToQString( a2, txt );
1122
1123                QTextEdit* edit = (QTextEdit*) rec->widget;
1124
1125                cursor = edit->textCursor();
1126                cursor.movePosition( QTextCursor::End );
1127                cursor.insertText( txt );
1128
1129                //edit->insertPlainText( txt );
1130                //edit->append( txt );  // Adds linefeed before text.
1131            }
1132                break;
1133
1134            default:
1135                break;
1136        }
1137    }
1138}
1139
1140
1141OR_NATIVE( messageNative )
1142{
1143#define REF_MSG_WARN    a1+2
1144    OString* str1;
1145    OString* str2;
1146    const char* cp1;
1147    const char* cp2;
1148    OValue* a2 = a1 + 1;
1149
1150    str1 = orSTRING(a1);
1151    str2 = orSTRING(a2);
1152    orTermCStr( str1 );
1153    orTermCStr( str2 );
1154    cp1 = orStrChars(str1, a1);
1155    cp2 = orStrChars(str2, a2);
1156
1157    if( orRefineSet( REF_MSG_WARN ) )
1158        QMessageBox::warning( 0, cp1, cp2 );
1159    else
1160        QMessageBox::information( 0, cp1, cp2 );
1161}
1162
1163
1164OR_NATIVE( questionNative )
1165{
1166#define REF_QUESTION_DEF    a1+4
1167#define REF_QUESTION_BTN    a1+5
1168    OString* ostr;
1169    QString str[4];
1170    int def = 0;
1171    int i;
1172
1173    for( i = 0; i < 4; ++i )