/
niceSOFT
/
doxygen
Обзор
Документация
Войти
/
niceSOFT
/
doxygen
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
addon/doxywizard/doxywizard.cpp
1 139 строк
34 KB
albert-github
Small doxywizard usage improvement
03 июн 2026, 20:31
03 июн 2026, 20:31
d187118
Код
Авторство
О чём код?
/****************************************************************************** * * Copyright (C) 1997-2021 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * */ #include "doxywizard.h" #include "version.h" #include "expert.h" #include "wizard.h" #include "languagedialog.h" #include <QMenu> #include <QMenuBar> #include <QPushButton> #include <QMessageBox> #include <QVBoxLayout> #include <QLineEdit> #include <QLabel> #include <QCheckBox> #include <QTextBrowser> #include <QStatusBar> #include <QProcess> #include <QTimer> #include <QCloseEvent> #include <QApplication> #include <QDir> #include <QFileDialog> #include <QDesktopServices> #include <QUrl> #include <QTextStream> #include <QRegularExpression> #include <QDebug> #include <QDate> #include <QScrollBar> #include <QLocale> #include <QTranslator> #include <QList> #ifdef _WIN32 #include <windows.h> #endif #define MAX_RECENT_FILES 10 // globally accessible variables bool DoxygenWizard::debugFlag = false; QString DoxygenWizard::langCode; static QList<QString> newArgs; const int messageTimeout = 5000; //!< status bar message timeout in milliseconds. #define APPQT(x) QString::fromLatin1("<qt><pre>") + x + QString::fromLatin1("</pre></qt>") //---------------------------------------------------------------------------------------------- // check if a translation for langCode is stored as resource static bool isLanguageCodeSupported(const QString &langCode) { // English is the default language, always supported if (langCode == QString::fromLatin1("en")) { return true; } QDir resourceDir(QString::fromLatin1(":/i18n")); QFileInfoList fileList = resourceDir.entryInfoList(); foreach (QFileInfo fileInfo, fileList) { QString filename = fileInfo.fileName(); const int underscore = filename.indexOf(QChar::fromLatin1('_')); const int dot = filename.lastIndexOf(QChar::fromLatin1('.')); if (filename.startsWith(QString::fromLatin1("doxywizard")) && underscore!=-1 && dot>underscore) { QString supportedLangCode = filename.mid(underscore+1, dot-underscore-1); if (langCode==supportedLangCode) return true; } } return false; } static QString getStartupLanguageCode() { QSettings settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard")); // fetch stored language code QString langCode = settings.value(QString::fromLatin1("language/code")).toString(); if (!langCode.isEmpty() && isLanguageCodeSupported(langCode)) { return langCode; } // no translation found yet -> determine system language code from Locale QLocale systemLocale = QLocale::system(); if (systemLocale.language()==QLocale::Chinese) { langCode = QLocale::SimplifiedChineseScript ? QString::fromLatin1("zh_CN") : QString::fromLatin1("zh_TW"); } else { langCode = systemLocale.name().left(2); } // return code if supported return isLanguageCodeSupported(langCode) ? langCode : QString(); } //---------------------------------------------------------------------------------------------- #define TR_MSG(msg) QCoreApplication::translate("Messages",msg) QString DoxygenWizard::msgFileNotFound(const QString &fileName) { return TR_MSG("Sorry, cannot find file(%1)").arg(fileName); } QString DoxygenWizard::msgNoPreviewAvailable(const QString &fileName) { return TR_MSG("Sorry, no preview available (%1)").arg(fileName); } QString DoxygenWizard::msgNoProjectLogoSelected() { return TR_MSG("No Project logo selected."); } QString DoxygenWizard::msgBrowseToFile() { return TR_MSG("Browse to a file"); } QString DoxygenWizard::msgBrowseToFolder() { return TR_MSG("Browse to a folder"); } QString DoxygenWizard::msgSelectButton() { return TR_MSG("Select..."); } QString DoxygenWizard::msgPreviousButton() { return TR_MSG("Previous"); } QString DoxygenWizard::msgNextButton() { return TR_MSG("Next"); } QString DoxygenWizard::msgTopicsHeader() { return TR_MSG("Topics"); } #undef TR_MSG_ENTRY //---------------------------------------------------------------------------------------------- MainWindow &MainWindow::instance() { static MainWindow *theInstance = new MainWindow; return *theInstance; } MainWindow::MainWindow() : m_settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard")) { QMenu *file = menuBar()->addMenu(tr("File")); { QAction *a = file->addAction(tr("Open...")); a->setShortcut(QKeySequence{ Qt::CTRL | Qt::Key_O }); connect(a, SIGNAL(triggered()), this, SLOT(openConfig())); } m_recentMenu = file->addMenu(tr("Open recent")); { QAction *a = file->addAction(tr("Save")); a->setShortcut(QKeySequence{ Qt::CTRL | Qt::Key_S }); connect(a, SIGNAL(triggered()), this, SLOT(saveConfig())); } { QAction *a = file->addAction(tr("Save as...")); a->setShortcut(QKeySequence{ Qt::SHIFT | Qt::CTRL | Qt::Key_S }); connect(a, SIGNAL(triggered()), this, SLOT(saveConfigAs())); } { QAction *a = file->addAction(tr("Quit")); a->setShortcut(QKeySequence{ Qt::CTRL | Qt::Key_Q }); connect(a, SIGNAL(triggered()), this, SLOT(quit())); } QMenu *settings = menuBar()->addMenu(tr("Settings")); m_resetDefault = settings->addAction(tr("Reset to factory defaults"), this,SLOT(resetToDefaults())); settings->addAction(tr("Use current settings at startup"), this,SLOT(makeDefaults())); m_hideDocumentation = settings->addAction(tr("Hide documentation"), this,SLOT(setDocumentationVisibility())); m_hideDocumentation->setCheckable(true); bool hidden = m_settings.value(QString::fromLatin1("documentation/hide")).toBool(); m_hideDocumentation->setChecked(hidden); settings->addAction(tr("Switch language..."), this,SLOT(switchLanguage())); m_clearRecent = settings->addAction(tr("Clear recent list"), this,SLOT(clearRecent())); settings->addSeparator(); m_runMenu = settings->addAction(tr("Run doxygen")); m_runMenu->setShortcut(QKeySequence{ Qt::CTRL | Qt::Key_R }); connect(m_runMenu, SIGNAL(triggered()), this, SLOT(runDoxygenMenu())); m_runMenu->setEnabled(false); QMenu *help = menuBar()->addMenu(tr("Help")); { QAction *a = help->addAction(tr("Online manual")); a->setShortcut(Qt::Key_F1); connect(a, SIGNAL(triggered()), this, SLOT(manual())); } help->addAction(tr("About"), this, SLOT(about()) ); m_expert = new Expert; m_wizard = new Wizard(m_expert->modelData()); // ----------- top part ------------------ QWidget *mainPart = new QWidget; QVBoxLayout *mainLayout = new QVBoxLayout(mainPart); QWidget *topPart = new QWidget; QVBoxLayout *rowLayout = new QVBoxLayout(topPart); mainLayout->addWidget(topPart); // select working directory QHBoxLayout *dirLayout = new QHBoxLayout; m_workingDir = new QLineEdit; m_selWorkingDir = new QPushButton(DoxygenWizard::msgSelectButton()); dirLayout->addWidget(m_workingDir); dirLayout->addWidget(m_selWorkingDir); //------------- bottom part -------------- m_runTab = new QWidget; QVBoxLayout *runTabLayout = new QVBoxLayout(m_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")); m_showCondensedSettings = new QCheckBox(this); m_showCondensedSettings->setText(tr("Condensed")); m_showCondensedSettings->setChecked(false); m_showCondensedSettings->setToolTip(tr("Show only configuration settings different from default settings")); // select extra run options m_runOptions = new QLineEdit; runTabLayout->addWidget(new QLabel(tr("Specify additional command line options for running doxygen"))); runTabLayout->addWidget(m_runOptions); QVBoxLayout *runVLayout = new QVBoxLayout; runLayout->addLayout(runVLayout); QHBoxLayout *runVHLayout = new QHBoxLayout; runVLayout->addLayout(runVHLayout); runVHLayout->addWidget(m_run); runVHLayout->addWidget(m_runStatus); QHBoxLayout *runVH2Layout = new QHBoxLayout; runVLayout->addLayout(runVH2Layout); m_launchHtml = new QPushButton(tr("Show HTML output")); runVH2Layout->addWidget(m_launchHtml); runVH2Layout->addStretch(1); // to have launch button not being stretched runLayout->addStretch(1); QVBoxLayout *settingsLayout = new QVBoxLayout; runLayout->addLayout(settingsLayout); settingsLayout->addWidget(m_showCondensedSettings); settingsLayout->addWidget(showSettings); QVBoxLayout *saveLayout = new QVBoxLayout; runLayout->addLayout(saveLayout); saveLayout->addWidget(m_saveLog); saveLayout->setAlignment(Qt::AlignTop); // saveLayout->addWidget(new QWidget); // to have the save button at the top // 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 = new QTextBrowser; //m_outputLog = new QPlainTextEdit; m_outputLog->setReadOnly(true); m_outputLog->setFontFamily(QString::fromLatin1("courier")); m_outputLog->setMinimumWidth(600); grid->addWidget(m_outputLog,0,0); grid->setColumnStretch(0,1); grid->setRowStretch(0,1); runTabLayout->addLayout(grid); m_tabs = new QTabWidget; m_tabs->addTab(m_wizard,tr("Wizard")); m_tabs->addTab(m_expert,tr("Expert")); m_tabs->addTab(m_runTab,tr("Run")); rowLayout->addWidget(new QLabel(tr("Specify the working directory from which doxygen will run"))); rowLayout->addLayout(dirLayout); rowLayout->addWidget(new QLabel(tr("Configure doxygen using the Wizard and/or Expert tab, then switch to the Run tab to generate the documentation"))); mainLayout->addWidget(m_tabs); setCentralWidget(mainPart); statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout); m_runProcess = new QProcess; m_running = false; m_timer = new QTimer; // connect signals and slots connect(m_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())); connect(m_wizard,SIGNAL(done()),SLOT(selectRunTab())); connect(m_expert,SIGNAL(done()),SLOT(selectRunTab())); loadSettings(); updateLaunchButtonState(); m_modified = false; updateTitle(); m_wizard->refresh(); m_expert->setDocumentationVisibility(hidden); } void MainWindow::closeEvent(QCloseEvent *event) { if (discardUnsavedChanges()) { saveSettings(); event->accept(); } else { event->ignore(); } } void MainWindow::quit() { if (discardUnsavedChanges()) { saveSettings(); } else { return; } QApplication::exit(0); } void MainWindow::setWorkingDir(const QString &dirName) { QDir::setCurrent(dirName); m_workingDir->setText(dirName); m_run->setEnabled(!dirName.isEmpty()); m_runMenu->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::setLanguage(const QString &langCode) { m_settings.setValue(QString::fromLatin1("language/code"), langCode); m_settings.sync(); } void MainWindow::manual() { QDesktopServices::openUrl(QUrl(QString::fromLatin1("https://www.doxygen.org/manual/index.html"))); } void MainWindow::about() { QString msg; QTextStream t(&msg,QIODevice::WriteOnly); t << QString::fromLatin1("<qt><center>")+ tr("A tool to configure and run doxygen version %1 on your source files.").arg(QString::fromLatin1(getDoxygenVersion().c_str()))+ QString::fromLatin1("</center><center>"); if (QString::fromLatin1(qVersion())==QString::fromLatin1(QT_VERSION_STR)) { t << tr("(Created with Qt version %1)").arg(QString::fromLatin1(QT_VERSION_STR)); } else { t << tr("(Created with Qt version %1, running with version %2)").arg(QString::fromLatin1(QT_VERSION_STR)).arg(QString::fromLatin1(qVersion())); } t << QString::fromLatin1("</center><p><br><center>") + tr("Written by"); t << QString::fromLatin1("<br> Dimitri van Heesch<br>© 2000-") << QDate::currentDate().year(); t << QString::fromLatin1("</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) { // save full path info of original file QString absFileName = QFileInfo(fileName).absoluteFilePath(); // updates the current directory updateConfigFileName(fileName); // open the specified configuration file m_expert->loadConfig(absFileName); m_wizard->refresh(); updateLaunchButtonState(); m_modified = false; updateTitle(); } void MainWindow::saveConfig(const QString &fileName) { if (fileName.isEmpty()) return; QFile f(fileName); if (!f.open(QIODevice::WriteOnly | QIODevice::Text )) { QMessageBox::warning(this, tr("Error saving"), tr("Error: cannot open the file %1 for writing!\nReason given: %2").arg(fileName).arg(f.error())); return; } QTextStream t(&f); t.device()->setTextModeEnabled(false); m_expert->writeConfig(t,false,false,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::fromLatin1("/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::fromLatin1("wizard/loadsettings"), true); m_settings.sync(); } } void MainWindow::setDocumentationVisibility() { // New state bool hidden = m_hideDocumentation->isChecked(); m_settings.setValue(QString::fromLatin1("documentation/hide"), hidden); m_settings.sync(); m_expert->setDocumentationVisibility(hidden); } void MainWindow::switchLanguage() { LanguageDialog languageDialog(DoxygenWizard::langCode,this); if (languageDialog.exec()==QDialog::Accepted) { QString langCode = languageDialog.selectedLocale(); qDebug() << "selected language" << langCode; if (langCode!=DoxygenWizard::langCode) { // Restart the application if (discardUnsavedChanges()) { setLanguage(langCode); saveSettings(); qApp->quit(); QProcess::startDetached(qApp->arguments()[0], newArgs); } } } } 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::fromLatin1("recent/config%1").arg(i),QString::fromLatin1("")); } m_clearRecent->setEnabled(false); m_recentMenu->setEnabled(false); m_settings.sync(); } } 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::fromLatin1("wizard/loadsettings"), false); m_settings.sync(); m_modified = false; updateTitle(); m_wizard->refresh(); } } void MainWindow::loadSettings() { QVariant geometry = m_settings.value(QString::fromLatin1("main/geometry")); QVariant state = m_settings.value(QString::fromLatin1("main/state")); QVariant wizState = m_settings.value(QString::fromLatin1("wizard/state")); QVariant loadSettings = m_settings.value(QString::fromLatin1("wizard/loadsettings")); QVariant workingDir = m_settings.value(QString::fromLatin1("wizard/workingdir")); if (!geometry.isNull()) restoreGeometry(geometry.toByteArray()); if (!state.isNull()) restoreState (state.toByteArray()); if (!wizState.isNull()) m_wizard->restoreState(wizState.toByteArray()); if (!loadSettings.isNull() && loadSettings.toBool()) { m_expert->loadSettings(&m_settings); if (!workingDir.isNull() && QDir(workingDir.toString()).exists()) { setWorkingDir(workingDir.toString()); } } /* due to prepend use list in reversed order */ for (int i=MAX_RECENT_FILES;i>=0;i--) { QString entry = m_settings.value(QString::fromLatin1("recent/config%1").arg(i)).toString(); if (!entry.isEmpty() && QFileInfo(entry).exists()) { addRecentFileList(entry); } } updateRecentFile(); } void MainWindow::saveSettings() { QSettings settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard")); m_settings.setValue(QString::fromLatin1("main/geometry"), saveGeometry()); m_settings.setValue(QString::fromLatin1("main/state"), saveState()); m_settings.setValue(QString::fromLatin1("wizard/state"), m_wizard->saveState()); m_settings.setValue(QString::fromLatin1("wizard/workingdir"), m_workingDir->text()); } void MainWindow::selectTab(int id) { if (id==0) m_wizard->refresh(); else if (id==1) m_expert->refresh(); } void MainWindow::selectRunTab() { m_tabs->setCurrentIndex(2); } void MainWindow::addRecentFile(const QString &fileName) { addRecentFileList(fileName); updateRecentFile(); } void MainWindow::addRecentFileList(const QString &fileName) { int i=m_recentFiles.indexOf(fileName); if (i!=-1) m_recentFiles.removeAt(i); // not found if (m_recentFiles.count() < MAX_RECENT_FILES) // append { m_recentFiles.prepend(fileName); } else // add + drop last item { m_recentFiles.removeLast(); m_recentFiles.prepend(fileName); } m_clearRecent->setEnabled(m_recentFiles.count()>0); m_recentMenu->setEnabled(m_recentFiles.count()>0); m_settings.sync(); } void MainWindow::updateRecentFile(void) { m_recentMenu->clear(); int i=0; foreach( QString str, m_recentFiles ) { m_recentMenu->addAction(str); m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i++),str); } for (;i<MAX_RECENT_FILES;i++) { m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i),QString::fromLatin1("")); } m_clearRecent->setEnabled(m_recentFiles.count()>0); m_recentMenu->setEnabled(m_recentFiles.count()>0); m_settings.sync(); } void MainWindow::openRecent(QAction *action) { if (discardUnsavedChanges(false)) { loadConfigFromFile(action->text()); } } void MainWindow::runDoxygenMenu() { m_tabs->setCurrentWidget(m_runTab); runDoxygen(); } void MainWindow::runDoxygen() { if (!m_running) { QString doxygenPath; #if defined(Q_OS_MACOS) doxygenPath = qApp->applicationDirPath()+QString::fromLatin1("/../Resources/"); qDebug() << "Doxygen path: " << doxygenPath; if ( !QFile(doxygenPath + QString::fromLatin1("doxygen")).exists() ) { // No Doxygen binary in the resources, if there is a system Doxygen binary, use that instead if ( QFile(QString::fromLatin1("/usr/local/bin/doxygen")).exists() ) { doxygenPath = QString::fromLatin1("/usr/local/bin/"); } else { qDebug() << "Cannot find the doxygen command, make sure it's in your $$PATH"; doxygenPath = QString::fromLatin1(""); } } qDebug() << "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(QRegularExpression(QString::fromLatin1("^PWD=(.*)"),QRegularExpression::CaseInsensitiveOption), QString::fromLatin1("PWD=")+m_workingDir->text()); m_runProcess->setEnvironment(env); QStringList args; #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList runOptions = m_runOptions->text().split(QLatin1Char(' '),QString::SkipEmptyParts); #else QStringList runOptions = m_runOptions->text().split(QLatin1Char(' '),Qt::SkipEmptyParts); #endif args << runOptions; args << QString::fromLatin1("-b"); // make stdout unbuffered args << QString::fromLatin1("-"); // read config from stdin m_outputLog->clear(); m_runProcess->start(doxygenPath + QString::fromLatin1("doxygen"), args); if (!m_runProcess->waitForStarted()) { m_outputLog->append(APPQT(QString::fromLatin1("*** Failed to run doxygen\n"))); return; } QTextStream t(m_runProcess); m_expert->writeConfig(t,false,false,false); t.flush(); m_runProcess->closeWriteChannel(); if (m_runProcess->state() == QProcess::NotRunning) { m_outputLog->append(APPQT(QString::fromLatin1("*** Failed to run doxygen\n"))); } else { m_saveLog->setEnabled(false); m_running=true; m_run->setText(tr("Stop doxygen")); m_runMenu->setEnabled(false); 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::fromUtf8(data); if (!text.isEmpty()) { QScrollBar *vbar = m_outputLog->verticalScrollBar(); const QTextCursor old_cursor = m_outputLog->textCursor(); const bool is_scrolled_up = vbar->value() == vbar->maximum(); const int distanceFromBottom = vbar->minimum() - vbar->value(); m_outputLog->moveCursor(QTextCursor::End); m_outputLog->insertPlainText(text); if (old_cursor.hasSelection() || !is_scrolled_up) { m_outputLog->setTextCursor(old_cursor); vbar->setValue(vbar->minimum() - distanceFromBottom); } else { m_outputLog->moveCursor(QTextCursor::End); vbar->setValue(m_outputLog->verticalScrollBar()->maximum()); } } } } void MainWindow::runComplete() { if (m_running) { m_outputLog->append(APPQT(tr("*** Doxygen has finished\n"))); } else { m_outputLog->append(APPQT(tr("*** Canceled by user\n"))); } m_outputLog->ensureCursorVisible(); m_run->setText(tr("Run doxygen")); m_runStatus->setText(tr("Status: not running")); m_running=false; m_runMenu->setEnabled(true); 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); // TODO: the following doesn't seem to work with IE #ifdef _WIN32 //QString indexUrl(QString::fromLatin1("file:///")); ShellExecute(nullptr, L"open", (LPCWSTR)fi.absoluteFilePath().utf16(), nullptr, nullptr, SW_SHOWNORMAL); #else QString indexUrl(QString::fromLatin1("file://")); indexUrl+=fi.absoluteFilePath(); QDesktopServices::openUrl(QUrl(indexUrl)); #endif } void MainWindow::saveLog() { QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"), m_workingDir->text()+ QString::fromLatin1("/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(nullptr, tr("Warning"), tr("Cannot open file %1 for writing. Nothing saved!").arg(fn), QMessageBox::Ok); } } } void MainWindow::showSettings() { QString text; QTextStream t(&text); if (m_showCondensedSettings->isChecked()) { m_expert->writeConfig(t,true,true,true); } else { m_expert->writeConfig(t,true,false,true); } m_outputLog->clear(); m_outputLog->append(APPQT(text)); m_outputLog->ensureCursorVisible(); m_saveLog->setEnabled(true); } void MainWindow::dump() { m_expert->dump(); } void MainWindow::configChanged() { m_modified = true; updateTitle(); } void MainWindow::updateTitle() { QString title = tr("Doxygen GUI frontend"); m_resetDefault->setEnabled(m_modified); if (m_modified) { title+=QString::fromLatin1(" +"); } if (!m_fileName.isEmpty()) { title+=QString::fromLatin1(" (")+m_fileName+QString::fromLatin1(")"); } 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; } void MainWindow::outputLogStart() { m_outputLogTextCount = 0; m_outputLog->clear(); } void MainWindow::outputLogText(QString text) { m_outputLogTextCount++; m_outputLog->append(APPQT(text)); } void MainWindow::outputLogFinish() { if (m_outputLogTextCount > 0) { selectRunTab(); } m_outputLog->ensureCursorVisible(); m_saveLog->setEnabled(true); } static QString languagesList() { QString languages = QString::fromLatin1("en"); // add additional languages based on embedded info QDir resourceDir(QString::fromLatin1(":/i18n")); QFileInfoList fileList = resourceDir.entryInfoList(); QString prevLangCode; foreach (QFileInfo fileInfo, fileList) { QString filename = fileInfo.fileName(); const int underscore = filename.indexOf(QChar::fromLatin1('_')); const int dot = filename.lastIndexOf(QChar::fromLatin1('.')); if (filename.startsWith(QString::fromLatin1("config")) && underscore!=-1 && dot>underscore) { QString langCode = filename.mid(underscore+1, dot-underscore-1); QFile trFile(QString::fromLatin1(":/i18n/config_%1.xml").arg(langCode)); if (trFile.open(QIODevice::ReadOnly)) { if (!prevLangCode.isEmpty()) { languages += QString::fromLatin1(", ") + prevLangCode; } prevLangCode = langCode; } } } if (!prevLangCode.isEmpty()) { languages += QString::fromLatin1(" and ") + prevLangCode; } return languages; } #define TXT_ARGS QString::fromLatin1(argc > 2?"Too many arguments specified\n\n":"") static void usage(const char *exeName, const QString txt) { QMessageBox msgBox; QString fullText = txt; fullText += QString::fromLatin1("Usage:\n"); fullText += QString::fromLatin1(" %1 [--debug] [--dump] [--doxyfile] [--language [lang]] [config file]\n").arg(QString::fromLatin1(exeName)); fullText += QString::fromLatin1(" or\n"); fullText += QString::fromLatin1(" %1 --help\n").arg(QString::fromLatin1(exeName)); fullText += QString::fromLatin1(" or\n"); fullText += QString::fromLatin1(" %1 --version\n").arg(QString::fromLatin1(exeName)); msgBox.setText(fullText); msgBox.exec(); } //----------------------------------------------------------------------- int main(int argc,char **argv) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO"; if (!qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } #endif QApplication a(argc,argv); int optInd=1; bool langSet = false; bool dumpFlag = false; bool doxyfileFlag = false; QString langSel; while (optInd<argc && argv[optInd][0]=='-' && argv[optInd][1]=='-') { if (!qstrcmp(argv[optInd],"--help")) { usage(argv[0],TXT_ARGS); if (argc > 2) exit(1); exit(0); } else if (!qstrcmp(argv[optInd],"--version")) { QMessageBox msgBox; if (argc > 2) { usage(argv[0],TXT_ARGS); exit(1); } else if (!qstrcmp(qVersion(),QT_VERSION_STR)) { msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: %2").arg(QString::fromLatin1(getFullVersion().c_str())).arg(QString::fromLatin1(QT_VERSION_STR))); } else { msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: created with %2, running with %3").arg(QString::fromLatin1(getFullVersion().c_str())).arg(QString::fromLatin1(QT_VERSION_STR),QString::fromLatin1(qVersion()))); } msgBox.exec(); exit(0); } else if (!qstrcmp(argv[optInd],"--dump")) { dumpFlag = true; } else if (!qstrcmp(argv[optInd],"--doxyfile")) { doxyfileFlag = true; } else if (!qstrcmp(argv[optInd],"--debug")) { DoxygenWizard::debugFlag = true; newArgs.push_back(QString::fromLatin1(argv[optInd])); } else if (!qstrcmp(argv[optInd],"--language")) { langSet = true; if (optInd+1>=argc || (argv[optInd+1][0]=='-' && argv[optInd+1][1]=='-')) { langSel = QString::fromLatin1("en"); } else { langSel = QString::fromLatin1(argv[optInd+1]); optInd++; } if (!isLanguageCodeSupported(langSel)) { usage(argv[0],QString::fromLatin1("Unknown language selected\n available languages: ") + languagesList() + QString::fromLatin1("\n\n")); exit(1); } } optInd++; } if (optInd+2<=argc) { usage(argv[0],TXT_ARGS); exit(1); } { qDebug() << "Starting doxywizard..."; QString initialPath = QDir::currentPath(); if (langSet) { DoxygenWizard::langCode = langSel; } else { DoxygenWizard::langCode = getStartupLanguageCode(); } QTranslator qtTranslator; if (!DoxygenWizard::langCode.isEmpty() && qtTranslator.load(QString::fromLatin1(":/i18n/qtbase_%1.qm").arg(DoxygenWizard::langCode)) ) { qDebug() << "Installing qt translator" << DoxygenWizard::langCode; a.installTranslator(&qtTranslator); } QTranslator appTranslator; if (!DoxygenWizard::langCode.isEmpty() && appTranslator.load(QString::fromLatin1(":/i18n/doxywizard_%1.qm").arg(DoxygenWizard::langCode)) ) { qDebug() << "Installing app translator" << DoxygenWizard::langCode; a.installTranslator(&appTranslator); } MainWindow &main = MainWindow::instance(); if (langSet) { main.setLanguage(langSel); } if (optInd+1==argc && argv[argc-1][0]!='-') // name of config file as an argument { newArgs.push_back(QString::fromLatin1(argv[argc-1])); main.loadConfigFromFile(QString::fromLocal8Bit(argv[argc-1])); } if (dumpFlag) { main.setWorkingDir(initialPath); main.dump(); } if (doxyfileFlag) { QString fn = QString::fromLatin1("Doxyfile_%1").arg(DoxygenWizard::langCode); main.setWorkingDir(initialPath); main.saveConfig(fn); } if (dumpFlag ||doxyfileFlag) exit(0); main.show(); return a.exec(); } }