More cleanup, and a few bugs fixed. There are many more!

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@2647 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2012-10-04 21:39:48 +00:00
parent c1e779f966
commit 41c25dbc01
9 changed files with 79 additions and 214 deletions

View File

@ -9,7 +9,7 @@ CAboutDlg::CAboutDlg(QWidget *parent, QString Revision) :
ui->setupUi(this); ui->setupUi(this);
ui->labelTxt->clear(); ui->labelTxt->clear();
m_Str = "<html><h2>" + m_Revision + "</h2>\n\n"; m_Str = "<html><h2>" + m_Revision + "</h2>\n\n";
m_Str += "WSJT-X implements experimental mode JT8 for <br>"; m_Str += "WSJT-X implements experimental mode JT9 for <br>";
m_Str += "Amateur Radio communication at MF and LF. <br><br>"; m_Str += "Amateur Radio communication at MF and LF. <br><br>";
m_Str += "Copyright 2001-2012 by Joe Taylor, K1JT. Additional <br>"; m_Str += "Copyright 2001-2012 by Joe Taylor, K1JT. Additional <br>";
m_Str += "acknowledgments are contained in the source code. <br>"; m_Str += "acknowledgments are contained in the source code. <br>";

31
jt8.txt
View File

@ -1,31 +0,0 @@
JT8 is a mode designed for amateur QSOs and beacon-like transmissions
at MF and LF. The mode uses the same 72-bit user messages as JT65,
augmented by a 12-bit cyclic redundancy check (CRC). Error-control
coding uses a convolutional code with constraint length K=16, rate
r=1/2, and a zero tail, leading to an encoded message length of
(72+12+15)*2 = 198 bits. Modulation is 8-FSK, so a transmission
requires 198/3 = 66 information-carrying channel symbols. Two 8x8
Costas arrays are added to each transmission for purposes of time and
frequency synchronization. A full transmission thus contains 66 + 16
= 82 symbols. Tone spacing df of the 8-FSK modulation is equal to the
keying rate; symbol duration tsym = 1/df, and the total occupied
bandwidth is 8*df. The actual transmission length TxT is slightly
less than the T/R sequence time, to allow for possible message
decoding before the next transmission starts.
Parameters of the five JT8 sub-modes are summarized in the following
table, along with S/N thresholds measured by simulation on an AWGN
(additive white Gaussian noise) channel. Parameter nsps is the number
of samples per symbol at sample rate 1500 Hz.
-----------------------------------------------------
Mode T/R TxT nsps df tsym BW S/N*
(m) (s) (Hz) (s) (Hz) (dB)
-----------------------------------------------------
JT8-1 1 52.5 960 1.562 0.64 12.6 -26.9
JT8-2 2 112.0 2048 0.732 1.37 5.9 -30.2
JT8-5 5 293.9 5376 0.279 3.58 2.2 -34.4
JT8-10 10 587.8 10752 0.140 7.17 1.1 -37.5
JT8-30 30 1791.3 32768 0.046 21.85 0.4 -42.3
-----------------------------------------------------
* Noise power measured in a 2500 Hz bandwidth.

View File

