doxywizard.cpp 18.7 KB
Newer Older
1
#include <QtGui>
2
#include "doxywizard.h"
3
#include "version.h"
4 5
#include "expert.h"
#include "wizard.h"
6

7 8 9 10
#ifdef WIN32
#include <windows.h>
#endif

11 12
#define MAX_RECENT_FILES 10

13 14
const int messageTimeout = 5000; //!< status bar message timeout in millisec.

15 16
MainWindow &MainWindow::instance()
{
17 18
  static MainWindow *theInstance = new MainWindow;
  return *theInstance;
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
}

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()));
40 41
  settings->addAction(tr("Clear recent list"),
                  this,SLOT(clearRecent()));
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

  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);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
95

96 97 98
  launchLayout->addStretch(1);
  grid->addLayout(launchLayout,1,0);
  runTabLayout->addLayout(grid);
99

100 101 102 103
  m_tabs = new QTabWidget;
  m_tabs->addTab(m_wizard,tr("Wizard"));
  m_tabs->addTab(m_expert,tr("Expert"));
  m_tabs->addTab(runTab,tr("Run"));
104

105 106 107
  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")));
108
  rowLayout->addWidget(m_tabs);
109

110 111
  setCentralWidget(topPart);
  statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout);
112

113 114 115
  m_runProcess = new QProcess;
  m_running = false;
  m_timer = new QTimer;
116

117
  // connect signals and slots
118
  connect(m_tabs,SIGNAL(currentChanged(int)),SLOT(selectTab(int)));
119 120 121 122 123 124 125 126 127 128 129
  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()));
130
  connect(m_wizard,SIGNAL(done()),SLOT(selectRunTab()));
131
  connect(m_expert,SIGNAL(done()),SLOT(selectRunTab()));
132 133 134 135 136 137

  loadSettings();
  updateLaunchButtonState();
  m_modified = false;
  updateTitle();
  m_wizard->refresh();
138 139
}

140
void MainWindow::closeEvent(QCloseEvent *event)
141
{
142 143 144 145 146 147 148 149 150
  if (discardUnsavedChanges())
  {
    saveSettings();
    event->accept();
  }
  else
  {
    event->ignore();
  }
151 152
}

153
void MainWindow::quit()
154
{
155 156 157 158 159
  if (discardUnsavedChanges())
  {
    saveSettings();
  }
  QApplication::exit(0);
160 161
}

162
void MainWindow::setWorkingDir(const QString &dirName)
163
{
164 165 166
    QDir::setCurrent(dirName);
    m_workingDir->setText(dirName);
    m_run->setEnabled(!dirName.isEmpty());
167 168
}

169
void MainWindow::selectWorkingDir()
170
{
171 172 173
  QString dirName = QFileDialog::getExistingDirectory(this,
        tr("Select working directory"),m_workingDir->text());
  if (!dirName.isEmpty())
174
  {
175
    setWorkingDir(dirName);
176
  }
177 178
}

179
void MainWindow::updateWorkingDir()
180
{
181
  setWorkingDir(m_workingDir->text());
182 183
}

184
void MainWindow::manual()
185
{
186
  QDesktopServices::openUrl(QUrl(QString::fromAscii("http://www.doxygen.org/manual.html")));
187
}
188

189
void MainWindow::about()
190
{
191 192 193 194 195
  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>"
albert-github's avatar
albert-github committed
196
       "<center>Written by<br> Dimitri van Heesch<br>&copy; 2000-2014</center><p>"
197 198
       "</qt>");
  QMessageBox::about(this,tr("Doxygen GUI"),msg);
199 200
}

201
void MainWindow::openConfig()
202
{
203
  if (discardUnsavedChanges(false))
204
  {
205 206 207 208 209 210 211
    QString fn = QFileDialog::getOpenFileName(this,
        tr("Open configuration file"),
        m_workingDir->text());
    if (!fn.isEmpty())
    {
      loadConfigFromFile(fn);
    }
212 213 214
  }
}

215
void MainWindow::updateConfigFileName(const QString &fileName)
216
{
217
  if (m_fileName!=fileName)
218
  {
219 220 221 222 223
    m_fileName = fileName;
    QString curPath = QFileInfo(fileName).path();
    setWorkingDir(curPath);
    addRecentFile(fileName);
    updateTitle();
224 225 226
  }
}

