1 // Implementation of most LinguisticaMainWindow methods
2 // Copyright © 2009 The University of Chicago
3 #include "linguisticamainwindow.h"
10 #include <QDesktopWidget>
11 #include <QProgressBar>
12 #include <QMessageBox>
13 #include <Q3PopupMenu>
15 #include <QResizeEvent>
16 #include <QCloseEvent>
19 #include <Q3TextStream>
20 #include <Q3ValueList>
21 #include "listbuilderdialog.h"
22 #include "helpaboutdialog.h"
23 #include "verifydialog.h"
24 #include "LPreferences.h"
25 #include "GraphicView.h"
26 #include "GUIclasses.h"
27 #include "gui/Status.h"
28 #include "Sequencer.h"
29 #include "DLHistory.h"
33 #include "MiniLexicon.h"
35 #include "Signature.h"
37 #include "SignatureCollection.h"
38 #include "TemplateCollection.h"
39 #include "SuffixCollection.h"
40 #include "PrefixCollection.h"
41 #include "StemCollection.h"
42 #include "WordCollection.h"
43 #include "CommandLine.h"
48 // command-line argument parsing helper
49 struct command_line_args
{
50 QString corpus
, logFile
, goldStdFile
, outputDir
, error
;
57 command_line_args() : mini(false),
58 prefix(false), suffix(false),
59 verbose(false), count(0) { }
60 /// result is false for --help and errors
61 bool process(int argc
, char** argv
)
63 return processCommandLineArgs(argc
, argv
,
64 corpus
, count
, logFile
, goldStdFile
,
65 outputDir
, mini
, prefix
, suffix
,
71 LinguisticaMainWindow::LinguisticaMainWindow( const int argc
, char** argv
,
72 QApplication
* app
, QWidget
* parent
, Qt::WindowFlags f
)
73 : QMainWindow(parent
, f
), Ui::LinguisticaMainWindowBase(),
76 m_commandLineFlag(argc
> 1),
78 // XXX. set organization string "UChicago", application "Linguistica"
80 m_preferences(&m_Settings
),
82 m_lexicon(new CLexicon(this)),
93 m_logFileName(m_Settings
.value(
94 "/linguistica.uchicago.edu/Linguistica/MainWindow/LogFile/FileName",
95 QString("C:\\.txt")).value
<QString
>()),
98 // Status/Progress bar
101 m_progressText1(), m_progressText2(),
103 m_counterDisplayFlag(false),
107 m_projectDirectory(m_Settings
.value(
108 "/linguistica.uchicago.edu/Linguistica/Project/Directory",
109 QString()).value
<QString
>()),
111 m_projectDirty(false), // No changes yet
113 m_corpusFileName(m_Settings
.value(
114 "/linguistica.uchicago.edu/Linguistica/MainWindow/FileMenu/Open",
115 QString()).value
<QString
>()),
116 m_goldStdFileName(m_Settings
.value(
117 "/linguistica.uchicago.edu/Linguistica/MainWindow/DiagnosticsMenu/NewGoldStdFile",
118 QString()).value
<QString
>()),
119 m_goldStdOutputFile(),
121 m_EncodingType(m_Settings
.value(
122 "/linguistica.uchicago.edu/Linguistica/MainWindow/Encoding/EncodingType",
123 QString()).value
<QString
>()),
125 m_eastFont(m_preferences
.GetFontPreference("Main")),
128 // String edit distance
130 m_Words_InitialTemplates(), m_Words_Templates(),
131 m_Sequencer(new CSequencer
),
132 m_Stats(new CStats(this)),
134 m_SmallCanvas(new Q3Canvas(10, 10)),
135 m_SmallGraphicDisplay(), // initialized below
136 m_SmallGraphicDisplayVBox()
141 command_line_args args
;
142 if (m_commandLineFlag
&& !args
.process(argc
, argv
)) {
143 printf("%s", args
.error
.ascii());
149 setCaption("Linguistica " + QString(LXA_VERSION
));
152 // Set up the status bars
154 using linguistica::ui::qt::status_interface
;
156 auto_ptr
<QLabel
> statusBar1(new QLabel(this));
157 auto_ptr
<QLabel
> statusBar2(new QLabel(this));
158 auto_ptr
<QProgressBar
> progressBar(new QProgressBar
);
159 m_status
= auto_ptr
<status_interface
>(new status_interface(
160 *statusBar1
.get(), *statusBar2
.get(), *progressBar
.get()));
162 statusBar1
->setMaximumWidth(250);
163 progressBar
->setMaximumWidth(250);
164 statusBar2
->setMaximumWidth(250);
165 statusBar()->addPermanentWidget(statusBar1
.release(), 33);
166 statusBar()->addPermanentWidget(progressBar
.release(), 33);
167 statusBar()->addPermanentWidget(statusBar2
.release(), 33);
170 m_commandLine
->setWordWrap( Q3TextEdit::NoWrap
);
172 // Toolbars and Status Bar visible
173 viewToolbarsAction
->setOn(true);
174 viewStatusBarAction
->setOn(true);
177 auto_ptr
<Q3PopupMenu
> help(new Q3PopupMenu(this));
178 // Web links in windows version only
179 auto_ptr
<Q3PopupMenu
> links(new Q3PopupMenu(this));
180 links
->insertItem( "&John Goldsmith", this, SLOT(jgWebLinksActionSlot()) );
181 links
->insertItem( "&Linguistica", this, SLOT(lxaWebLinksActionSlot()) );
182 help
->insertItem( "&Web Links", links
.release() );
183 help
->insertSeparator();
184 help
->insertItem( "&About", this, SLOT( helpAboutSlot() ) );
185 menuBar()->insertItem( "&Help", help
.release() );
189 // memory owned by m_SmallGraphicDisplayTab
190 m_SmallGraphicDisplay
= new GraphicView(m_SmallCanvas
,
191 NULL
, m_SmallGraphicDisplayTab
);
192 m_SmallGraphicDisplayTab
->layout()->addWidget(m_SmallGraphicDisplay
);
195 this->pImgLabel
= new QLabel
;
196 this->pImgLabel
->setSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Expanding
);
197 this->pImgLabel
->setAlignment(Qt::AlignCenter
);
198 this->pImgLabel
->setMinimumSize(240, 160);
199 QVBoxLayout
* smGraphicDisplayLayout
= new QVBoxLayout
;
200 smGraphicDisplayLayout
->addWidget(pImgLabel
);
201 m_SmallGraphicDisplay
->setLayout(smGraphicDisplayLayout
);
204 // Get all user settings and preferences
206 m_Settings
.beginGroup("/linguistica.uchicago.edu/Linguistica");
208 setMinimumSize(800, 600);
210 m_Settings
.beginGroup("Geometry");
211 if (m_Settings
.contains("Width") &&
212 m_Settings
.contains("Height") &&
213 m_Settings
.contains("X_Pos") &&
214 m_Settings
.contains("Y_Pos")) {
215 QSize
sz(m_Settings
.value("Width").value
<int>(),
216 m_Settings
.value("Height").value
<int>());
217 QPoint
loc(m_Settings
.value("X_Pos").value
<int>(),
218 m_Settings
.value("Y_Pos").value
<int>());
225 m_Settings
.endGroup();
228 // Hack: ensure that if the window closed maximized, the next
229 // time it opens it will be maximized again and when
230 // un-maximized it will return to the last remembered
231 // un-maximized size and position.
233 // If the remembered position was large, the window
234 // probably closed maximized.
235 const bool maximized
= QApplication::desktop()->width() < width()+10 ||
236 QApplication::desktop()->height() < height()+30;
239 m_Settings
.beginGroup("Geometry");
240 if (m_Settings
.contains("Width_Old") &&
241 m_Settings
.contains("Height_Old") &&
242 m_Settings
.contains("X_Pos_Old") &&
243 m_Settings
.contains("Y_Pos_Old")) {
244 QSize
sz(m_Settings
.value("Width_Old").value
<int>(),
245 m_Settings
.value("Height_Old").value
<int>());
246 QPoint
loc(m_Settings
.value("X_Pos_Old").value
<int>(),
247 m_Settings
.value("Y_Pos_Old").value
<int>());
252 m_Settings
.endGroup();
258 m_numberOfTokens
= m_Settings
.value(
259 "Lexicon/NumberOfTokens", 10000)
262 // Set the triscreen dimensions
264 m_Settings
.beginGroup("Triscreen");
266 if (m_Settings
.contains("West") &&
267 m_Settings
.contains("East") &&
268 m_Settings
.contains("North") &&
269 m_Settings
.contains("South")) {
270 QList
<int> eastWest
, northSouth
;
273 eastWest
.append(m_Settings
.value("West").value
<int>());
275 eastWest
.append(m_Settings
.value("East").value
<int>());
278 northSouth
.append(m_Settings
.value("North").value
<int>());
280 northSouth
.append(m_Settings
.value("South").value
<int>());
282 m_eastWestSplitter
->setSizes(eastWest
);
283 m_northSouthSplitter
->setSizes(northSouth
);
286 m_Settings
.endGroup();
288 m_Settings
.endGroup();
292 // Connect signals and slots
293 connect(this, SIGNAL(updateAllViewsSignal()),
294 this, SLOT(updateTreeViewSlot()));
295 connect(this, SIGNAL(updateAllViewsSignal()),
296 this, SLOT(updateCollectionViewSlot()));
297 connect(this, SIGNAL(updateAllViewsSignal()),
298 this, SLOT(updateCommandLineSlot()));
299 connect(this, SIGNAL(updateCommandLineSignal()),
300 this, SLOT(updateCommandLineSlot()));
301 connect(this, SIGNAL(updateTreeViewSignal()),
302 this, SLOT(updateTreeViewSlot()));
303 connect(this, SIGNAL(tokensRequestedSignal()),
304 this, SLOT(tokensRequestedDialogSlot()));
308 m_treeView
->setSortColumn(-1);
309 emit
updateAllViewsSignal();
311 // Prepare collection view
312 m_collectionView
->setShowSortIndicator(true);
314 // Command line execution
315 if (!args
.corpus
.isEmpty()) {
316 m_corpusFileName
= args
.corpus
;
318 if (!args
.logFile
.isEmpty()) {
320 m_logFileName
= args
.logFile
;
323 if (!args
.goldStdFile
.isEmpty())
324 m_goldStdFileName
= args
.goldStdFile
;
326 if (!args
.outputDir
.isEmpty())
327 m_projectDirectory
= args
.outputDir
;
329 executeCommandLineArgs(args
.count
, args
.mini
,
330 args
.prefix
, args
.suffix
);
335 LinguisticaMainWindow::~LinguisticaMainWindow()
338 delete m_pSig1
; // never used
339 delete m_pSig2
; // never used
340 delete m_GUIWords
; // never used
341 // close log file (flushes buffers)
343 delete m_logFileStream
;
344 delete m_progressDialog
;
345 delete m_Words_InitialTemplates
;
346 delete m_Words_Templates
;
350 delete m_SmallCanvas
;
351 delete m_SmallGraphicDisplayVBox
; // never used
354 void LinguisticaMainWindow::enableLoggingActionSlot(bool b
)
357 emit
updateAllViewsSignal();
361 void LinguisticaMainWindow::clearLogFileActionSlot()
363 if( m_logFileStream
)
365 // Log file open, can't clear now.
366 // TODO: message to screen.
370 // Delete the file and create a new, empty one with
372 Q_ASSERT(!GetLogFileName().isEmpty());
373 m_logFile
= new QFile( GetLogFileName() );
378 *m_logFileStream
<< "";
381 emit
updateAllViewsSignal();
385 void LinguisticaMainWindow::CloseLogFile()
387 if ( !m_logFileStream
)
389 *GetLogFileStream() << "</body></html>";
390 Q_ASSERT ( !m_logging
);
391 // AfxMessageBox ("Log file is not open."); // TODO: Qt
395 Q_ASSERT ( m_logging
);
399 m_logFileStream
= NULL
;
404 void LinguisticaMainWindow::OpenLogFile()
406 if( m_logFileStream
)
408 Q_ASSERT ( m_logging
);
409 // AfxMessageBox ("Log file is already open."); // TODO: Qt
413 if( GetLogFileName().lower() == "c:\\.txt" || GetLogFileName().lower() == "none" )
415 AskUserForLogFileName();
418 m_logFile
= new QFile( GetLogFileName() );
420 if ( m_logFile
->open( QIODevice::WriteOnly
) )
422 m_logFileStream
= new QTextStream( m_logFile
);
423 m_logFileStream
->setEncoding( QTextStream::Unicode
);
425 *m_logFileStream
<< "<html><head> <meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\"/> <link rel=\"stylesheet\" type=\"text/css\" href=\"template_files/lxa.css\"/> <script charset=\"utf-8\" id=\"injection_graph_func\" src=\"template_files/injection_graph_func.js\"></script>";
426 *m_logFileStream
<< " <style type=\"text/css\">" ;
427 *m_logFileStream
<< " h1 { font-size: 250%; color: white; background-color: #1A4969; text-align: center;; font-family: Georgia, \"Times New Roman\", Times, serif }";
428 *m_logFileStream
<< " h2 { text-align: center; color: #0000FF; background-color: #E3DDAF ; font-size: 150%; margin-left:25%; margin-right:25%; }";
429 *m_logFileStream
<< " h3 { text-align: center; font-size: 120%; font-weight: bold; color: black; background-color: #21AD94 ; %border-top: thin solid #000000; border-bottom: thin solid #000000; margin-left: 0%; margin-right: 40%; padding: 0.3em; border-right: 1em solid black }" ;
430 *m_logFileStream
<< " h4 { text-align: center; font-size: 120%; color: #000000; background-color: #21AD94 ; padding: 5px; height: auto; border-left: 1em solid black; %border: thin solid #FF0000; %margin-top: 5px; %margin-bottom: 5px; margin-left: 40%; }" ;
431 *m_logFileStream
<< " h5 { color: #FF0000; background-color: #EEEEEE; font-size: 80%; text-align: center; }" ;
432 *m_logFileStream
<< " table { border-width: 4px 4px 4px 4px; border-spacing: 2px; border-style: outset outset outset outset; border-color: #1A4969 #1A4969 #1A4969 #1A4969; border-collapse: separate; background-color: rgb(255, 255, 255); margin-left: auto; margin-right: auto; margin-top: 2em; }";
433 *m_logFileStream
<< "table th { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; border-color: gray gray gray gray; background-color: white; -moz-border-radius: 3px 3px 3px 3px; }" ;
434 *m_logFileStream
<< " h4 { table td { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; border-color: gray gray gray gray; background-color: white; -moz-border-radius: 3px 3px 3px 3px; }" ;
435 *m_logFileStream
<< "</style></head><body>";
445 void LinguisticaMainWindow::newLogFileActionSlot()
447 AskUserForLogFileName();
448 emit
updateAllViewsSignal();
452 void LinguisticaMainWindow::runAllSuffixActionSlot()
454 if( m_lexicon
->GetMiniCount() )
456 // Run all suffix functions, log if desired
457 if( m_logging
) OpenLogFile();
458 m_lexicon
->FindSuffixes();
459 if( m_logging
) CloseLogFile();
461 // Update corpus words
462 m_lexicon
->DoWordUpdates();
466 // findAllomorphyAction->setEnabled(true);
469 m_projectDirty
= true;
472 emit
updateAllViewsSignal();
477 void LinguisticaMainWindow::runAllPrefixActionSlot()
479 if( m_lexicon
->GetMiniCount() )
481 // Run all prefix functions, log if desired
482 if( m_logging
) OpenLogFile();
483 m_lexicon
->FindPrefixes();
484 if( m_logging
) CloseLogFile();
486 // Update corpus words
487 m_lexicon
->DoWordUpdates();
490 m_projectDirty
= true;
493 emit
updateAllViewsSignal();
498 void LinguisticaMainWindow::AskUserForLogFileName()
502 QString lastfile
= m_Settings
.readEntry( "/linguistica.uchicago.edu/Linguistica/MainWindow/LogFile/FileName", QString::null
, &ok
);
503 m_logFileName
= Q3FileDialog::getSaveFileName( lastfile
,
504 "Text Files( *.txt );;Rich Text Files( *.rtf );;All Files( *.* )",
507 if( !m_logFileName
.isEmpty() && lastfile
!= m_logFileName
)
508 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/MainWindow/LogFile/FileName", m_logFileName
);
512 // Change font in collection view and command line only
513 void LinguisticaMainWindow::changeFontSlot()
516 QFont font
= QFontDialog::getFont( &ok
, m_eastFont
, this );
519 // Apply this font to the collection view and
520 // command line frames
522 font
= GetFontPreference( "Affix" );
523 font
.setFamily( m_eastFont
.family() );
524 font
.setPointSize( m_eastFont
.pointSize() );
525 SetFontPreference( "Affix", font
);
527 font
= GetFontPreference( "Signature" );
528 font
.setFamily( m_eastFont
.family() );
529 font
.setPointSize( m_eastFont
.pointSize() );
530 SetFontPreference( "Signature", font
);
532 font
= GetFontPreference( "Stem" );
533 font
.setFamily( m_eastFont
.family() );
534 font
.setPointSize( m_eastFont
.pointSize() );
535 SetFontPreference( "Stem", font
);
537 font
= GetFontPreference( "Word" );
538 font
.setFamily( m_eastFont
.family() );
539 font
.setPointSize( m_eastFont
.pointSize() );
540 SetFontPreference( "Word", font
);
542 emit
updateAllViewsSignal();
546 // the user canceled the dialog; font is set
547 // to the application's default font
551 // Called before closing the main window
552 void LinguisticaMainWindow::closeEvent(QCloseEvent
* close
)
554 if (m_commandLineFlag
) {
561 // Record triscreen position before closing
562 Q3ValueList
<int> eastWest
= m_eastWestSplitter
->sizes(),
563 northSouth
= m_northSouthSplitter
->sizes();
565 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Triscreen/West", eastWest
.first() );
566 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Triscreen/East", eastWest
.last() );
567 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Triscreen/North", northSouth
.first() );
568 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Triscreen/South", northSouth
.last() );
570 // Verify information saved
571 QString notifications
= GetPreference( "Notifications" );
572 if( notifications
.length() ) verify
= GetPreference( "Notifications" ).toInt();
575 if ( verify
&& m_projectDirty
) {
576 QString message
= "Would you like to save your changes before closing?";
577 VerifyDialog
*saveCheckDlg
= new VerifyDialog(message
);
578 saveCheckDlg
->setCaption( saveCheckDlg
->caption() + "Save Project?" );
580 switch( saveCheckDlg
->exec() )
583 // User clicked 'Yes', save changes and close
584 saveFileActionSlot();
585 if ( m_projectDirty
) close
->ignore();
586 else close
->accept();
589 // User clicked 'No', close without saving
594 // User clicked 'Cancel', do not close
600 // allow the window to close
605 // Called whenever the window is resized, includes maximizing,
606 // normalizing, opening and closing the window
607 void LinguisticaMainWindow::resizeEvent( QResizeEvent
*resize
)
609 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Width", resize
->size().width() );
610 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Height", resize
->size().height() );
612 // If old size and new size are different, update old size
613 if( resize
->size().width() != resize
->oldSize().width() )
614 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Width_Old", resize
->oldSize().width() );
615 if( resize
->size().width() != resize
->oldSize().width() )
616 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Height_Old", resize
->oldSize().height() );
620 // Called whenever the window is moved, includes maximizing,
621 // normalizing, opening and closing the window
622 void LinguisticaMainWindow::moveEvent( QMoveEvent
*move
)
625 int x_max
= QApplication::desktop()->width() - ( width() + 10 );
626 int y_max
= QApplication::desktop()->height() - ( height() + 30 );
629 if( x
> x_max
) x
= x_max
;
632 if( y
> y_max
) y
= y_max
;
634 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/X_Pos", x
);
635 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Y_Pos", y
);
637 // If old position and new position are different, update old position.
638 if( move
->pos().x() != move
->oldPos().x() || move
->pos().y() != move
->oldPos().y() )
640 x
= move
->oldPos().x();
642 if( x
> x_max
) x
= x_max
;
643 y
= move
->oldPos().y();
645 if( y
> y_max
) y
= y_max
;
647 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/X_Pos_Old", x
);
648 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Geometry/Y_Pos_Old", y
);
652 void LinguisticaMainWindow::tokensRequestedDialogSlot()
655 int amount
= QInputDialog::getInteger(this, "Linguistica",
656 "Number of tokens requested:", m_numberOfTokens
,
657 0, std::numeric_limits
<int>::max(), 1, &ok
);
659 if (!ok
|| amount
== 0)
663 // user entered something and pressed OK
664 m_numberOfTokens
= amount
;
665 m_Settings
.writeEntry("/linguistica.uchicago.edu/Linguistica/"
666 "Lexicon/NumberOfTokens", amount
);
668 m_collectionView
->clear();
670 emit
updateTreeViewSignal();
673 void LinguisticaMainWindow::newFileActionSlot()
678 // Verify information saved before overwrite
679 bool notifications
= GetPreference( "Notifications" ).toInt();
680 if( notifications
&& m_projectDirty
)
682 QString message
= "This action will overwrite your data. Would you like to\nsave your changes first?";
683 VerifyDialog
*saveCheckDlg
= new VerifyDialog(message
);
684 saveCheckDlg
->setCaption( saveCheckDlg
->caption() + "Save Project?" );
686 switch( saveCheckDlg
->exec() )
689 // User clicked 'Yes', save changes and continue
690 saveFileActionSlot();
691 if( m_projectDirty
) return;
694 // User clicked 'No', continue
698 // User clicked 'Cancel', just return
704 // Dialog for lexicon file
705 QString lastfile
= m_Settings
.readEntry( "/linguistica.uchicago.edu/Linguistica/MainWindow/FileMenu/Open", QString::null
, &ok
);
706 QString filename
= Q3FileDialog::getOpenFileName( lastfile
, "Text Files( *.txt );;Rich Text Files( *.rtf );;All Files( *.* )" );
707 if( !filename
.isEmpty() ){
708 if( lastfile
!= filename
) m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/MainWindow/FileMenu/Open", filename
);
710 m_corpusFileName
= filename
;
712 // Read the lexicon and activate other functions
713 // if successful. Log if desired.
714 m_lexicon
->ClearAll();
715 if( m_logging
) OpenLogFile();
716 result
= m_lexicon
->ReadCorpus( filename
, GetNumberOfTokens() );
717 if( m_logging
) CloseLogFile();
720 // runAllAction->setEnabled(true);
721 rereadCorpusAction
->setEnabled( true );
725 // if( runAllAction->isEnabled() ) runAllAction->setEnabled(false);
726 if( rereadCorpusAction
->isEnabled() ) rereadCorpusAction
->setEnabled(false);
729 // Update corpus words
730 m_lexicon
->DoWordUpdates();
733 m_projectDirty
= true;
736 // Set the filter for graphic display and anything else if necessary
737 m_SmallGraphicDisplay
->SetFilter( m_lexicon
->GetOutFilter() );
739 // Clear the collection view
740 m_collectionView
->clear();
744 emit
updateAllViewsSignal();
748 void LinguisticaMainWindow::SetUpNewLexicon()
750 // int count = m_lexicon->GetNumberOfWords();
752 m_lexicon
= new CLexicon(this);
753 // m_lexicon->SetNumberOfWords( count );
756 GetStringListPreference( "Character_Combinations", &items
);
757 m_lexicon
->SetFilters( &items
);
760 void LinguisticaMainWindow::openFileActionSlot()
762 linguistica::ui::status_user_agent
& status
= status_display();
769 int SlashLoc
, DotLoc
, i
, j
;
775 CorpusFileName
= Q3FileDialog::getOpenFileName( m_projectDirectory
,
776 "Project files (*.prj);;All files (*.*)",
779 "Choose a project to open" );
781 if( CorpusFileName
!= QString::null
)
783 SlashLoc
= CorpusFileName
.findRev ('\\');
784 if( SlashLoc
< 0 ) SlashLoc
= CorpusFileName
.findRev('/');
785 Directory
= CorpusFileName
.left( SlashLoc
+ 1 );
787 setProjectDirectory( Directory
);
789 FileName
= CorpusFileName
.mid (SlashLoc
+1);
790 DotLoc
= FileName
.findRev ('.');
791 if( DotLoc
< 0 ) return;
793 ProjectName
= FileName
.left(DotLoc
);
794 ProjectFileName
= Directory
+ ProjectName
+ ".prj";
796 int miniCount
= m_lexicon
->ReadProjectFile( ProjectFileName
);
798 for( i
=0; i
< miniCount
; i
++ )
800 j
= m_lexicon
->NewMiniLexicon();
802 mini
= m_lexicon
->GetMiniLexicon(i
);
804 QString Prefix
= Directory
+ ProjectName
+ "_";
805 QString SuffixFileName
= Prefix
+ QString("Mini%1_").arg(i
+1) + "Suffixes.txt";
806 QString PrefixFileName
= Prefix
+ QString("Mini%1_").arg(i
+1) + "Prefixes.txt";
807 QString SignatureFileName
= Prefix
+ QString("Mini%1_").arg(i
+1) + "Signatures.txt";
808 QString StemFileName
= Prefix
+ QString("Mini%1_").arg(i
+1) + "Stems.txt";
809 QString WordFileName
= Prefix
+ QString("Mini%1_").arg(i
+1) + "Words.txt";
811 // must precede signatures.
812 status
.major_operation
= "Reading suffixes...";
813 mini
->GetSuffixes()->ReadSuffixFile( SuffixFileName
);
815 if (mini
->GetSuffixes()->GetCount() == 0) {
816 // must precede signatures.
817 status
.major_operation
= "Reading prefixes...";
818 mini
->SetAffixLocation(STEM_INITIAL
);
819 mini
->GetPrefixes()->ReadPrefixFile(PrefixFileName
);
822 // must follow suffixes.
823 status
.major_operation
= "Reading signatures...";
824 mini
->GetSignatures()->ReadSignatureFile(SignatureFileName
, mini
->GetAffixLocation());
826 // must follow signatures
827 // but also must precede signatures
828 // for signatures to get their stem lists... too bad.
829 status
.major_operation
= "Reading stems...";
830 mini
->GetStems()->ReadStemFile(StemFileName
, mini
->GetAffixLocation());
832 status
.major_operation
= "Reading signatures (verbose)...";
833 mini
->GetSignatures()->ReadSignatureFileBis(SignatureFileName
);
835 status
.major_operation
= "Reading words...";
836 mini
->GetWords()->ReadWordFile(WordFileName
);
837 status
.major_operation
.clear();
839 // XXX. read corpus words
840 emit
updateAllViewsSignal();
844 void LinguisticaMainWindow::saveAsFileActionSlot()
850 // Notify about large number of files
852 QString notifications
= GetPreference( "Notifications" );
853 if( notifications
.length() ) notify
= GetPreference( "Notifications" ).toInt();
858 QString message
= "Linguistica saves your project in a large number of 'readable' text\nfiles. We suggest you create a new folder in which to save them.";
859 QMessageBox::information ( this, "Linguistica : Save File", message
);
862 QString FileName
= Q3FileDialog::getSaveFileName( m_projectDirectory
+ m_projectName
,
863 "Linguistica Projects (*.prj)",
866 "Choose a folder to save under" );
868 if (FileName
.length() == 0 ) return;
870 SlashLoc
= FileName
.findRev ('\\');
871 if( SlashLoc
< 0 ) SlashLoc
= FileName
.findRev('/');
874 m_projectDirectory
= FileName
.left( SlashLoc
+ 1 );
875 m_Settings
.writeEntry( "/linguistica.uchicago.edu/Linguistica/Project/Directory", m_projectDirectory
);
877 m_projectName
= FileName
.mid ( SlashLoc
+ 1 );
878 NameLoc
= m_projectName
.findRev(".prj");
879 SlashLoc
= m_projectName
.findRev("_");
882 if( SlashLoc
>= 0 && SlashLoc
< NameLoc
)
884 FileName
= m_projectName
.mid( SlashLoc
+ 1, NameLoc
- SlashLoc
- 1 );
885 m_projectIndex
= FileName
.toInt();
886 m_projectName
= m_projectName
.left( SlashLoc
);
890 m_projectName
= m_projectName
.left( NameLoc
);
894 //saveFileActionSlot(); //removed so I can use in Xfst function -sw
899 void LinguisticaMainWindow::saveFileActionSlot()
901 if ( m_projectDirectory
.length() == 0 || m_projectName
.length() == 0 )
903 saveAsFileActionSlot();
904 //return; //changed flow, control returns to this func -sw
907 QString Prefix
= m_projectDirectory
+ m_projectName
+ "_" + QString("%1").arg( m_projectIndex
);
909 QString ProjectFileName
= Prefix
+ ".prj";
911 for( int i
=0; i
< m_lexicon
->GetMiniSize(); i
++ )
913 CMiniLexicon
* mini
= m_lexicon
->GetMiniLexicon(i
);
914 if( !mini
) continue;
916 QString WordsFileName
= Prefix
+ QString("_Mini%1").arg(i
+1) + "_Words.txt";
918 QString SuffixFileName
= Prefix
+ QString("_Mini%1").arg(i
+1) + "_Suffixes.txt";
919 QString PrefixFileName
= Prefix
+ QString("_Mini%1").arg(i
+1) + "_Prefixes.txt";
921 QString SignatureFileName
= Prefix
+ QString("_Mini%1").arg(i
+1) + "_Signatures.txt";
922 QString StemFileName
= Prefix
+ QString("_Mini%1").arg(i
+1) + "_Stems.txt";
924 mini
->GetWords()->OutputWords(WordsFileName
,
925 m_lexicon
->GetOutFilter());
927 if( mini
->GetAffixLocation() == WORD_FINAL
||
928 mini
->GetAffixLocation() == STEM_FINAL
)
930 mini
->GetSuffixes()->OutputSuffixes( SuffixFileName
);
933 if( mini
->GetAffixLocation() == WORD_INITIAL
||
934 mini
->GetAffixLocation() == STEM_INITIAL
)
936 mini
->GetPrefixes()->OutputPrefixes( PrefixFileName
);
939 if( mini
->GetSignatures() )
941 mini
->GetSignatures()->OutputSignatures( SignatureFileName
);
942 mini
->GetStems()->OutputStems(StemFileName
,
943 m_lexicon
->GetOutFilter());
948 m_lexicon
->OutputStats( ProjectFileName
);
950 // TODO: output corpus words
953 m_projectDirty
= false;
955 emit
updateTreeViewSignal();
958 void LinguisticaMainWindow::xfstExportActionSlot()
960 if ( m_projectDirectory
.length() == 0 || m_projectName
.length() == 0 )
961 saveAsFileActionSlot(); //get project dir and name
963 QString Prefix
= m_projectDirectory
+ m_projectName
+ "_" + QString("%1").arg( m_projectIndex
);
965 m_lexicon
->GetFSA()->OutputFSAXfst(Prefix
+"_FSA.xfst");
967 //for now commenting out this loop, will just use FSA output
968 // also note: now there is only 1 FSA at lexicon level
969 for( int i=0; i < m_lexicon->GetMiniSize(); i++ )
971 CMiniLexicon* mini = m_lexicon->GetMiniLexicon(i);
972 if( mini && mini->GetSignatures() )
974 QString XfstFileName = Prefix + QString("_Mini%1").arg(i+1) + ".xfst";
975 mini->GetSignatures()->OutputXfst( XfstFileName );
983 // "c:\\Program Files\\Internet Explorer\\iexplore.exe" on Windows?
984 const QString default_browser
= "netscape";
987 void LinguisticaMainWindow::jgWebLinksActionSlot()
989 // code taken from a Qt message board -jeremy
990 QString url
= "http://humanities.uchicago.edu/faculty/goldsmith";
991 Q3Process
*browser
= new Q3Process( this );
992 browser
->clearArguments();
993 browser
->addArgument(default_browser
);
995 if(url
.stripWhiteSpace().length() > 0)
997 browser
->addArgument(url
);
999 if( !browser
->start() )
1001 QMessageBox::critical(this, "Critical!",
1002 "Browser reports error!");
1007 void LinguisticaMainWindow::lxaWebLinksActionSlot()
1009 // code taken from a Qt message board -jeremy
1010 QString url
= "http://linguistica.uchicago.edu/linguistica.html";
1011 Q3Process
*browser
= new Q3Process( this );
1012 browser
->clearArguments();
1013 browser
->addArgument(default_browser
);
1015 if(url
.stripWhiteSpace().length() > 0)
1017 browser
->addArgument(url
);
1019 if( !browser
->start() )
1021 QMessageBox::critical(this, "Critical!",
1022 "Browser reports error!");
1028 void LinguisticaMainWindow::findAllomorphySlot()
1030 if( m_lexicon
->GetMiniCount() )
1033 if( m_logging
) OpenLogFile();
1034 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1036 current_mini
->RelateStems();
1040 // m_lexicon->FindAllomorphy();
1041 // m_lexicon->FindAllomorphy2();
1042 if( m_logging
) CloseLogFile();
1044 // Update corpus words
1045 m_lexicon
->DoWordUpdates();
1047 // Disable this functionality
1048 // if( findAllomorphyAction->isEnabled() ) findAllomorphyAction->setEnabled(false);
1051 m_projectDirty
= true;
1054 emit
updateAllViewsSignal();
1060 void LinguisticaMainWindow::showDeleteesSlot( bool b
)
1062 m_showDeleteesAction
->setOn( b
);
1063 emit
updateAllViewsSignal();
1067 void LinguisticaMainWindow::rereadCorpusSlot()
1071 if (m_corpusFileName
.isEmpty()) {
1072 // XXX. no corpus file chosen! let user know.
1076 // Verify information saved before overwrite
1077 bool notifications
= GetPreference( "Notifications" ).toInt();
1078 if( notifications
&& m_projectDirty
)
1080 QString message
= "This action will overwrite your data. Would you like to\nsave your changes first?";
1081 VerifyDialog
*saveCheckDlg
= new VerifyDialog(message
);
1082 saveCheckDlg
->setCaption( saveCheckDlg
->caption() + "Save Project?" );
1084 switch( saveCheckDlg
->exec() )
1087 // User clicked 'Yes', save changes and continue
1088 saveFileActionSlot();
1089 if( m_projectDirty
) return;
1092 // User clicked 'No', continue
1096 // User clicked 'Cancel', just return
1101 // Clear collection view
1102 m_collectionView
->clear();
1105 // Read the lexicon and activate other functions
1106 // if successful. Log if desired.
1107 if( m_logging
) OpenLogFile();
1108 Q_ASSERT(!m_corpusFileName
.isEmpty());
1109 result
= m_lexicon
->RereadCorpus( m_corpusFileName
, GetNumberOfTokens() );
1110 if( m_logging
) CloseLogFile();
1111 // if( result != -1 ) runAllAction->setEnabled(true);
1112 // else if( runAllAction->isEnabled() ) runAllAction->setEnabled(false);
1114 // Set the filter for graphic display and anything else if necessary
1115 m_SmallGraphicDisplay
->SetFilter( m_lexicon
->GetOutFilter() );
1117 // Update corpus words
1118 m_lexicon
->DoWordUpdates();
1121 m_projectDirty
= true;
1123 emit
updateAllViewsSignal();
1127 void LinguisticaMainWindow::clearLexiconSlot()
1129 // Verify information saved before overwrite
1130 bool notifications
= GetPreference( "Notifications" ).toInt();
1131 if( notifications
&& m_projectDirty
)
1133 QString message
= "This action will overwrite your data. Would you like to\nsave your changes first?";
1134 VerifyDialog
*saveCheckDlg
= new VerifyDialog(message
);
1135 saveCheckDlg
->setCaption( saveCheckDlg
->caption() + "Save Project?" );
1137 switch( saveCheckDlg
->exec() )
1140 // User clicked 'Yes', save changes and continue
1141 saveFileActionSlot();
1142 if( m_projectDirty
) return;
1145 // User clicked 'No', continue
1149 // User clicked 'Cancel', just return
1154 m_collectionView
->clear();
1156 m_lexicon
->ClearAll();
1157 m_projectDirty
= false;
1158 emit
updateAllViewsSignal();
1162 void LinguisticaMainWindow::successorFreqSlot()
1164 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1166 if( m_lexicon
->GetMiniCount() )
1168 if( isCorrectAffix( STEM_FINAL
) )
1171 // Run successor freq function, log if desired
1172 if( m_logging
) OpenLogFile();
1173 current_mini
->GetWords()->SuccessorFreq1(
1174 current_mini
->GetStems(),
1175 current_mini
->GetSuffixes(),
1176 current_mini
->GetSignatures(), SF1
,
1177 CStem::NUMBER
| CStem::UNKNOWN
);
1178 if( m_logging
) CloseLogFile();
1180 // Update corpus words
1181 m_lexicon
->DoWordUpdates();
1184 m_projectDirty
= true;
1187 emit
updateAllViewsSignal();
1191 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1192 new_mini
->SetAffixLocation( STEM_FINAL
);
1193 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1194 CMiniLexicon::WW_All
);
1195 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1196 successorFreqSlot();
1202 void LinguisticaMainWindow::predecessorFreqSlot()
1204 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1206 if( m_lexicon
->GetMiniCount() )
1208 if( isCorrectAffix( STEM_INITIAL
) )
1211 // Run predecessor freq function, log if desired
1212 if( m_logging
) OpenLogFile();
1213 current_mini
->GetWords()->CreateReverseTrie();
1214 current_mini
->GetWords()->PredecessorFreq1(
1215 current_mini
->GetStems(),
1216 current_mini
->GetPrefixes(),
1217 current_mini
->GetSignatures(),
1219 CStem::NUMBER
| CStem::UNKNOWN
);
1220 if( m_logging
) CloseLogFile();
1222 // Update corpus words
1223 m_lexicon
->DoWordUpdates();
1226 m_projectDirty
= true;
1229 emit
updateAllViewsSignal();
1233 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1234 new_mini
->SetAffixLocation( STEM_INITIAL
);
1235 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1236 CMiniLexicon::WW_All
);
1237 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1238 predecessorFreqSlot();
1244 void LinguisticaMainWindow::checkPfxSignaturesSlot()
1246 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1248 if( m_lexicon
->GetMiniCount() )
1250 if( isCorrectAffix( STEM_INITIAL
) )
1253 // Run successor freq function, log if desired
1254 if( m_logging
) OpenLogFile();
1255 current_mini
->CheckSignatures();
1257 if( m_logging
) CloseLogFile();
1259 // Update corpus words
1260 m_lexicon
->DoWordUpdates();
1263 m_projectDirty
= true;
1266 emit
updateAllViewsSignal();
1270 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1271 new_mini
->SetAffixLocation( STEM_INITIAL
);
1272 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1273 CMiniLexicon::WW_All
);
1274 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1275 checkPfxSignaturesSlot();
1280 void LinguisticaMainWindow::checkSignaturesSlot()
1282 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1284 if( m_lexicon
->GetMiniCount() )
1286 if( isCorrectAffix( STEM_FINAL
) )
1289 // Run successor freq function, log if desired
1290 if( m_logging
) OpenLogFile();
1291 m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex())->CheckSignatures();
1293 if( m_logging
) CloseLogFile();
1295 // Update corpus words
1296 // m_lexicon->DoWordUpdates();
1299 m_projectDirty
= true;
1302 emit
updateAllViewsSignal();
1306 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1307 new_mini
->SetAffixLocation( STEM_FINAL
);
1308 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1309 CMiniLexicon::WW_All
);
1310 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1311 checkSignaturesSlot();
1316 void LinguisticaMainWindow::knownStemsPrefixesSlot()
1318 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1320 if( m_lexicon
->GetMiniCount() )
1322 if( isCorrectAffix( STEM_INITIAL
) )
1325 // Run successor freq function, log if desired
1326 if( m_logging
) OpenLogFile();
1327 current_mini
->ExtendKnownStemsToKnownAffixes();
1329 if( m_logging
) CloseLogFile();
1331 // Update corpus words
1332 m_lexicon
->DoWordUpdates();
1335 m_projectDirty
= true;
1338 emit
updateAllViewsSignal();
1342 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1343 new_mini
->SetAffixLocation( STEM_INITIAL
);
1344 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1345 CMiniLexicon::WW_All
);
1346 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1347 knownStemsPrefixesSlot();
1353 void LinguisticaMainWindow::knownStemsSuffixesSlot()
1355 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1357 if( m_lexicon
->GetMiniCount() )
1359 if( isCorrectAffix( STEM_FINAL
) )
1362 // Run successor freq function, log if desired
1363 if( m_logging
) OpenLogFile();
1364 current_mini
->ExtendKnownStemsToKnownAffixes();
1366 if( m_logging
) CloseLogFile();
1368 // Update corpus words
1369 m_lexicon
->DoWordUpdates();
1372 m_projectDirty
= true;
1375 emit
updateAllViewsSignal();
1379 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1380 new_mini
->SetAffixLocation( STEM_FINAL
);
1381 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1382 CMiniLexicon::WW_All
);
1383 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1384 knownStemsSuffixesSlot();
1389 void LinguisticaMainWindow::fromPfxSigsFindStemsSlot()
1391 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1393 if( m_lexicon
->GetMiniCount() )
1395 if( isCorrectAffix( STEM_INITIAL
) )
1398 // Run successor freq function, log if desired
1399 if( m_logging
) OpenLogFile();
1400 current_mini
->TakeSignaturesFindStems();
1402 if( m_logging
) CloseLogFile();
1404 // Update corpus words
1405 m_lexicon
->DoWordUpdates();
1408 m_projectDirty
= true;
1411 emit
updateAllViewsSignal();
1415 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1416 new_mini
->SetAffixLocation( STEM_INITIAL
);
1417 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1418 CMiniLexicon::WW_All
);
1419 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1420 fromPfxSigsFindStemsSlot();
1426 void LinguisticaMainWindow::fromSigsFindStemsSlot()
1428 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1430 if( m_lexicon
->GetMiniCount() )
1432 if( isCorrectAffix( STEM_FINAL
) )
1435 // Run successor freq function, log if desired
1436 if( m_logging
) OpenLogFile();
1437 current_mini
->TakeSignaturesFindStems();
1439 if( m_logging
) CloseLogFile();
1441 // Update corpus words
1442 m_lexicon
->DoWordUpdates();
1445 m_projectDirty
= true;
1448 emit
updateAllViewsSignal();
1452 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1453 new_mini
->SetAffixLocation( STEM_FINAL
);
1454 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1455 CMiniLexicon::WW_All
);
1456 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1457 fromSigsFindStemsSlot();
1463 void LinguisticaMainWindow::fromStemsFindAffixesSlot()
1465 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1467 if( m_lexicon
->GetMiniCount() )
1469 if( isCorrectAffix( STEM_FINAL
) )
1472 // Run successor freq function, log if desired
1473 if( m_logging
) OpenLogFile();
1474 current_mini
->FromStemsFindAffixes();
1476 if( m_logging
) CloseLogFile();
1478 // Update corpus words
1479 m_lexicon
->DoWordUpdates();
1482 m_projectDirty
= true;
1485 emit
updateAllViewsSignal();
1489 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1490 new_mini
->SetAffixLocation( STEM_FINAL
);
1491 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1492 CMiniLexicon::WW_All
);
1493 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1494 fromStemsFindAffixesSlot();
1500 void LinguisticaMainWindow::findPfxSingletonSigsSlot()
1502 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1504 if( m_lexicon
->GetMiniCount() )
1506 if( isCorrectAffix( STEM_INITIAL
) )
1509 // Run successor freq function, log if desired
1510 if( m_logging
) OpenLogFile();
1511 current_mini
->FindSingletonSignatures();
1513 if( m_logging
) CloseLogFile();
1515 // Update corpus words
1516 m_lexicon
->DoWordUpdates();
1519 m_projectDirty
= true;
1522 emit
updateAllViewsSignal();
1526 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1527 new_mini
->SetAffixLocation( STEM_INITIAL
);
1528 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1529 CMiniLexicon::WW_All
);
1530 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1531 findPfxSingletonSigsSlot();
1537 void LinguisticaMainWindow::findSingletonSigsSlot()
1539 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1541 if( m_lexicon
->GetMiniCount() )
1543 if( isCorrectAffix( STEM_FINAL
) )
1546 // Run successor freq function, log if desired
1547 if( m_logging
) OpenLogFile();
1548 current_mini
->FindSingletonSignatures();
1550 if( m_logging
) CloseLogFile();
1552 // Update corpus words
1553 m_lexicon
->DoWordUpdates();
1556 m_projectDirty
= true;
1559 emit
updateAllViewsSignal();
1563 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1564 new_mini
->SetAffixLocation( STEM_FINAL
);
1565 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1566 CMiniLexicon::WW_All
);
1567 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1568 findSingletonSigsSlot();
1574 void LinguisticaMainWindow::pfxLooseFitSlot()
1576 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1578 if( m_lexicon
->GetMiniCount() )
1580 if( isCorrectAffix( STEM_INITIAL
) )
1583 // Run successor freq function, log if desired
1584 if( m_logging
) OpenLogFile();
1585 current_mini
->LooseFit();
1587 if( m_logging
) CloseLogFile();
1589 // Update corpus words
1590 m_lexicon
->DoWordUpdates();
1593 m_projectDirty
= true;
1596 emit
updateAllViewsSignal();
1600 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1601 new_mini
->SetAffixLocation( STEM_INITIAL
);
1602 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1603 CMiniLexicon::WW_All
);
1604 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1611 void LinguisticaMainWindow::looseFitSlot()
1613 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1615 if( m_lexicon
->GetMiniCount() )
1617 if( isCorrectAffix( STEM_FINAL
) )
1620 // Run successor freq function, log if desired
1621 if( m_logging
) OpenLogFile();
1622 current_mini
->LooseFit();
1624 if( m_logging
) CloseLogFile();
1626 // Update corpus words
1627 m_lexicon
->DoWordUpdates();
1630 m_projectDirty
= true;
1633 emit
updateAllViewsSignal();
1637 CMiniLexicon
* new_mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->NewMiniLexicon() );
1638 new_mini
->SetAffixLocation( STEM_FINAL
);
1639 new_mini
->AddToWordCollection(current_mini
->GetWords(),
1640 CMiniLexicon::WW_All
);
1641 m_lexicon
->SetActiveMiniIndex( new_mini
->GetIndex() );
1647 void LinguisticaMainWindow::showToolbarsSlot(bool b
)
1649 if (b
) m_Toolbar
->show();
1650 else m_Toolbar
->hide();
1654 void LinguisticaMainWindow::showStatusBarSlot(bool b
)
1656 if( b
) statusBar()->show();
1657 else statusBar()->hide();
1661 void LinguisticaMainWindow::saveBrokenCorpusSlot()
1663 QString BrokenCorpusFileName
= m_corpusFileName
.left( m_corpusFileName
.find('.') ) + "_Broken.txt";
1664 BrokenCorpusFileName
= Q3FileDialog::getSaveFileName( BrokenCorpusFileName
,
1665 "Text Documents (*.txt)",
1668 "Choose a folder to save under" );
1670 if( BrokenCorpusFileName
.length() == 0 ) return;
1672 m_lexicon
->MakeBrokenCorpus( BrokenCorpusFileName
);
1676 void LinguisticaMainWindow::helpAboutSlot()
1678 HelpAboutDialog
*helpDlg
= new HelpAboutDialog( this );
1679 if( helpDlg
->exec() == QDialog::Accepted
)
1691 void LinguisticaMainWindow::newMiniLexiconActionSlot()
1695 for( index
= m_lexicon
->GetMiniSize()-1; index
>= 0; index
-- )
1697 if( m_lexicon
->GetMiniLexicon(index
) )
1706 newFileActionSlot();
1710 // Create the new mini
1711 index
= m_lexicon
->NewMiniLexicon();
1712 m_lexicon
->SetActiveMiniIndex( index
);
1714 // Populate its words
1715 populateWordsActionSlot();
1718 QString
mini_name( "Mini-Lexicon %1" );
1719 mini_name
= mini_name
.arg( index
+ 1 );
1720 QString remark
= "Before analysis; words only";
1721 m_lexicon
->GetDLHistory()->append( mini_name
, remark
, m_lexicon
->GetMiniLexicon( index
) );
1725 void LinguisticaMainWindow::deleteMiniLexiconActionSlot()
1727 if( m_lexicon
->GetMiniCount() == 1 )
1733 int active
= m_lexicon
->GetActiveMiniIndex();
1734 m_lexicon
->DeleteMiniLexicon( active
);
1737 SetDocType( NO_DOC
);
1738 emit
updateAllViewsSignal();
1742 void LinguisticaMainWindow::autoLayeringActionSlot()
1744 if( m_lexicon
->GetMiniCount() )
1746 // Run all suffix functions, log if desired
1747 if( m_logging
) OpenLogFile();
1748 m_lexicon
->FindSuffixes( true );
1750 if( m_logging
) CloseLogFile();
1752 // Update corpus words
1753 m_lexicon
->DoWordUpdates();
1756 m_projectDirty
= true;
1759 emit
updateAllViewsSignal();
1764 void LinguisticaMainWindow::populateWordsActionSlot()
1766 int index
= m_lexicon
->GetActiveMiniIndex();
1767 CMiniLexicon
* active
, * other
;
1769 QStringList notIncluded
, included
;
1771 if( m_lexicon
->GetMiniLexicon( index
-1 ) )
1773 included
<< "Mini-Lexicon " + QString("%1").arg( index
) + " : Unanalyzed Words";
1774 included
<< "Mini-Lexicon " + QString("%1").arg( index
) + " : Stems";
1775 notIncluded
<< "Mini-Lexicon " + QString("%1").arg( index
) + " : Analyzed Words";
1777 for( int i
=0; i
< m_lexicon
->GetMiniSize(); i
++ )
1779 if( i
!= index
&& i
!= index
-1 && m_lexicon
->GetMiniLexicon(i
) )
1781 notIncluded
<< "Mini-Lexicon " + QString("%1").arg( i
+1 ) + " : Analyzed Words";
1782 notIncluded
<< "Mini-Lexicon " + QString("%1").arg( i
+1 ) + " : Unanalyzed Words";
1783 notIncluded
<< "Mini-Lexicon " + QString("%1").arg( i
+1 ) + " : Stems";
1787 ListBuilderDialog
*dlg
= new ListBuilderDialog( "Linguistica : Populate Mini-Lexicon",
1788 notIncluded
, included
, this );
1789 if( dlg
->exec() == QDialog::Accepted
)
1791 Q3ListBoxItem
* included
= dlg
->GetIncluded()->item(0);
1794 // Populate the word collection of a new mini
1795 active
= m_lexicon
->GetMiniLexicon( index
);
1798 while( active
&& included
)
1800 item
= included
->text();
1801 index
= item
.find( " :" ) - 1;
1802 index
= item
.mid( index
, 1 ).toInt() - 1;
1804 other
= m_lexicon
->GetMiniLexicon( index
);
1805 if( !other
) continue;
1807 if( item
.find( "Unanalyzed" ) >= 0 )
1809 active
->AddToWordCollection(
1810 other
->GetWords(), CMiniLexicon::WW_UnanalyzedOnly
);
1812 else if( item
.find( "Analyzed" ) >= 0 )
1814 active
->AddToWordCollection(other
->GetWords(),
1815 CMiniLexicon::WW_AnalyzedOnly
);
1817 else if( item
.find( "Stems" ) >= 0 )
1819 active
->AddToWordCollection( other
->GetStems() );
1822 included
= included
->next();
1831 emit
updateTreeViewSignal();
1835 void LinguisticaMainWindow::addToBorrowedSigsSlot()
1837 int index
= m_lexicon
->GetActiveMiniIndex();
1838 CMiniLexicon
* active
, * other
;
1840 QStringList notIncluded
, included
;
1842 if( m_lexicon
->GetMiniLexicon( index
-1 ) )
1844 included
<< "Mini-Lexicon " + QString("%1").arg( index
) + " : Signatures";
1846 for( int i
=0; i
< m_lexicon
->GetMiniSize(); i
++ )
1848 if( i
!= index
-1 && m_lexicon
->GetMiniLexicon(i
) )
1850 notIncluded
<< "Mini-Lexicon " + QString("%1").arg( i
+1 ) + " : Signatures";
1854 ListBuilderDialog
*dlg
= new ListBuilderDialog( "Linguistica : Populate Mini-Lexicon",
1855 notIncluded
, included
, this );
1856 if( dlg
->exec() == QDialog::Accepted
)
1858 Q3ListBoxItem
* included
= dlg
->GetIncluded()->item(0);
1861 // Populate the word collection of a new mini
1862 active
= m_lexicon
->GetMiniLexicon( index
);
1864 while( active
&& included
)
1866 item
= included
->text();
1867 index
= item
.find( " :" ) - 1;
1868 index
= item
.mid( index
, 1 ).toInt() - 1;
1870 other
= m_lexicon
->GetMiniLexicon( index
);
1871 if( !other
) continue;
1873 included
= included
->next();
1882 emit
updateTreeViewSignal();
1888 void LinguisticaMainWindow::RunSedSlot()
1890 QMessageBox::information( this, "Debug","Finding word neighbors","OK" );
1893 if ( m_Words_InitialTemplates
!= NULL
)
1895 QMessageBox::information( this, "Attention","You have run the SED !","OK" );
1899 // StringEdit Distance Init
1900 m_Words_InitialTemplates
= new CTemplateCollection
;
1901 m_Words_Templates
= new CTemplateCollection
;
1903 if( m_logging
) OpenLogFile();
1906 FindAllEditDistances(m_Words_InitialTemplates
);
1907 FindAllWordNeighbors(m_lexicon
);
1910 if (false) // John Goldsmith Dec 28 2008 testing what follows:
1912 CheckForConflations(m_Words_Templates
, m_Words_InitialTemplates
);
1914 // Update the Stickness
1915 m_Words_Templates
->UpdateGlobalStickNess2();
1917 // Move Common Head/Tail
1918 m_Words_Templates
->AdjustTemplatesByMovingCommonTailOrHead2(0);
1920 // Collapse algorithm 1
1921 m_Words_Templates
->CollapseAlgorithm1(1);
1923 // Then sort these templates again.
1924 m_Words_Templates
->SetSwitchOfSortingValue(true);
1925 m_Words_Templates
->SetSortValidFlag(false);
1926 m_Words_Templates
->Sort(TEMPLATE_SORT
);
1929 // Next, I tried the absorption algorithm
1930 m_Words_Templates
->AbsorbWords1(1);
1931 m_Words_Templates
->SetSwitchOfSortingValue(true);
1932 m_Words_Templates
->SetSortValidFlag(false);
1933 m_Words_Templates
->Sort(TEMPLATE_SORT
);
1936 // Next, I tried the Paradigmatic graph function
1937 m_Words_Templates
->UpdateGlobalStickNess2();
1938 m_Words_Templates
->FindMorphemePrefixOrSuffixWithParadigmaticGraph(1);
1940 // Then sort these templates again.
1941 m_Words_Templates
->SetSwitchOfSortingValue(true);
1942 m_Words_Templates
->SetSortValidFlag(false);
1943 m_Words_Templates
->Sort(TEMPLATE_SORT
);
1948 m_Words_Templates
->OutputTemplatesForGoldStand();
1949 } // end of if (FALSE);
1950 emit
updateTreeViewSignal();
1954 QMessageBox::information( this, "Attention","Lexicon is NULL","OK" );
1956 if( m_logging
) CloseLogFile();
1959 void LinguisticaMainWindow::FindSlicesSlot()
1961 if (m_lexicon
&& m_lexicon
->GetMiniCount()) {
1965 linguistica::ui::status_user_agent
& status
= status_display();
1970 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
1971 CWordCollection
* Words
= current_mini
->GetWords();
1972 SliceCollection MySlices
;
1973 StringInventory MyStringInventory
;
1975 status
.major_operation
= "Finding slices...";
1976 MyStringInventory
.addwordcollection(Words
, MySlices
, status
);
1978 MySlices
.writetolog(*GetLogFileStream());
1979 MySlices
.FindWordPairs(status
, m_lexicon
);
1982 status
.major_operation
.clear();
1985 std::cout
<< "FindSlices:: Time elapsed: " <<
1986 t
.elapsed() << "ms." << std::endl
;
1992 /////////////////////////////////////////////////////////////////
1993 void LinguisticaMainWindow::FindAllWordNeighbors(CLexicon
* MyLexicon
)
1996 MyLexicon
->GetSEDWords()->FindAllWordNeighbors(MyLexicon
);
2003 /////////////////////////////////////////////////////////////////
2004 //// FindStringEditDistance
2005 void LinguisticaMainWindow::FindAllEditDistances(CTemplateCollection
* pContainer
)
2007 pContainer
->FindAllEditDistances ( m_lexicon
, m_lexicon
->GetSEDWords()) ;
2012 void LinguisticaMainWindow::CheckForConflations(CTemplateCollection
* Target
, CTemplateCollection
* Source
)
2014 Target
->CheckForConflations(Source
);
2017 bool LinguisticaMainWindow::isCorrectAffix( eAffixLocation affixLoc
)
2019 CMiniLexicon
* mini
= m_lexicon
->GetMiniLexicon( m_lexicon
->GetActiveMiniIndex() );
2020 eAffixLocation current
= mini
->GetAffixLocation();
2022 if( current
== affixLoc
) return TRUE
;
2024 if( ( mini
->GetSuffixes() && !mini
->GetSuffixes()->GetCount() ) ||
2025 ( mini
->GetPrefixes() && !mini
->GetPrefixes()->GetCount() ) )
2027 mini
->SetAffixLocation( affixLoc
);
2035 if( current
== STEM_INITIAL
|| current
== WORD_INITIAL
) return TRUE
;
2041 if( current
== STEM_FINAL
|| current
== WORD_FINAL
) return TRUE
;
2046 void LinguisticaMainWindow::commandLineCloseSlot()
2049 void LinguisticaMainWindow::executeCommandLineArgs(int count
,
2050 bool mini
, bool prefix
, bool suffix
)
2052 if (m_corpusFileName
.isEmpty()) {
2053 // XXX. no corpus file chosen! let user know.
2057 if( count
!= 0 ) SetNumberOfTokens( count
);
2059 m_lexicon
->ClearAll();
2062 if( m_logging
) OpenLogFile();
2064 // Read words into lexicon from the corpus
2065 Q_ASSERT(!m_corpusFileName
.isEmpty());
2066 m_lexicon
->ReadCorpus(m_corpusFileName
, GetNumberOfTokens());
2070 if( suffix
) m_lexicon
->FindSuffixes( TRUE
);
2071 if( prefix
) m_lexicon
->FindPrefixes( TRUE
);
2076 if( suffix
) m_lexicon
->FindSuffixes();
2077 if( prefix
) m_lexicon
->FindPrefixes();
2081 if( m_logging
) CloseLogFile();
2083 // Clear the collection view
2084 m_collectionView
->clear();
2087 int SlashLoc
= m_corpusFileName
.findRev('\\');
2088 if( SlashLoc
< 0 ) SlashLoc
= m_corpusFileName
.findRev('/');
2090 if( m_projectDirectory
.length() == 0 ) m_projectDirectory
= m_corpusFileName
.left( SlashLoc
+ 1 );
2091 else if( m_projectDirectory
.at( m_projectDirectory
.length()-1 ) != '/' ) m_projectDirectory
= m_projectDirectory
+ "/";
2092 if( m_projectDirectory
.length() == 0 ) m_projectDirectory
= "./";
2094 m_projectName
= m_corpusFileName
.mid ( SlashLoc
+ 1 );
2095 int NameLoc
= m_projectName
.findRev(".");
2096 m_projectName
= m_projectName
.left( NameLoc
);
2099 if( m_goldStdFileName
.length() > 0 )
2101 m_goldStdOutputFile
= m_projectDirectory
+ m_projectName
+ "_GoldStandardComparison.txt";
2102 compareGoldStdSlot();
2105 saveFileActionSlot();
2108 emit
updateAllViewsSignal();
2112 // YuHu Add for output morphological cut corpus for MT
2113 // TODO: Need change after 2005/11/30 Fix after Lexicon is done
2114 void LinguisticaMainWindow::editCorpusForMT()
2118 QString FirstPiece, RemainingPiece;
2122 StringToParse* TempSedCuts;
2123 StringToParse::Iterator StringToParseIt;
2124 StringToPtrCStem SFCuts;
2125 StringToPtrCStem SedCuts;
2126 StringToCStem::Iterator SFIt;
2127 StringToCStem* TempSFCut;
2128 int Strategy; // we discussed the strategy 1, 2, 3, 4
2131 // Get the Lingustica analyses result SF or PF
2132 if ( !m_lexicon) return;
2133 TempSFCut = m_lexicon ->GetWords();
2135 for ( SFIt = TempSFCut ->begin(); SFIt != TempSFCut ->end(); SFIt++)
2137 theWord = SFIt.key();
2138 theCStem = &SFIt.data();
2139 SFCuts.insert(theWord, theCStem);
2143 if ( m_Words_Templates != NULL)
2145 TempSedCuts = m_Words_Templates ->GetParsedResult();
2146 for ( StringToParseIt = TempSedCuts ->begin(); StringToParseIt != TempSedCuts ->end(); StringToParseIt++)
2148 theWord = StringToParseIt.key();
2149 theParse = StringToParseIt.data();
2150 theCStem = new CStem(*theParse);
2151 SedCuts.insert(theWord, theCStem);
2155 // 3. Read MT Corpus File
2158 QString FileNameStrippedDot;
2159 QString outputMTFileName_SF;
2160 QString outputMTFileName_SED;
2163 MTFileName = QFileDialog::getOpenFileName( m_projectDirectory,
2167 "Choose a file to open" );
2169 if( !MTFileName.isEmpty() )
2178 FileNameStrippedDot = MTFileName.left(MTFileName.find(QString(".")));
2181 for ( Strategy =1; Strategy <=4; Strategy++)
2183 outputMTFileName_SF = FileNameStrippedDot + "_Output_SF_" + QString("%1").arg(Strategy) + ".txt";
2184 m_lexicon ->CutMtCorpusWithMorphologyAnalyses(MTFileName, outputMTFileName_SF,SFCuts,Strategy);
2187 if ( m_Words_Templates != NULL)
2189 for ( Strategy =1; Strategy <=4; Strategy++)
2191 outputMTFileName_SED = FileNameStrippedDot + "_Output_SED_" + QString("%1").arg(Strategy) + ".txt";
2192 m_Words_Templates ->CutMtCorpusWithMorphologyAnalyses(MTFileName, outputMTFileName_SED,SedCuts,Strategy);
2200 //////////////////////////////////////////////////////////////////////////////
2202 //////////////////////////////////////////////////////////////////////////////
2204 void LinguisticaMainWindow::testMultiDimensionDisplaySlot()
2206 int NumberOfSymbols
;
2209 IntToString listOfSymbols
;
2211 int NumberOfIterations
=100;
2213 NumberOfSymbols
= 4;
2216 // Update the GraphicView to Display the HMM multidimension data
2217 ptrData
= new double*[NumberOfSymbols
];
2218 for ( i
=0; i
<NumberOfSymbols
; i
++)
2220 ptrData
[i
] = new double[NumberOfStates
] ;
2223 // assign initial ptrData
2224 for(i
=0; i
<NumberOfSymbols
;i
++)
2226 listOfSymbols
.insert(i
, QString("s%1").arg(i
));
2227 for(j
=0; j
<NumberOfStates
; j
++)
2229 ptrData
[i
][j
] = 1.0 / NumberOfStates
;
2234 for (i
=0; i
<NumberOfIterations
; i
++)
2237 // Display on Graphic View
2238 updateSmallGraphicDisplaySlotForMultiDimensionData(NumberOfStates
,
2245 for(j
=0; j
<NumberOfSymbols
;j
++)
2247 ptrData
[j
][j
% NumberOfStates
] += 0.1 / NumberOfStates
;
2251 // Sleep for a short time : Is there any Qt sleep function ?
2253 for(j
=0; j
<500000; j
++)
2261 for(i
=0; i
<NumberOfSymbols
; i
++)
2263 delete [] ptrData
[i
];
2270 void LinguisticaMainWindow::goldwaterMethodSlot()
2272 QMessageBox::information ( this, "GoldwaterMethod", "Begin Goldwater Thesis Morphology Learning Algorithm!" );
2275 void LinguisticaMainWindow::suffixesCollapse_two_signaturesAction_activated()
2279 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
2280 CSignatureCollection
TheseSignatures (current_mini
);
2283 int NumberOfSignaturesSelected
= 0;
2285 // QListViewItem* selectedItem = NULL;
2287 m_collectionView
->setSelectionMode (Q3ListView::Extended
);
2289 Q3ListViewItemIterator
it( m_collectionView
);
2291 while ( it
.current() )
2293 if (it
.current()->isSelected() )
2295 NumberOfSignaturesSelected
++;
2296 CSignatureListViewItem
*item
= (CSignatureListViewItem
*) it
.current();
2297 TheseSignatures
<< item
->GetSignature();
2302 if (NumberOfSignaturesSelected
!= 2)
2304 QMessageBox::warning( m_lexicon
->GetDocument(),
2306 "Select exactly two signatures, and press command again",
2308 QMessageBox::NoButton
,
2309 QMessageBox::NoButton
);
2319 m_collectionView
->setSelectionMode (Q3ListView::Single
);
2321 void LinguisticaMainWindow::toggleMultipleSelectionSlot()
2323 if (m_collectionView
->selectionMode() == Q3ListView::Single
)
2325 m_collectionView
->setSelectionMode(Q3ListView::Extended
);
2328 m_collectionView
->setSelectionMode (Q3ListView::Single
);
2334 void LinguisticaMainWindow::addContentToCommandLine(QString content
)
2336 m_commandLine
->insert(content
);
2339 /** \page page1 The GUI: An overview
2341 \section sec The main screen
2342 This page contains the subsections \ref subsection1 and \ref subsection2.
2343 For more info see page \ref page2. Hello??
2344 \subsection subsection1 The first subsection
2346 \subsection subsection2 The second subsection
2349 ! \page page2 How strings are represented: The CParse class
2351 ! \page page3 Collection classes
2352 ! \page page4 The Lexicon class
2353 ! \page page5 A MiniLexicon: Signatures, Stems, Affixes
2358 void LinguisticaMainWindow::fsaTestFuncAction()
2360 if( m_lexicon
&& m_lexicon
->GetMiniCount())
2362 CMiniLexicon
* current_mini
= m_lexicon
->GetMiniLexicon(m_lexicon
->GetActiveMiniIndex());
2363 if(m_lexicon
->GetFSA())
2365 FSA
* pFSA
= m_lexicon
->GetFSA();
2366 pFSA
->ResetDisplay();
2367 pFSA
->FSATestFunc();
2368 pFSA
->FSAListDisplay(m_collectionView
,m_lexicon
->GetOutFilter(),false);