@ -1,72 +0,0 @@
JTMSK: Possible New Mode for Meteor Scatter
-------------------------------------------
JTMSK is a digital mode designed for amateur meteor-scatter
communication. The "MSK" part of the name could mean "Meteor Scatter
King": the mode works at the same signal levels as the popular mode
FSK441, but at about twice the character transmission rate, so it
makes much better use of short pings. MSK also means "Minimum Shift
Keying", which is the modulation technique used in JTMSK. It is a
form of continuous-phase frequency-shift keying that achieves high
transmission rate with a narrow bandwidth, while maintaining a
constant-envelope waveform.
1. Transmitting
Messages are sent character-by character, 6 bits plus odd parity.
Message length in characters is automatically selected from among the
possibilities 5 7 9 11 13 17 19 23 29. (Note that these lengths share
no common factor.) Messages are padded with blanks when required, up
to the next available length.
Modulation is Minimum Shift Keying (MSK) at 2000 baud. A "0" bit is
sent as an audio sine wave at f0=1000 Hz, lasting 0.5 ms; a "1" bit is
a sine wave at f1=2000 Hz. The carrier phase increment over one bit
is thus 0.5 cycles (pi radians) at f0, or 1.0 cycles at f1. Odd
parity assures an odd number of 1's and even number of 0's in every
7-bit character, so the phase increment over a full character is
always an integer number of cycles.
2. Receiving
a. Detect pings and update display in real time. (rtping)
b. Compute real-to-complex FFT. Zap birdies, remove frequency
components outside the range 300 - 2700 Hz, convert to analytic
time-domain signal. (analytic)
c. Square the complex signal and compute FFT. Look for narrow
spectral lines at frequency 2000 + 2*(DF +/- Tol) Hz and
4000 + 2*(DF +/- Tol) Hz. (msdf)
d. If a signal is found, measure frequency offset DF and phase Dphi.
(DF and Dphi are measured relative to the original frequencies f0
and f1, not their doubled values.) Multiply cx by
exp(-twopi*i*DF*t - Dphi) to recover the standard-frequency
baseband signal. (tweak1)
e. Establish symbol and character sync by cross-correlating with
conjg(cwb), MSK waveform for the <space> character.
f. Find message length by computing ACF.
g. Decode the message by cross-correlating character-length segments
of cdat against complex waveforms for each possible character.
h. If ping is long enough, try folding the data and determining the
best-fit characters as above.
3. Parameters of fast modes:
+--------------------+-----------------------+-------------------+
| | Meteor Scatter | IonoScatter |
| | FSK441 JTMS JTMSK | JT6M ISCAT |
+--------------------+-----------------------+-------------------|
| T/R period (s) | 30 30 30 | 30 30 |
| Modulation type | 4-FSK MSK MSK | 44-FSK 41-FSK |
| Keying rate (baud) | 441 1378 2000 | 21.5 43.1 |
| Bit rate (bps) | 882 1378 2000 | - - |
| Characters/s | 147 197 286 | 14.3 32.3 |
| Bandwidth (Hz) | 1764 1378 2000 | 947 1809 |
+--------------------+-----------------------+-------------------+

View File