227
void MainWindow::loadConfigFromFile(const QString & fileName)
228
{
229 230 231
  // save full path info of original file
  QString absFileName = QFileInfo(fileName).absoluteFilePath();
  // updates the current directory
232
  updateConfigFileName(fileName);
233 234 235
  // open the specified configuration file
  m_expert->loadConfig(absFileName);
  m_wizard->refresh();
236 237 238
  updateLaunchButtonState();
  m_modified = false;
  updateTitle();
239 240
}

241
void MainWindow::saveConfig(const QString &fileName)
242
{
243 244
  if (fileName.isEmpty()) return;
  QFile f(fileName);
245 246 247 248 249 250 251 252
  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;
  }
253 254 255 256 257
  QTextStream t(&f);
  m_expert->writeConfig(t,false);
  updateConfigFileName(fileName);
  m_modified = false;
  updateTitle();
258 259
}

260
bool MainWindow::saveConfig()
261
{
262
  if (m_fileName.isEmpty())
263
  {
264
    return saveConfigAs();
265
  }
266
  else
267
  {
268 269
    saveConfig(m_fileName);
    return true;
270 271 272
  }
}

273
bool MainWindow::saveConfigAs()
274
{
275 276 277 278 279
  QString fileName = QFileDialog::getSaveFileName(this, QString(), 
             m_workingDir->text()+QString::fromAscii("/Doxyfile"));
  if (fileName.isEmpty()) return false;
  saveConfig(fileName);
  return true;
280 281
}

282
void MainWindow::makeDefaults()
283
{
284 285 286 287 288
  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)
289
  {
290 291 292
    //printf("MainWindow:makeDefaults()\n");
    m_expert->saveSettings(&m_settings);
    m_settings.setValue(QString::fromAscii("wizard/loadsettings"), true);
293
    m_settings.sync();
294 295 296
  }
}

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
void MainWindow::clearRecent()
{
  if (QMessageBox::question(this,tr("Clear the list of recent files?"),
                        tr("Do you want to clear the list of recently "
                           "loaded configuration files?"),
                        QMessageBox::Yes|
                        QMessageBox::Cancel)==QMessageBox::Yes)
  {
    m_recentMenu->clear();
    m_recentFiles.clear();
    for (int i=0;i<MAX_RECENT_FILES;i++)
    {
      m_settings.setValue(QString().sprintf("recent/config%d",i++),QString::fromAscii(""));
    }
    m_settings.sync();
  }
  
}

316
void MainWindow::resetToDefaults()
317
{
318 319 320 321 322
  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)
323
  {
324 325 326
    //printf("MainWindow:resetToDefaults()\n");
    m_expert->resetToDefaults();
    m_settings.setValue(QString::fromAscii("wizard/loadsettings"), false);
327
    m_settings.sync();
328
    m_wizard->refresh();
329
  }
330 331
}

332
void MainWindow::loadSettings()
333
{
334 335 336 337
  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);
338
  QVariant workingDir   = m_settings.value(QString::fromAscii("wizard/workingdir"), QVariant::Invalid);
339

340 341 342 343
  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())
344
  {
345
    m_expert->loadSettings(&m_settings);
346 347 348 349
    if (workingDir!=QVariant::Invalid && QDir(workingDir.toString()).exists())
    {
      setWorkingDir(workingDir.toString());
    }
350
  }
351

352
  for (int i=0;i<MAX_RECENT_FILES;i++)
353
  {
354
    QString entry = m_settings.value(QString().sprintf("recent/config%d",i)).toString();
355 356 357 358
    if (!entry.isEmpty() && QFileInfo(entry).exists())
    {
      addRecentFile(entry);
    }
359 360
  }

361 362
}

363
void MainWindow::saveSettings()
364
{
365
  QSettings settings(QString::fromAscii("Doxygen.org"), QString::fromAscii("Doxywizard"));
366

367 368 369
  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());
370
  m_settings.setValue(QString::fromAscii("wizard/workingdir"), m_workingDir->text());
371 372
}

