Orb/Doxygen/addon/doxywizard/doxywizard.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Orb/Doxygen/addon/doxywizard/doxywizard.cpp	Thu Jan 21 17:29:01 2010 +0000
@@ -0,0 +1,593 @@
+#include <QtGui>
+#include "doxywizard.h"
+#include "version.h"
+#include "expert.h"
+#include "wizard.h"
+
+const int messageTimeout = 5000; //!< status bar message timeout in millisec.
+
+MainWindow &MainWindow::instance()
+{
+  static MainWindow *theInstance = new MainWindow;
+  return *theInstance;
+}
+
+MainWindow::MainWindow()
+  : m_settings(QString::fromAscii("Doxygen.org"), QString::fromAscii("Doxywizard"))
+{
+  QMenu *file = menuBar()->addMenu(tr("File"));
+  file->addAction(tr("Open..."), 
+                  this, SLOT(openConfig()), Qt::CTRL+Qt::Key_O);
+  m_recentMenu = file->addMenu(tr("Open recent"));
+  file->addAction(tr("Save"), 
+                  this, SLOT(saveConfig()), Qt::CTRL+Qt::Key_S);
+  file->addAction(tr("Save as..."), 
+                  this, SLOT(saveConfigAs()), Qt::SHIFT+Qt::CTRL+Qt::Key_S);
+  file->addAction(tr("Quit"),  
+                  this, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
+
+  QMenu *settings = menuBar()->addMenu(tr("Settings"));
+  settings->addAction(tr("Reset to factory defaults"),
+                  this,SLOT(resetToDefaults()));
+  settings->addAction(tr("Use current settings at startup"),
+                  this,SLOT(makeDefaults()));
+
+  QMenu *help = menuBar()->addMenu(tr("Help"));
+  help->addAction(tr("Online manual"), 
+                  this, SLOT(manual()), Qt::Key_F1);
+  help->addAction(tr("About"), 
+                  this, SLOT(about()) );
+
+  m_expert = new Expert;
+  m_wizard = new Wizard(m_expert->modelData());
+
+  // ----------- top part ------------------
+  QWidget *topPart = new QWidget;
+  QVBoxLayout *rowLayout = new QVBoxLayout(topPart);
+
+  // select working directory
+  QHBoxLayout *dirLayout = new QHBoxLayout;
+  m_workingDir = new QLineEdit;
+  m_selWorkingDir = new QPushButton(tr("Select..."));
+  dirLayout->addWidget(m_workingDir);
+  dirLayout->addWidget(m_selWorkingDir);
+
+  //------------- bottom part --------------
+  QWidget *runTab = new QWidget;
+  QVBoxLayout *runTabLayout = new QVBoxLayout(runTab);
+
+  // run doxygen
+  QHBoxLayout *runLayout = new QHBoxLayout;
+  m_run = new QPushButton(tr("Run doxygen"));
+  m_run->setEnabled(false);
+  m_runStatus = new QLabel(tr("Status: not running"));
+  m_saveLog = new QPushButton(tr("Save log..."));
+  m_saveLog->setEnabled(false);
+  QPushButton *showSettings = new QPushButton(tr("Show configuration"));
+  runLayout->addWidget(m_run);
+  runLayout->addWidget(m_runStatus);
+  runLayout->addStretch(1);
+  runLayout->addWidget(showSettings);
+  runLayout->addWidget(m_saveLog);
+
+  // output produced by doxygen
+  runTabLayout->addLayout(runLayout);
+  runTabLayout->addWidget(new QLabel(tr("Output produced by doxygen")));
+  QGridLayout *grid = new QGridLayout;
+  m_outputLog = new QTextEdit;
+  m_outputLog->setReadOnly(true);
+  m_outputLog->setFontFamily(QString::fromAscii("courier"));
+  m_outputLog->setMinimumWidth(600);
+  grid->addWidget(m_outputLog,0,0);
+  grid->setColumnStretch(0,1);
+  grid->setRowStretch(0,1);
+  QHBoxLayout *launchLayout = new QHBoxLayout;
+  m_launchHtml = new QPushButton(tr("Show HTML output"));
+  launchLayout->addWidget(m_launchHtml);
+
+  launchLayout->addStretch(1);
+  grid->addLayout(launchLayout,1,0);
+  runTabLayout->addLayout(grid);
+
+  QTabWidget *tabs = new QTabWidget;
+  tabs->addTab(m_wizard,tr("Wizard"));
+  tabs->addTab(m_expert,tr("Expert"));
+  tabs->addTab(runTab,tr("Run"));
+
+  rowLayout->addWidget(new QLabel(tr("Step 1: Specify the working directory from which doxygen will run")));
+  rowLayout->addLayout(dirLayout);
+  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")));
+  rowLayout->addWidget(tabs);
+
+  setCentralWidget(topPart);
+  statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout);
+  loadSettings();
+
+  m_runProcess = new QProcess;
+  m_running = false;
+  m_timer = new QTimer;
+  updateLaunchButtonState();
+  m_modified = false;
+  updateTitle();
+
+  // connect signals and slots
+  connect(tabs,SIGNAL(currentChanged(int)),SLOT(selectTab(int)));
+  connect(m_selWorkingDir,SIGNAL(clicked()),SLOT(selectWorkingDir()));
+  connect(m_recentMenu,SIGNAL(triggered(QAction*)),SLOT(openRecent(QAction*)));
+  connect(m_workingDir,SIGNAL(returnPressed()),SLOT(updateWorkingDir()));
+  connect(m_runProcess,SIGNAL(readyReadStandardOutput()),SLOT(readStdout()));
+  connect(m_runProcess,SIGNAL(finished(int, QProcess::ExitStatus)),SLOT(runComplete()));
+  connect(m_timer,SIGNAL(timeout()),SLOT(readStdout()));
+  connect(m_run,SIGNAL(clicked()),SLOT(runDoxygen()));
+  connect(m_launchHtml,SIGNAL(clicked()),SLOT(showHtmlOutput()));
+  connect(m_saveLog,SIGNAL(clicked()),SLOT(saveLog()));
+  connect(showSettings,SIGNAL(clicked()),SLOT(showSettings()));
+  connect(m_expert,SIGNAL(changed()),SLOT(configChanged()));
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+  if (discardUnsavedChanges())
+  {
+    saveSettings();
+    event->accept();
+  }
+  else
+  {
+    event->ignore();
+  }
+}
+
+void MainWindow::quit()
+{
+  if (discardUnsavedChanges())
+  {
+    saveSettings();
+  }
+  QApplication::exit(0);
+}
+
+void MainWindow::setWorkingDir(const QString &dirName)
+{
+    QDir::setCurrent(dirName);
+    m_workingDir->setText(dirName);
+    m_run->setEnabled(!dirName.isEmpty());
+}
+
+void MainWindow::selectWorkingDir()
+{
+  QString dirName = QFileDialog::getExistingDirectory(this,
+        tr("Select working directory"),m_workingDir->text());
+  if (!dirName.isEmpty())
+  {
+    setWorkingDir(dirName);
+  }
+}
+
+void MainWindow::updateWorkingDir()
+{
+  setWorkingDir(m_workingDir->text());
+}
+
+void MainWindow::manual()
+{
+  QDesktopServices::openUrl(QUrl(QString::fromAscii("http://www.doxygen.org/manual.html")));
+}
+
+void MainWindow::about()
+{
+  QString msg;
+  QTextStream t(&msg,QIODevice::WriteOnly);
+  t << QString::fromAscii("<qt><center>A tool to configure and run doxygen version ")+
+       QString::fromAscii(versionString)+
+       QString::fromAscii(" on your source files.</center><p><br>"
+       "<center>Written by<br> Dimitri van Heesch<br>&copy; 2000-2009</center><p>"
+       "</qt>");
+  QMessageBox::about(this,tr("Doxygen GUI"),msg);
+}
+
+void MainWindow::openConfig()
+{
+  if (discardUnsavedChanges(false))
+  {
+    QString fn = QFileDialog::getOpenFileName(this,
+        tr("Open configuration file"),
+        m_workingDir->text());
+    if (!fn.isEmpty())
+    {
+      loadConfigFromFile(fn);
+    }
+  }
+}
+
+void MainWindow::updateConfigFileName(const QString &fileName)
+{
+  if (m_fileName!=fileName)
+  {
+    m_fileName = fileName;
+    QString curPath = QFileInfo(fileName).path();
+    setWorkingDir(curPath);
+    addRecentFile(fileName);
+    updateTitle();
+  }
+}
+
+void MainWindow::loadConfigFromFile(const QString & fileName)
+{
+  m_expert->loadConfig(fileName);
+  m_wizard->refresh();
+  updateConfigFileName(fileName);
+  updateLaunchButtonState();
+  m_modified = false;
+  updateTitle();
+}
+
+void MainWindow::saveConfig(const QString &fileName)
+{
+  if (fileName.isEmpty()) return;
+  QFile f(fileName);
+  if (!f.open(QIODevice::WriteOnly)) 
+  {
+    QMessageBox::warning(this,
+        tr("Error saving"),
+        tr("Error: cannot open the file ")+fileName+tr(" for writing!\n")+
+        tr("Reason given: ")+f.error());
+    return;
+  }
+  QTextStream t(&f);
+  m_expert->writeConfig(t,false);
+  updateConfigFileName(fileName);
+  m_modified = false;
+  updateTitle();
+}
+
+bool MainWindow::saveConfig()
+{
+  if (m_fileName.isEmpty())
+  {
+    return saveConfigAs();
+  }
+  else
+  {
+    saveConfig(m_fileName);
+    return true;
+  }
+}
+
+bool MainWindow::saveConfigAs()
+{
+  QString fileName = QFileDialog::getSaveFileName(this, QString(), 
+             m_workingDir->text()+QString::fromAscii("/Doxyfile"));
+  if (fileName.isEmpty()) return false;
+  saveConfig(fileName);
+  return true;
+}
+
+void MainWindow::makeDefaults()
+{
+  if (QMessageBox::question(this,tr("Use current setting at startup?"),
+                        tr("Do you want to save the current settings "
+                           "and use them next time Doxywizard starts?"),
+                        QMessageBox::Save|
+                        QMessageBox::Cancel)==QMessageBox::Save)
+  {
+    //printf("MainWindow:makeDefaults()\n");
+    m_expert->saveSettings(&m_settings);
+    m_settings.setValue(QString::fromAscii("wizard/loadsettings"), true);
+  }
+}
+
+void MainWindow::resetToDefaults()
+{
+  if (QMessageBox::question(this,tr("Reset settings to their default values?"),
+                        tr("Do you want to revert all settings back "
+                           "to their original values?"),
+                        QMessageBox::Reset|
+                        QMessageBox::Cancel)==QMessageBox::Reset)
+  {
+    //printf("MainWindow:resetToDefaults()\n");
+    m_expert->resetToDefaults();
+    m_settings.setValue(QString::fromAscii("wizard/loadsettings"), false);
+    m_wizard->refresh();
+  }
+}
+
+void MainWindow::loadSettings()
+{
+  QVariant geometry     = m_settings.value(QString::fromAscii("main/geometry"), QVariant::Invalid);
+  QVariant state        = m_settings.value(QString::fromAscii("main/state"),    QVariant::Invalid);
+  QVariant wizState     = m_settings.value(QString::fromAscii("wizard/state"),  QVariant::Invalid);
+  QVariant loadSettings = m_settings.value(QString::fromAscii("wizard/loadsettings"),  QVariant::Invalid);
+
+  if (geometry  !=QVariant::Invalid) restoreGeometry(geometry.toByteArray());
+  if (state     !=QVariant::Invalid) restoreState   (state.toByteArray());
+  if (wizState  !=QVariant::Invalid) m_wizard->restoreState(wizState.toByteArray());
+  if (loadSettings!=QVariant::Invalid && loadSettings.toBool())
+  {
+    m_expert->loadSettings(&m_settings);
+  }
+
+  for (int i=0;i<10;i++)
+  {
+    QString entry = m_settings.value(QString().sprintf("recent/config%d",i)).toString();
+    if (!entry.isEmpty()) addRecentFile(entry);
+  }
+
+}
+
+void MainWindow::saveSettings()
+{
+  QSettings settings(QString::fromAscii("Doxygen.org"), QString::fromAscii("Doxywizard"));
+
+  m_settings.setValue(QString::fromAscii("main/geometry"), saveGeometry());
+  m_settings.setValue(QString::fromAscii("main/state"),    saveState());
+  m_settings.setValue(QString::fromAscii("wizard/state"),  m_wizard->saveState());
+}
+
+void MainWindow::selectTab(int id)
+{
+  if (id==0) m_wizard->refresh();
+}
+
+void MainWindow::addRecentFile(const QString &fileName)
+{
+  int i=m_recentFiles.indexOf(fileName);
+  if (i!=-1) m_recentFiles.removeAt(i);
+  
+  // not found
+  if (m_recentFiles.count() < 10) // append
+  {
+    m_recentFiles.prepend(fileName);
+  }
+  else // add + drop last item
+  {
+    m_recentFiles.removeLast();
+    m_recentFiles.prepend(fileName);
+  }
+  m_recentMenu->clear();
+  i=0;
+  foreach( QString str, m_recentFiles ) 
+  {
+    m_recentMenu->addAction(str);
+    m_settings.setValue(QString().sprintf("recent/config%d",i++),str);
+  }
+}
+
+void MainWindow::openRecent(QAction *action)
+{
+  if (discardUnsavedChanges(false))
+  {
+    loadConfigFromFile(action->text());
+  }
+}
+
+void MainWindow::runDoxygen()
+{
+  if (!m_running)
+  {
+    QString doxygenPath; 
+#if defined(Q_OS_MACX)
+    doxygenPath = qApp->applicationDirPath()+QString::fromAscii("/../Resources/");
+    qDebug() << tr("Doxygen path: ") << doxygenPath;
+    if ( !QFile(doxygenPath + QString::fromAscii("doxygen")).exists() ) 
+    {
+      // No doygen binary in the resources, if there is a system doxygen binary, use that instead
+      if ( QFile(QString::fromAscii("/usr/local/bin/doxygen")).exists() )
+      {
+        doxygenPath = QString::fromAscii("/usr/local/bin/");
+      }
+      else 
+      {
+        qDebug() << tr("Can't find the doxygen command, make sure it's in your $$PATH");
+        doxygenPath = QString::fromAscii("");
+      }
+    }
+    qDebug() << tr("Getting doxygen from: ") << doxygenPath;
+#endif
+
+    m_runProcess->setReadChannel(QProcess::StandardOutput);
+    m_runProcess->setProcessChannelMode(QProcess::MergedChannels);
+    m_runProcess->setWorkingDirectory(m_workingDir->text());
+    QStringList env=QProcess::systemEnvironment();
+    // set PWD environment variable to m_workingDir
+    env.replaceInStrings(QRegExp(QString::fromAscii("^PWD=(.*)"),Qt::CaseInsensitive), 
+                         QString::fromAscii("PWD=")+m_workingDir->text());
+    m_runProcess->setEnvironment(env);
+
+    QStringList args;
+    args << QString::fromAscii("-b"); // make stdout unbuffered
+    args << QString::fromAscii("-");  // read config from stdin
+
+    m_outputLog->clear();
+    m_runProcess->start(doxygenPath + QString::fromAscii("doxygen"), args);
+
+    if (!m_runProcess->waitForStarted())
+    {
+      m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
+      return;
+    }
+    QTextStream t(m_runProcess);
+    m_expert->writeConfig(t,false);
+    m_runProcess->closeWriteChannel();
+
+    if (m_runProcess->state() == QProcess::NotRunning)
+    {
+      m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
+    }
+    else
+    {
+      m_saveLog->setEnabled(false);
+      m_running=true;
+      m_run->setText(tr("Stop doxygen"));
+      m_runStatus->setText(tr("Status: running"));
+      m_timer->start(1000);
+    }
+  }
+  else
+  {
+    m_running=false;
+    m_run->setText(tr("Run doxygen"));
+    m_runStatus->setText(tr("Status: not running"));
+    m_runProcess->kill();
+    m_timer->stop();
+    //updateRunnable(m_workingDir->text());
+  }
+}
+
+void MainWindow::readStdout()
+{
+  if (m_running)
+  {
+    QByteArray data = m_runProcess->readAllStandardOutput();
+    QString text = QString::fromLocal8Bit(data);
+    if (!text.isEmpty())
+    {
+      m_outputLog->append(text.trimmed());
+    }
+  }
+}
+
+void MainWindow::runComplete()
+{
+  if (m_running)
+  {
+    m_outputLog->append(tr("*** Doxygen has finished\n"));
+  }
+  else
+  {
+    m_outputLog->append(tr("*** Cancelled by user\n"));
+  }
+  m_outputLog->ensureCursorVisible();
+  m_run->setText(tr("Run doxygen"));
+  m_runStatus->setText(tr("Status: not running"));
+  m_running=false;
+  updateLaunchButtonState();
+  //updateRunnable(m_workingDir->text());
+  m_saveLog->setEnabled(true);
+}
+
+void MainWindow::updateLaunchButtonState()
+{
+  m_launchHtml->setEnabled(m_expert->htmlOutputPresent(m_workingDir->text()));
+#if 0
+  m_launchPdf->setEnabled(m_expert->pdfOutputPresent(m_workingDir->text()));
+#endif
+}
+
+void MainWindow::showHtmlOutput()
+{
+  QString indexFile = m_expert->getHtmlOutputIndex(m_workingDir->text());
+  QFileInfo fi(indexFile);
+#ifdef WIN32
+  QString indexUrl(QString::fromAscii("file:///"));
+#else
+  QString indexUrl(QString::fromAscii("file://"));
+#endif
+  indexUrl+=fi.absoluteFilePath();
+  QDesktopServices::openUrl(QUrl(indexUrl));
+}
+
+void MainWindow::saveLog()
+{
+  QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"), 
+        m_workingDir->text()+
+        QString::fromAscii("/doxygen_log.txt"));
+  if (!fn.isEmpty())
+  {
+    QFile f(fn);
+    if (f.open(QIODevice::WriteOnly))
+    {
+      QTextStream t(&f);
+      t << m_outputLog->toPlainText();
+      statusBar()->showMessage(tr("Output log saved"),messageTimeout);
+    }
+    else
+    {
+      QMessageBox::warning(0,tr("Warning"),
+          tr("Cannot open file ")+fn+tr(" for writing. Nothing saved!"),tr("ok"));
+    }
+  }
+}
+
+void MainWindow::showSettings()
+{
+  QString text;
+  QTextStream t(&text);
+  m_expert->writeConfig(t,true);
+  m_outputLog->clear();
+  m_outputLog->append(text);
+  m_outputLog->ensureCursorVisible();
+  m_saveLog->setEnabled(true);
+}
+
+void MainWindow::configChanged()
+{
+  m_modified = true;
+  updateTitle();
+}
+
+void MainWindow::updateTitle()
+{
+  QString title = tr("Doxygen GUI frontend");
+  if (m_modified)
+  {
+    title+=QString::fromAscii(" +");
+  }
+  if (!m_fileName.isEmpty())
+  {
+    title+=QString::fromAscii(" (")+m_fileName+QString::fromAscii(")");
+  }
+  setWindowTitle(title);
+}
+
+bool MainWindow::discardUnsavedChanges(bool saveOption)
+{
+  if (m_modified)
+  {
+    QMessageBox::StandardButton button;
+    if (saveOption)
+    {
+      button = QMessageBox::question(this,
+          tr("Unsaved changes"),
+          tr("Unsaved changes will be lost! Do you want to save the configuration file?"),
+          QMessageBox::Save    |
+          QMessageBox::Discard |
+          QMessageBox::Cancel
+          );
+      if (button==QMessageBox::Save)
+      {
+        return saveConfig();
+      }
+    }
+    else
+    {
+      button = QMessageBox::question(this,
+          tr("Unsaved changes"),
+          tr("Unsaved changes will be lost! Do you want to continue?"),
+          QMessageBox::Discard |
+          QMessageBox::Cancel
+          );
+    }
+    return button==QMessageBox::Discard;
+  }
+  return true;
+}
+
+//-----------------------------------------------------------------------
+
+int main(int argc,char **argv)
+{
+  QApplication a(argc,argv);
+  MainWindow &main = MainWindow::instance();
+  if (argc==2 && argv[1][0]!='-') // name of config file as an argument
+  {
+    main.loadConfigFromFile(QString::fromLocal8Bit(argv[1]));
+  }
+  else if (argc>1)
+  {
+    printf("Usage: %s [config file]\n",argv[0]);
+    exit(1);
+  }
+  main.show();
+  return a.exec();
+}