@ -65,6 +65,7 @@ subroutine symspec(k,ntrperiod,nsps,ndiskdat,nb,nbslider,pxdb,s,f0a,df3, &
k1=0 k1=0
k8=0 k8=0
x2=0. x2=0.
if(ndiskdat.eq.0) id2(k+1:60*ntrperiod*12000)=0
endif endif
k0=k k0=k
@ -99,14 +100,9 @@ subroutine symspec(k,ntrperiod,nsps,ndiskdat,nb,nbslider,pxdb,s,f0a,df3, &
npts8=k8 npts8=k8
ja=ja+jstep !Index of first sample ja=ja+jstep !Index of first sample
if(ja.lt.0 .or. npts8.lt.ja+nfft3) go to 999 nsum=nblks*kstep1 - nzap
do i=0,nfft3-1 !Copy data into cx
cx(i)=c0(ja+i+1)
enddo
!### !###
! if(nzap/178.lt.50 .and. (ndiskdat.eq.0 .or. ihsym.lt.280)) then ! if(nzap/178.lt.50 .and. (ndiskdat.eq.0 .or. ihsym.lt.280)) then
nsum=nblks*kstep1 - nzap
if(nsum.le.0) nsum=1 if(nsum.le.0) nsum=1
rms=sqrt(0.5*px/nsum) rms=sqrt(0.5*px/nsum)
! endif ! endif
@ -114,30 +110,36 @@ subroutine symspec(k,ntrperiod,nsps,ndiskdat,nb,nbslider,pxdb,s,f0a,df3, &
if(rms.gt.0.0) pxdb=20.0*log10(rms) if(rms.gt.0.0) pxdb=20.0*log10(rms)
if(pxdb.gt.60.0) pxdb=60.0 if(pxdb.gt.60.0) pxdb=60.0
!### !###
! if(ja.lt.0 .or. npts8.lt.ja+nfft3) go to 999
if(ja.gt.0) then
do i=0,nfft3-1 !Copy data into cx
cx(i)=c0(ja+i+1)
enddo
ihsym=ihsym+1 ihsym=ihsym+1
cx(0:nfft3-1)=w3(1:nfft3)*cx(0:nfft3-1) !Apply window w3 cx(0:nfft3-1)=w3(1:nfft3)*cx(0:nfft3-1) !Apply window w3
call four2a(cx,nfft3,1,1,1) !Third forward FFT (X) call four2a(cx,nfft3,1,1,1) !Third forward FFT (X)
n=min(184,ihsym) n=min(184,ihsym)
df3=1500.0/nfft3 df3=1500.0/nfft3
i0=nint(-500.0/df3) i0=nint(-500.0/df3)
iz=min(NSMAX,nint(1000.0/df3)) iz=min(NSMAX,nint(1000.0/df3))
fac=(1.0/nfft3)**2 fac=(1.0/nfft3)**2
do i=1,iz do i=1,iz
j=i0+i-1 j=i0+i-1
if(j.lt.0) j=j+nfft3 if(j.lt.0) j=j+nfft3
sx=fac*(real(cx(j))**2 + aimag(cx(j))**2) sx=fac*(real(cx(j))**2 + aimag(cx(j))**2)
ss(n,i)=sx ss(n,i)=sx
savg(i)=savg(i) + sx savg(i)=savg(i) + sx
s(i)=sx s(i)=sx
enddo enddo
endif
999 continue 999 continue
! write(71,3003) k,nsum,nzap,px,rms,pxdb ! write(71,*) ja,npts8,ja,ja+nfft3,px,rms,pxdb
!3003 format(3i10,3f12.2) !3003 format(5i9,3f11.0)
! flush(71) ! flush(71)
return return
end subroutine symspec end subroutine symspec

View File

@ -1,35 +0,0 @@
program tastro
implicit real*8 (a-h,o-z)
character grid*6
character*9 cauxra,cauxdec
character*12 clock(3)
integer nt(8)
equivalence (nt(1),nyear)
grid='FN20qi'
nfreq=144
cauxra='00:00:00'
10 call date_and_time(clock(1),clock(2),clock(3),nt)
ih=ihour-ntz/60
if(ih.le.0) then
ih=ih+24
nday=nday+1
endif
uth8=ih + imin/60.d0 + isec/3600.d0 + ims/3600000.d0
call astro0(nyear,month,nday,uth8,nfreq,grid,cauxra,cauxdec, &
AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8,ntsky,ndop,ndop00, &
dbMoon8,RAMoon8,DecMoon8,HA8,Dgrd8,sd8,poloffset8,xnr8,dfdt,dfdt0, &
RaAux8,DecAux8,AzAux8,ElAux8,width1,width2,w501,w502,xlst8)
write(*,1010) nyear,month,nday,ih,imin,isec,AzMoon8,ElMoon8, &
AzSun8,ElSun8,ndop,dgrd8,ntsky
1010 format(i4,i3,i3,i4.2,':',i2.2,':',i2.2,4f8.1,i6,f6.1,i6)
call system('sleep 1')
go to 10
end program tastro

View File

@ -35,7 +35,8 @@ subroutine timf2(x0,k,nfft,nwindow,nb,peaklimit,faclim,x1, &
equivalence (x,cx),(xw,cxw),(xs,cxs) equivalence (x,cx),(xw,cxw),(xs,cxs)
data first/.true./ data first/.true./
data k0/99999999/ data k0/99999999/
save w,xsov,xwov,s,ntc,ntot,nh,kstep,fac,first,k0 ! save w,xsov,xwov,s,ntc,ntot,nh,kstep,fac,first,k0
save
if(first) then if(first) then
pi=4.0*atan(1.0) pi=4.0*atan(1.0)

View File

@ -42,11 +42,11 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionBlue->setActionGroup(paletteGroup); ui->actionBlue->setActionGroup(paletteGroup);
QActionGroup* modeGroup = new QActionGroup(this); QActionGroup* modeGroup = new QActionGroup(this);
ui->actionJT8_1->setActionGroup(modeGroup); ui->actionJT9_1->setActionGroup(modeGroup);
ui->actionJT8_2->setActionGroup(modeGroup); ui->actionJT9_2->setActionGroup(modeGroup);
ui->actionJT8_5->setActionGroup(modeGroup); ui->actionJT9_5->setActionGroup(modeGroup);
ui->actionJT8_10->setActionGroup(modeGroup); ui->actionJT9_10->setActionGroup(modeGroup);
ui->actionJT8_30->setActionGroup(modeGroup); ui->actionJT9_30->setActionGroup(modeGroup);
QActionGroup* saveGroup = new QActionGroup(this); QActionGroup* saveGroup = new QActionGroup(this);
ui->actionSave_all->setActionGroup(saveGroup); ui->actionSave_all->setActionGroup(saveGroup);
@ -107,7 +107,7 @@ MainWindow::MainWindow(QWidget *parent) :
m_RxLog=1; //Write Date and Time to RxLog m_RxLog=1; //Write Date and Time to RxLog
m_nutc0=9999; m_nutc0=9999;
m_NB=false; m_NB=false;
m_mode="JT8-1"; m_mode="JT9-1";
m_TRperiod=60; m_TRperiod=60;
ui->xThermo->setFillBrush(Qt::green); ui->xThermo->setFillBrush(Qt::green);
@ -129,11 +129,11 @@ MainWindow::MainWindow(QWidget *parent) :
genStdMsgs("-30"); genStdMsgs("-30");
on_actionWide_Waterfall_triggered(); //### on_actionWide_Waterfall_triggered(); //###
if(m_mode=="JT8-1") on_actionJT8_1_triggered(); if(m_mode=="JT9-1") on_actionJT9_1_triggered();
if(m_mode=="JT8-2") on_actionJT8_2_triggered(); if(m_mode=="JT9-2") on_actionJT9_2_triggered();
if(m_mode=="JT8-5") on_actionJT8_5_triggered(); if(m_mode=="JT9-5") on_actionJT9_5_triggered();
if(m_mode=="JT8-10") on_actionJT8_10_triggered(); if(m_mode=="JT9-10") on_actionJT9_10_triggered();
if(m_mode=="JT8-30") on_actionJT8_30_triggered(); if(m_mode=="JT9-30") on_actionJT9_30_triggered();
future1 = new QFuture<void>; future1 = new QFuture<void>;
watcher1 = new QFutureWatcher<void>; watcher1 = new QFutureWatcher<void>;
@ -273,7 +273,7 @@ void MainWindow::readSettings()
"PaletteAFMHot",false).toBool()); "PaletteAFMHot",false).toBool());
ui->actionBlue->setChecked(settings.value( ui->actionBlue->setChecked(settings.value(
"PaletteBlue",false).toBool()); "PaletteBlue",false).toBool());
m_mode=settings.value("Mode","JT8-1").toString(); m_mode=settings.value("Mode","JT9-1").toString();
ui->actionNone->setChecked(settings.value("SaveNone",true).toBool()); ui->actionNone->setChecked(settings.value("SaveNone",true).toBool());
ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool()); ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool());
m_NB=settings.value("NB",false).toBool(); m_NB=settings.value("NB",false).toBool();
@ -893,7 +893,7 @@ void MainWindow::guiUpdate()
ba2msg(ba,message); ba2msg(ba,message);
ba2msg(ba,msgsent); ba2msg(ba,msgsent);
int len1=28; int len1=28;
// genjt8_(message,iwave,&nwave,len1); // genjt9_(message,iwave,&nwave,len1);
if(m_restart) { if(m_restart) {
QFile f("wsjtx_tx.log"); QFile f("wsjtx_tx.log");
f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append);
@ -1306,9 +1306,9 @@ void MainWindow::on_actionErase_wsjtx_tx_log_triggered() //Erase Tx log
} }
} }
void MainWindow::on_actionJT8_1_triggered() void MainWindow::on_actionJT9_1_triggered()
{ {
m_mode="JT8-1"; m_mode="JT9-1";
m_TRperiod=60; m_TRperiod=60;
m_nsps=6912; m_nsps=6912;
soundInThread.setPeriod(m_TRperiod,m_nsps); soundInThread.setPeriod(m_TRperiod,m_nsps);
@ -1316,12 +1316,12 @@ void MainWindow::on_actionJT8_1_triggered()
g_pWideGraph->setPeriod(m_TRperiod,m_nsps); g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
lab5->setStyleSheet("QLabel{background-color: #ff6ec7}"); lab5->setStyleSheet("QLabel{background-color: #ff6ec7}");
lab5->setText(m_mode); lab5->setText(m_mode);
ui->actionJT8_1->setChecked(true); ui->actionJT9_1->setChecked(true);
} }
void MainWindow::on_actionJT8_2_triggered() void MainWindow::on_actionJT9_2_triggered()
{ {
m_mode="JT8-2"; m_mode="JT9-2";
m_TRperiod=120; m_TRperiod=120;
m_nsps=15360; m_nsps=15360;
soundInThread.setPeriod(m_TRperiod,m_nsps); soundInThread.setPeriod(m_TRperiod,m_nsps);
@ -1329,12 +1329,12 @@ void MainWindow::on_actionJT8_2_triggered()
g_pWideGraph->setPeriod(m_TRperiod,m_nsps); g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
lab5->setStyleSheet("QLabel{background-color: #ffff00}"); lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText(m_mode); lab5->setText(m_mode);
ui->actionJT8_2->setChecked(true); ui->actionJT9_2->setChecked(true);
} }
void MainWindow::on_actionJT8_5_triggered() void MainWindow::on_actionJT9_5_triggered()
{ {
m_mode="JT8-5"; m_mode="JT9-5";
m_TRperiod=300; m_TRperiod=300;
m_nsps=40960; m_nsps=40960;
soundInThread.setPeriod(m_TRperiod,m_nsps); soundInThread.setPeriod(m_TRperiod,m_nsps);
@ -1342,12 +1342,12 @@ void MainWindow::on_actionJT8_5_triggered()
g_pWideGraph->setPeriod(m_TRperiod,m_nsps); g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
lab5->setStyleSheet("QLabel{background-color: #ffa500}"); lab5->setStyleSheet("QLabel{background-color: #ffa500}");
lab5->setText(m_mode); lab5->setText(m_mode);
ui->actionJT8_5->setChecked(true); ui->actionJT9_5->setChecked(true);
} }
void MainWindow::on_actionJT8_10_triggered() void MainWindow::on_actionJT9_10_triggered()
{ {
m_mode="JT8-10"; m_mode="JT9-10";
m_TRperiod=600; m_TRperiod=600;
m_nsps=82944; m_nsps=82944;
soundInThread.setPeriod(m_TRperiod,m_nsps); soundInThread.setPeriod(m_TRperiod,m_nsps);
@ -1355,12 +1355,12 @@ void MainWindow::on_actionJT8_10_triggered()
g_pWideGraph->setPeriod(m_TRperiod,m_nsps); g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
lab5->setStyleSheet("QLabel{background-color: #7fff00}"); lab5->setStyleSheet("QLabel{background-color: #7fff00}");
lab5->setText(m_mode); lab5->setText(m_mode);
ui->actionJT8_10->setChecked(true); ui->actionJT9_10->setChecked(true);
} }
void MainWindow::on_actionJT8_30_triggered() void MainWindow::on_actionJT9_30_triggered()
{ {
m_mode="JT8-30"; m_mode="JT9-30";
m_TRperiod=1800; m_TRperiod=1800;
m_nsps=250880; m_nsps=250880;
soundInThread.setPeriod(m_TRperiod,m_nsps); soundInThread.setPeriod(m_TRperiod,m_nsps);
@ -1368,7 +1368,7 @@ void MainWindow::on_actionJT8_30_triggered()
g_pWideGraph->setPeriod(m_TRperiod,m_nsps); g_pWideGraph->setPeriod(m_TRperiod,m_nsps);
lab5->setStyleSheet("QLabel{background-color: #97ffff}"); lab5->setStyleSheet("QLabel{background-color: #97ffff}");
lab5->setText(m_mode); lab5->setText(m_mode);
ui->actionJT8_30->setChecked(true); ui->actionJT9_30->setChecked(true);
} }
void MainWindow::on_NBcheckBox_toggled(bool checked) void MainWindow::on_NBcheckBox_toggled(bool checked)