373
void MainWindow::selectTab(int id)
374
{
375
  if (id==0) m_wizard->refresh();
376
  else if (id==1) m_expert->refresh();
377 378
}

379 380 381 382 383
void MainWindow::selectRunTab()
{
  m_tabs->setCurrentIndex(2);
}

384
void MainWindow::addRecentFile(const QString &fileName)
385
{
386 387
  int i=m_recentFiles.indexOf(fileName);
  if (i!=-1) m_recentFiles.removeAt(i);
388
  
389
  // not found
390
  if (m_recentFiles.count() < MAX_RECENT_FILES) // append
391
  {
392
    m_recentFiles.prepend(fileName);
393
  }
394
  else // add + drop last item
395
  {
396 397
    m_recentFiles.removeLast();
    m_recentFiles.prepend(fileName);
398
  }
399 400 401
  m_recentMenu->clear();
  i=0;
  foreach( QString str, m_recentFiles ) 
402
  {
403 404
    m_recentMenu->addAction(str);
    m_settings.setValue(QString().sprintf("recent/config%d",i++),str);
405
  }
406 407 408 409
  for (;i<MAX_RECENT_FILES;i++)
  {
    m_settings.setValue(QString().sprintf("recent/config%d",i++),QString::fromAscii(""));
  }
410 411
}

412
void MainWindow::openRecent(QAction *action)
413
{
414
  if (discardUnsavedChanges(false))
415
  {
416
    loadConfigFromFile(action->text());
417
  }
418 419
}

420
void MainWindow::runDoxygen()
421
{
422
  if (!m_running)
423
  {
424 425 426 427
    QString doxygenPath; 
#if defined(Q_OS_MACX)
    doxygenPath = qApp->applicationDirPath()+QString::fromAscii("/../Resources/");
    qDebug() << tr("Doxygen path: ") << doxygenPath;
428 429 430 431 432 433 434 435 436 437 438 439 440
    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("");
      }
    }
441 442
    qDebug() << tr("Getting doxygen from: ") << doxygenPath;
#endif
443

444 445 446 447 448 449 450 451
    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);
452

453 454 455
    QStringList args;
    args << QString::fromAscii("-b"); // make stdout unbuffered
    args << QString::fromAscii("-");  // read config from stdin
456

457 458
    m_outputLog->clear();
    m_runProcess->start(doxygenPath + QString::fromAscii("doxygen"), args);
459

460
    if (!m_runProcess->waitForStarted())
461
    {
462 463
      m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
      return;
464
    }
465 466 467
    QTextStream t(m_runProcess);
    m_expert->writeConfig(t,false);
    m_runProcess->closeWriteChannel();
468

469
    if (m_runProcess->state() == QProcess::NotRunning)
470
    {
471
      m_outputLog->append(QString::fromAscii("*** Failed to run doxygen\n"));
472 473 474
    }
    else
    {
475 476 477 478 479
      m_saveLog->setEnabled(false);
      m_running=true;
      m_run->setText(tr("Stop doxygen"));
      m_runStatus->setText(tr("Status: running"));
      m_timer->start(1000);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
480
    }
481 482 483
  }
  else
  {
484 485 486 487 488 489
    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());
490 491 492
  }
}

493
void MainWindow::readStdout()
494
{
495
  if (m_running)
496
  {
497
    QByteArray data = m_runProcess->readAllStandardOutput();
498
    QString text = QString::fromUtf8(data);
499 500 501 502
    if (!text.isEmpty())
    {
      m_outputLog->append(text.trimmed());
    }
503 504 505
  }
}

506
void MainWindow::runComplete()
507
{
508
  if (m_running)
509
  {
510
    m_outputLog->append(tr("*** Doxygen has finished\n"));
511
  }
512
  else
513
  {
514
    m_outputLog->append(tr("*** Cancelled by user\n"));
515
  }
516 517 518 519 520 521 522
  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);
523 524
}

525
void MainWindow::updateLaunchButtonState()
526
{
527 528 529
  m_launchHtml->setEnabled(m_expert->htmlOutputPresent(m_workingDir->text()));
#if 0
  m_launchPdf->setEnabled(m_expert->pdfOutputPresent(m_workingDir->text()));
530
#endif
531 532
}

