Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/addon/doxywizard/doxywizard.cpp

Source at commit 1322 created 12 years 8 months ago.
By meklort, Add doxygen to utils folder
1#include <QtGui>
2#include "doxywizard.h"
3#include "version.h"
4#include "expert.h"
5#include "wizard.h"
6
7#ifdef WIN32
8#include <windows.h>
9#endif
10
11#define MAX_RECENT_FILES 10
12
13const int messageTimeout = 5000; //!< status bar message timeout in millisec.
14
15MainWindow &MainWindow::instance()
16{
17 static MainWindow *theInstance = new MainWindow;
18 return *theInstance;
19}
20
21MainWindow::MainWindow()
22 : m_settings(QString::fromAscii("Doxygen.org"), QString::fromAscii("Doxywizard"))
23{
24 QMenu *file = menuBar()->addMenu(tr("File"));
25 file->addAction(tr("Open..."),
26 this, SLOT(openConfig()), Qt::CTRL+Qt::Key_O);
27 m_recentMenu = file->addMenu(tr("Open recent"));
28 file->addAction(tr("Save"),
29 this, SLOT(saveConfig()), Qt::CTRL+Qt::Key_S);
30 file->addAction(tr("Save as..."),
31 this, SLOT(saveConfigAs()), Qt::SHIFT+Qt::CTRL+Qt::Key_S);
32 file->addAction(tr("Quit"),
33 this, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
34
35 QMenu *settings = menuBar()->addMenu(tr("Settings"));
36 settings->addAction(tr("Reset to factory defaults"),
37 this,SLOT(resetToDefaults()));
38 settings->addAction(tr("Use current settings at startup"),
39 this,SLOT(makeDefaults()));
40 settings->addAction(tr("Clear recent list"),
41 this,SLOT(clearRecent()));
42
43 QMenu *help = menuBar()->addMenu(tr("Help"));
44 help->addAction(tr("Online manual"),
45 this, SLOT(manual()), Qt::Key_F1);
46 help->addAction(tr("About"),
47 this, SLOT(about()) );
48
49 m_expert = new Expert;
50 m_wizard = new Wizard(m_expert->modelData());
51
52 // ----------- top part ------------------
53 QWidget *topPart = new QWidget;
54 QVBoxLayout *rowLayout = new QVBoxLayout(topPart);
55
56 // select working directory
57 QHBoxLayout *dirLayout = new QHBoxLayout;
58 m_workingDir = new QLineEdit;
59 m_selWorkingDir = new QPushButton(tr("Select..."));
60 dirLayout->addWidget(m_workingDir);
61 dirLayout->addWidget(m_selWorkingDir);
62
63 //------------- bottom part --------------
64 QWidget *runTab = new QWidget;
65 QVBoxLayout *runTabLayout = new QVBoxLayout(runTab);
66
67 // run doxygen
68 QHBoxLayout *runLayout = new QHBoxLayout;
69 m_run = new QPushButton(tr("Run doxygen"));
70 m_run->setEnabled(false);
71 m_runStatus = new QLabel(tr("Status: not running"));
72 m_saveLog = new QPushButton(tr("Save log..."));
73 m_saveLog->setEnabled(false);
74 QPushButton *showSettings = new QPushButton(tr("Show configuration"));
75 runLayout->addWidget(m_run);
76 runLayout->addWidget(m_runStatus);
77 runLayout->addStretch(1);
78 runLayout->addWidget(showSettings);
79 runLayout->addWidget(m_saveLog);
80
81 // output produced by doxygen
82 runTabLayout->addLayout(runLayout);
83 runTabLayout->addWidget(new QLabel(tr("Output produced by doxygen")));
84 QGridLayout *grid = new QGridLayout;
85 m_outputLog = new QTextEdit;
86 m_outputLog->setReadOnly(true);
87 m_outputLog->setFontFamily(QString::fromAscii("courier"));
88 m_outputLog->setMinimumWidth(600);
89 grid->addWidget(m_outputLog,0,0);
90 grid->setColumnStretch(0,1);
91 grid->setRowStretch(0,1);
92 QHBoxLayout *launchLayout = new QHBoxLayout;
93 m_launchHtml = new QPushButton(tr("Show HTML output"));
94 launchLayout->addWidget(m_launchHtml);
95
96 launchLayout->addStretch(1);
97 grid->addLayout(launchLayout,1,0);
98 runTabLayout->addLayout(grid);
99
100 QTabWidget *tabs = new QTabWidget;
101 tabs->addTab(m_wizard,tr("Wizard"));
102 tabs->addTab(m_expert,tr("Expert"));
103 tabs->addTab(runTab,tr("Run"));
104
105 rowLayout->addWidget(new QLabel(tr("Step 1: Specify the working directory from which doxygen will run")));
106 rowLayout->addLayout(dirLayout);
107 rowLayout->addWidget(new QLabel(tr("Step 2: Configure doxygen using the Wizard and/or Expert tab, then switch to the Run tab to generate the documentation")));
108 rowLayout->addWidget(tabs);
109
110 setCentralWidget(topPart);
111 statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout);
112
113 m_runProcess = new QProcess;
114 m_running = false;
115 m_timer = new QTimer;
116
117 // connect signals and slots
118 connect(tabs,SIGNAL(currentChanged(int)),SLOT(selectTab(int)));
119 connect(m_selWorkingDir,SIGNAL(clicked()),SLOT(selectWorkingDir()));
120 connect(m_recentMenu,SIGNAL(triggered(QAction*)),SLOT(openRecent(QAction*)));
121 connect(m_workingDir,SIGNAL(returnPressed()),SLOT(updateWorkingDir()));
122 connect(m_runProcess,SIGNAL(readyReadStandardOutput()),SLOT(readStdout()));
123 connect(m_runProcess,SIGNAL(finished(int, QProcess::ExitStatus)),SLOT(runComplete()));
124 connect(m_timer,SIGNAL(timeout()),SLOT(readStdout()));
125 connect(m_run,SIGNAL(clicked()),SLOT(runDoxygen()));
126 connect(m_launchHtml,SIGNAL(clicked()),SLOT(showHtmlOutput()));
127 connect(m_saveLog,SIGNAL(clicked()),SLOT(saveLog()));
128 connect(showSettings,SIGNAL(clicked()),SLOT(showSettings()));
129 connect(m_expert,SIGNAL(changed()),SLOT(configChanged()));
130
131 loadSettings();
132 updateLaunchButtonState();
133 m_modified = false;
134 updateTitle();
135 m_wizard->refresh();
136}
137
138void MainWindow::closeEvent(QCloseEvent *event)
139{
140 if (discardUnsavedChanges())
141 {
142 saveSettings();
143 event->accept();
144 }
145 else
146 {
147 event->ignore();
148 }
149}
150
151void MainWindow::quit()
152{
153 if (discardUnsavedChanges())
154 {
155 saveSettings();
156 }
157 QApplication::exit(0);
158}
159
160void MainWindow::setWorkingDir(const QString &dirName)
161{
162 QDir::setCurrent(dirName);
163 m_workingDir->setText(dirName);
164 m_run->setEnabled(!dirName.isEmpty());
165}
166
167void MainWindow::selectWorkingDir()
168{
169 QString dirName = QFileDialog::getExistingDirectory(this,
170 tr("Select working directory"),m_workingDir->text());
171 if (!dirName.isEmpty())
172 {
173 setWorkingDir(dirName);
174 }
175}
176
177void MainWindow::updateWorkingDir()
178{
179 setWorkingDir(m_workingDir->text());
180}
181
182void MainWindow::manual()
183{
184 QDesktopServices::openUrl(QUrl(QString::fromAscii("http://www.doxygen.org/manual.html")));
185}
186
187void MainWindow::about()
188{
189 QString msg;
190 QTextStream t(&msg,QIODevice::WriteOnly);
191 t << QString::fromAscii("<qt><center>A tool to configure and run doxygen version ")+
192 QString::fromAscii(versionString)+
193 QString::fromAscii(" on your source files.</center><p><br>"
194 "<center>Written by<br> Dimitri van Heesch<br>&copy; 2000-2010</center><p>"
195 "</qt>");
196 QMessageBox::about(this,tr("Doxygen GUI"),msg);
197}
198
199void MainWindow::openConfig()
200{
201 if (discardUnsavedChanges(false))
202 {
203 QString fn = QFileDialog::getOpenFileName(this,
204 tr("Open configuration file"),
205 m_workingDir->text());
206 if (!fn.isEmpty())
207 {
208 loadConfigFromFile(fn);
209 }
210 }
211}
212
213void MainWindow::updateConfigFileName(const QString &fileName)
214{
215 if (m_fileName!=fileName)
216 {
217 m_fileName = fileName;
218 QString curPath = QFileInfo(fileName).path();
219 setWorkingDir(curPath);
220 addRecentFile(fileName);
221 updateTitle();
222 }
223}
224
225void MainWindow::loadConfigFromFile(const QString & fileName)
226{
227 m_expert->loadConfig(fileName);
228 m_wizard->refresh();
229 updateConfigFileName(fileName);
230 updateLaunchButtonState();
231 m_modified = false;
232 updateTitle();
233}
234
235void MainWindow::saveConfig(const QString &fileName)
236{
237 if (fileName.isEmpty()) return;
238 QFile f(fileName);
239 if (!f.open(QIODevice::WriteOnly))
240 {
241 QMessageBox::warning(this,
242 tr("Error saving"),
243 tr("Error: cannot open the file ")+fileName+tr(" for writing!\n")+
244 tr("Reason given: ")+f.error());
245 return;
246 }
247 QTextStream t(&f);
248 m_expert->writeConfig(t,false);
249 updateConfigFileName(fileName);
250 m_modified = false;
251 updateTitle();
252}
253
254bool MainWindow::saveConfig()
255{
256 if (m_fileName.isEmpty())
257 {
258 return saveConfigAs();
259 }
260 else
261 {
262 saveConfig(m_fileName);
263 return true;
264 }
265}
266
267bool MainWindow::saveConfigAs()
268{
269 QString fileName = QFileDialog::getSaveFileName(this, QString(),
270 m_workingDir->text()+QString::fromAscii("/Doxyfile"));
271 if (fileName.isEmpty()) return false;
272 saveConfig(fileName);
273 return true;
274}
275
276void MainWindow::makeDefaults()
277{
278 if (QMessageBox::question(this,tr("Use current setting at startup?"),
279 tr("Do you want to save the current settings "
280 "and use them next time Doxywizard starts?"),
281 QMessageBox::Save|
282 QMessageBox::Cancel)==QMessageBox::Save)
283 {
284 //printf("MainWindow:makeDefaults()\n");
285 m_expert->saveSettings(&m_settings);
286 m_settings.setValue(QString::fromAscii("wizard/loadsettings"), true);
287 m_settings.sync();
288 }
289}
290
291void MainWindow::clearRecent()
292{
293 if (QMessageBox::question(this,tr("Clear the list of recent files?"),
294 tr("Do you want to clear the list of recently "
295 "loaded configuration files?"),
296 QMessageBox::Yes|
297 QMessageBox::Cancel)==QMessageBox::Yes)
298 {
299 m_recentMenu->clear();
300 m_recentFiles.clear();
301 for (int i=0;i<MAX_RECENT_FILES;i++)
302 {
303 m_settings.setValue(QString().sprintf("recent/config%d",i++),QString::fromAscii(""));
304 }
305 m_settings.sync();
306 }
307
308}
309
310void MainWindow::resetToDefaults()
311{
312 if (QMessageBox::question(this,tr("Reset settings to their default values?"),
313 tr("Do you want to revert all settings back "
314 "to their original values?"),
315 QMessageBox::Reset|
316 QMessageBox::Cancel)==QMessageBox::Reset)
317 {
318 //printf("MainWindow:resetToDefaults()\n");
319 m_expert->resetToDefaults();
320 m_settings.setValue(QString::fromAscii("wizard/loadsettings"), false);
321 m_settings.sync();
322 m_wizard->refresh();
323 }
324}
325
326void MainWindow::loadSettings()
327{
328 QVariant geometry = m_settings.value(QString::fromAscii("main/geometry"), QVariant::Invalid);
329 QVariant state = m_settings.value(QString::fromAscii("main/state"), QVariant::Invalid);
330 QVariant wizState = m_settings.value(QString::fromAscii("wizard/state"), QVariant::Invalid);
331 QVariant loadSettings = m_settings.value(QString::fromAscii("wizard/loadsettings"), QVariant::Invalid);
332 QVariant workingDir = m_settings.value(QString::fromAscii("wizard/workingdir"), QVariant::Invalid);
333
334 if (geometry !=QVariant::Invalid) restoreGeometry(geometry.toByteArray());
335 if (state !=QVariant::Invalid) restoreState (state.toByteArray());
336 if (wizState !=QVariant::Invalid) m_wizard->restoreState(wizState.toByteArray());
337 if (loadSettings!=QVariant::Invalid && loadSettings.toBool())
338 {
339 m_expert->loadSettings(&m_settings);
340 if (workingDir!=QVariant::Invalid && QDir(workingDir.toString()).exists())
341 {
342 setWorkingDir(workingDir.toString());
343 }
344 }
345
346 for (int i=0;i<MAX_RECENT_FILES;i++)
347 {
348 QString entry = m_settings.value(QString().sprintf("recent/config%d",i)).toString();
349 if (!entry.isEmpty() && QFileInfo(entry).exists())
350 {
351 addRecentFile(entry);
352 }
353 }
354
355}
356
357void MainWindow::saveSettings()
358{
359 QSettings settings(QString::fromAscii("Doxygen.org"), QString::fromAscii("Doxywizard"));
360
361 m_settings.setValue(QString::fromAscii("main/geometry"), saveGeometry());
362 m_settings.setValue(QString::fromAscii("main/state"), saveState());
363 m_settings.setValue(QString::fromAscii("wizard/state"), m_wizard->saveState());
364 m_settings.setValue(QString::fromAscii("wizard/workingdir"), m_workingDir->text());
365}
366
367void MainWindow::selectTab(int id)
368{
369 if (id==0) m_wizard->refresh();
370}
371
372void MainWindow::addRecentFile(const QString &fileName)
373{
374 int i=m_recentFiles.indexOf(fileName);
375 if (i!=-1) m_recentFiles.removeAt(i);
376
377 // not found
378 if (m_recentFiles.count() < MAX_RECENT_FILES) // append
379 {
380 m_recentFiles.prepend(fileName);
381 }
382 else // add + drop last item
383 {
384 m_recentFiles.removeLast();
385 m_recentFiles.prepend(fileName);
386 }
387 m_recentMenu->clear();
388 i=0;
389 foreach( QString str, m_recentFiles )
390 {
391 m_recentMenu->addAction(str);
392 m_settings.setValue(QString().sprintf("recent/config%d",i++),str);
393 }
394 for (;i<MAX_RECENT_FILES;i++)
395 {
396 m_settings.setValue(QString().sprintf("recent/config%d",i++),QString::fromAscii(""));
397 }
398}
399
400void MainWindow::openRecent(QAction *action)
401{
402 if (discardUnsavedChanges(false))
403 {
404 loadConfigFromFile(action->text());
405 }
406}
407
408void MainWindow::runDoxygen()
409{
410 if (!m_running)
411 {
412 QString doxygenPath;
413#if defined(Q_OS_MACX)
414 doxygenPath = qApp->applicationDirPath()+QString::fromAscii("/../Resources/");
415 qDebug() << tr("Doxygen path: ") << doxygenPath;
416 if ( !QFile(doxygenPath + QString::fromAscii("doxygen")).exists() )
417 {
418 // No doygen binary in the resources, if there is a system doxygen binary, use that instead
419 if ( QFile(QString::fromAscii("/usr/local/bin/doxygen")).exists() )
420 {
421 doxygenPath = QString::fromAscii("/usr/local/bin/");
422 }
423 else
424 {
425 qDebug() << tr("Can't find the doxygen command, make sure it's in your $$PATH");
426 doxygenPath = QString::fromAscii("");
427 }
428 }
429 qDebug() << tr("Getting doxygen from: ") << doxygenPath;
430#endif
431
432 m_runProcess->setReadChannel(QProcess::StandardOutput);
433 m_runProcess->setProcessChannelMode(QProcess::MergedChannels);
434 m_runProcess->setWorkingDirectory(m_workingDir->text());
435 QStringList env=QProcess::systemEnvironment();
436 // set PWD environment variable to m_workingDir
437 env.replaceInStrings(QRegExp(QString::fromAscii("^PWD=(.*)"),Qt::CaseInsensitive),
438 QString::fromAscii("PWD=")+m_workingDir->text());
439 m_runProcess->setEnvironment(env);
440
441 QStringList args;
442 args << QString::fromAscii("-b"); // make stdout unbuffered
443 args << QString::fromAscii("-"); // read config from stdin
444
445 m_outputLog->clear();
446 m_runProcess->start(doxygenPath + QString::fromAscii("doxygen"), args);
447
448 if (!m_runProcess->waitForStarted())
449 {
450 m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
451 return;
452 }
453 QTextStream t(m_runProcess);
454 m_expert->writeConfig(t,false);
455 m_runProcess->closeWriteChannel();
456
457 if (m_runProcess->state() == QProcess::NotRunning)
458 {
459 m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
460 }
461 else
462 {
463 m_saveLog->setEnabled(false);
464 m_running=true;
465 m_run->setText(tr("Stop doxygen"));
466 m_runStatus->setText(tr("Status: running"));
467 m_timer->start(1000);
468 }
469 }
470 else
471 {
472 m_running=false;
473 m_run->setText(tr("Run doxygen"));
474 m_runStatus->setText(tr("Status: not running"));
475 m_runProcess->kill();
476 m_timer->stop();
477 //updateRunnable(m_workingDir->text());
478 }
479}
480
481void MainWindow::readStdout()
482{
483 if (m_running)
484 {
485 QByteArray data = m_runProcess->readAllStandardOutput();
486 QString text = QString::fromLocal8Bit(data);
487 if (!text.isEmpty())
488 {
489 m_outputLog->append(text.trimmed());
490 }
491 }
492}
493
494void MainWindow::runComplete()
495{
496 if (m_running)
497 {
498 m_outputLog->append(tr("*** Doxygen has finished\n"));
499 }
500 else
501 {
502 m_outputLog->append(tr("*** Cancelled by user\n"));
503 }
504 m_outputLog->ensureCursorVisible();
505 m_run->setText(tr("Run doxygen"));
506 m_runStatus->setText(tr("Status: not running"));
507 m_running=false;
508 updateLaunchButtonState();
509 //updateRunnable(m_workingDir->text());
510 m_saveLog->setEnabled(true);
511}
512
513void MainWindow::updateLaunchButtonState()
514{
515 m_launchHtml->setEnabled(m_expert->htmlOutputPresent(m_workingDir->text()));
516#if 0
517 m_launchPdf->setEnabled(m_expert->pdfOutputPresent(m_workingDir->text()));
518#endif
519}
520
521void MainWindow::showHtmlOutput()
522{
523 QString indexFile = m_expert->getHtmlOutputIndex(m_workingDir->text());
524 QFileInfo fi(indexFile);
525 // TODO: the following doesn't seem to work with IE
526#ifdef WIN32
527 //QString indexUrl(QString::fromAscii("file:///"));
528 ShellExecute(NULL, L"open", fi.absoluteFilePath().utf16(), NULL, NULL, SW_SHOWNORMAL);
529#else
530 QString indexUrl(QString::fromAscii("file://"));
531 indexUrl+=fi.absoluteFilePath();
532 QDesktopServices::openUrl(QUrl(indexUrl));
533#endif
534}
535
536void MainWindow::saveLog()
537{
538 QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"),
539 m_workingDir->text()+
540 QString::fromAscii("/doxygen_log.txt"));
541 if (!fn.isEmpty())
542 {
543 QFile f(fn);
544 if (f.open(QIODevice::WriteOnly))
545 {
546 QTextStream t(&f);
547 t << m_outputLog->toPlainText();
548 statusBar()->showMessage(tr("Output log saved"),messageTimeout);
549 }
550 else
551 {
552 QMessageBox::warning(0,tr("Warning"),
553 tr("Cannot open file ")+fn+tr(" for writing. Nothing saved!"),tr("ok"));
554 }
555 }
556}
557
558void MainWindow::showSettings()
559{
560 QString text;
561 QTextStream t(&text);
562 m_expert->writeConfig(t,true);
563 m_outputLog->clear();
564 m_outputLog->append(text);
565 m_outputLog->ensureCursorVisible();
566 m_saveLog->setEnabled(true);
567}
568
569void MainWindow::configChanged()
570{
571 m_modified = true;
572 updateTitle();
573}
574
575void MainWindow::updateTitle()
576{
577 QString title = tr("Doxygen GUI frontend");
578 if (m_modified)
579 {
580 title+=QString::fromAscii(" +");
581 }
582 if (!m_fileName.isEmpty())
583 {
584 title+=QString::fromAscii(" (")+m_fileName+QString::fromAscii(")");
585 }
586 setWindowTitle(title);
587}
588
589bool MainWindow::discardUnsavedChanges(bool saveOption)
590{
591 if (m_modified)
592 {
593 QMessageBox::StandardButton button;
594 if (saveOption)
595 {
596 button = QMessageBox::question(this,
597 tr("Unsaved changes"),
598 tr("Unsaved changes will be lost! Do you want to save the configuration file?"),
599 QMessageBox::Save |
600 QMessageBox::Discard |
601 QMessageBox::Cancel
602 );
603 if (button==QMessageBox::Save)
604 {
605 return saveConfig();
606 }
607 }
608 else
609 {
610 button = QMessageBox::question(this,
611 tr("Unsaved changes"),
612 tr("Unsaved changes will be lost! Do you want to continue?"),
613 QMessageBox::Discard |
614 QMessageBox::Cancel
615 );
616 }
617 return button==QMessageBox::Discard;
618 }
619 return true;
620}
621
622//-----------------------------------------------------------------------
623
624int main(int argc,char **argv)
625{
626 QApplication a(argc,argv);
627 MainWindow &main = MainWindow::instance();
628 if (argc==2 && argv[1][0]!='-') // name of config file as an argument
629 {
630 main.loadConfigFromFile(QString::fromLocal8Bit(argv[1]));
631 }
632 else if (argc>1)
633 {
634 printf("Usage: %s [config file]\n",argv[0]);
635 exit(1);
636 }
637 main.show();
638 return a.exec();
639}
640

Archive Download this file

Revision: 1322