View File

@ -101,15 +101,15 @@ private slots:
void on_actionAFMHot_triggered(); void on_actionAFMHot_triggered();
void on_actionBlue_triggered(); void on_actionBlue_triggered();
void on_actionJT8_2_triggered(); void on_actionJT9_2_triggered();
void on_actionJT8_1_triggered(); void on_actionJT9_1_triggered();
void on_actionJT8_5_triggered(); void on_actionJT9_5_triggered();
void on_actionJT8_30_triggered(); void on_actionJT9_30_triggered();
void on_actionJT8_10_triggered(); void on_actionJT9_10_triggered();
void on_NBcheckBox_toggled(bool checked); void on_NBcheckBox_toggled(bool checked);
@ -221,7 +221,7 @@ void symspec_(int* k, int* ntrperiod, int* nsps, int* ndiskdat,
int* nb, int* m_NBslider, float* px, float s[], int* nb, int* m_NBslider, float* px, float s[],
float* f0a, float* df3, int* nhsym, int* nzap, float* f0a, float* df3, int* nhsym, int* nzap,
float* slimit, uchar lstrong[]); float* slimit, uchar lstrong[]);
void genjt8_(char* msg, char* msgsent, short itone[], int* nsym, void genJT9_(char* msg, char* msgsent, short itone[], int* nsym,
int len1, int len2); int len1, int len2);
int ptt_(int* nport, int* itx, int* iptt); int ptt_(int* nport, int* itx, int* iptt);
} }