533
void MainWindow::showHtmlOutput()
534
{
535 536
  QString indexFile = m_expert->getHtmlOutputIndex(m_workingDir->text());
  QFileInfo fi(indexFile);
537
  // TODO: the following doesn't seem to work with IE
Dimitri van Heesch's avatar
Dimitri van Heesch committed
538
#ifdef WIN32
539
  //QString indexUrl(QString::fromAscii("file:///"));
540
  ShellExecute(NULL, L"open", (LPCWSTR)fi.absoluteFilePath().utf16(), NULL, NULL, SW_SHOWNORMAL);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
541 542 543
#else
  QString indexUrl(QString::fromAscii("file://"));
  indexUrl+=fi.absoluteFilePath();
544
  QDesktopServices::openUrl(QUrl(indexUrl));
545
#endif
546 547
}

548
void MainWindow::saveLog()
549
{
550 551 552 553
  QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"), 
        m_workingDir->text()+
        QString::fromAscii("/doxygen_log.txt"));
  if (!fn.isEmpty())
554
  {
555 556
    QFile f(fn);
    if (f.open(QIODevice::WriteOnly))
557
    {
558 559 560
      QTextStream t(&f);
      t << m_outputLog->toPlainText();
      statusBar()->showMessage(tr("Output log saved"),messageTimeout);
561 562 563
    }
    else
    {
564 565
      QMessageBox::warning(0,tr("Warning"),
          tr("Cannot open file ")+fn+tr(" for writing. Nothing saved!"),tr("ok"));
566 567 568 569
    }
  }
}

570
void MainWindow::showSettings()
571
{
572 573 574 575 576 577 578
  QString text;
  QTextStream t(&text);
  m_expert->writeConfig(t,true);
  m_outputLog->clear();
  m_outputLog->append(text);
  m_outputLog->ensureCursorVisible();
  m_saveLog->setEnabled(true);
579 580
}

581
void MainWindow::configChanged()
582
{
583 584
  m_modified = true;
  updateTitle();
585 586
}

587
void MainWindow::updateTitle()
588
{
589 590
  QString title = tr("Doxygen GUI frontend");
  if (m_modified)
591
  {
592
    title+=QString::fromAscii(" +");
593
  }
594
  if (!m_fileName.isEmpty())
595
  {
596
    title+=QString::fromAscii(" (")+m_fileName+QString::fromAscii(")");
597
  }
598
  setWindowTitle(title);
599 600
}

601
bool MainWindow::discardUnsavedChanges(bool saveOption)
602
{
603
  if (m_modified)
604
  {
605 606
    QMessageBox::StandardButton button;
    if (saveOption)
607
    {
608 609 610 611 612 613 614 615 616 617 618
      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();
      }
619 620 621
    }
    else
    {
622 623 624 625 626 627
      button = QMessageBox::question(this,
          tr("Unsaved changes"),
          tr("Unsaved changes will be lost! Do you want to continue?"),
          QMessageBox::Discard |
          QMessageBox::Cancel
          );
628
    }
629
    return button==QMessageBox::Discard;
630
  }
631
  return true;
632 633
}

634
//-----------------------------------------------------------------------
635
int main(int argc,char **argv)
636 637
{
  QApplication a(argc,argv);
638
  if (argc == 2)
639
  {
640 641 642 643 644 645 646
    if (!qstrcmp(argv[1],"--help"))
    {
      QMessageBox msgBox;
      msgBox.setText(QString().sprintf("Usage: %s [config file]",argv[0]));
      msgBox.exec();
      exit(0);
    }
647
  }
648
  if (argc > 2)
649
  {
650 651 652
    QMessageBox msgBox;
    msgBox.setText(QString().sprintf("Too many arguments specified\n\nUsage: %s [config file]",argv[0]));
    msgBox.exec();
653 654
    exit(1);
  }
655 656 657 658 659 660 661 662 663 664
  else
  {
    MainWindow &main = MainWindow::instance();
    if (argc==2 && argv[1][0]!='-') // name of config file as an argument
    {
      main.loadConfigFromFile(QString::fromLocal8Bit(argv[1]));
    }
    main.show();
    return a.exec();
  }
665
}