View File

@ -1152,11 +1152,11 @@ p, li { white-space: pre-wrap; }
<property name="title"> <property name="title">
<string>Mode</string> <string>Mode</string>
</property> </property>
<addaction name="actionJT8_1"/> <addaction name="actionJT9_1"/>
<addaction name="actionJT8_2"/> <addaction name="actionJT9_2"/>
<addaction name="actionJT8_5"/> <addaction name="actionJT9_5"/>
<addaction name="actionJT8_10"/> <addaction name="actionJT9_10"/>
<addaction name="actionJT8_30"/> <addaction name="actionJT9_30"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuSetup"/> <addaction name="menuSetup"/>
@ -1492,44 +1492,44 @@ p, li { white-space: pre-wrap; }
<string>FUNcube Dongle Settings</string> <string>FUNcube Dongle Settings</string>
</property> </property>
</action> </action>
<action name="actionJT8_1"> <action name="actionJT9_1">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>JT8-1</string> <string>JT9-1</string>
</property> </property>
</action> </action>
<action name="actionJT8_2"> <action name="actionJT9_2">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>JT8-2</string> <string>JT9-2</string>
</property> </property>
</action> </action>
<action name="actionJT8_5"> <action name="actionJT9_5">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>JT8-5</string> <string>JT9-5</string>
</property> </property>
</action> </action>
<action name="actionJT8_10"> <action name="actionJT9_10">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>JT8-10</string> <string>JT9-10</string>
</property> </property>
</action> </action>
<action name="actionJT8_30"> <action name="actionJT9_30">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>JT8-30</string> <string>JT9-30</string>
</property> </property>
</action> </action>
</widget> </widget>