UniversalIndentGUI 1.2.0
IndentHandler.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2012 by Thomas Schweitzer                          *
00003  *   thomas-schweitzer(at)arcor.de                                         *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License version 2.0 as   *
00007  *   published by the Free Software Foundation.                            *
00008  *                                                                         *
00009  *   This program is distributed in the hope that it will be useful,       *
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012  *   GNU General Public License for more details.                          *
00013  *                                                                         *
00014  *   You should have received a copy of the GNU General Public License     *
00015  *   along with this program in the file LICENSE.GPL; if not, write to the *
00016  *   Free Software Foundation, Inc.,                                       *
00017  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00018  ***************************************************************************/
00019 
00020 #include "IndentHandler.h"
00021 
00022 #include "UiGuiSettings.h"
00023 #include "UiGuiErrorMessage.h"
00024 #include "TemplateBatchScript.h"
00025 #include "UiGuiIniFileParser.h"
00026 #include "SettingsPaths.h"
00027 
00028 #include <QToolBox>
00029 #include <QVBoxLayout>
00030 #include <QApplication>
00031 #include <QCheckBox>
00032 #include <QComboBox>
00033 #include <QToolButton>
00034 #include <QFile>
00035 #include <QProcess>
00036 #include <QSettings>
00037 #include <QStringList>
00038 #include <QLineEdit>
00039 #include <QSpinBox>
00040 #include <QLabel>
00041 #include <QByteArray>
00042 #include <QDir>
00043 #include <QMessageBox>
00044 #include <QMainWindow>
00045 #include <QTextStream>
00046 #include <QTextCodec>
00047 #include <QtScript>
00048 #include <QDesktopServices>
00049 #include <QMenu>
00050 #include <QAction>
00051 #include <QContextMenuEvent>
00052 #include <QFileDialog>
00053 #include <QtDebug>
00054 
00055 #ifdef Q_OS_WIN32
00056 #include <Windows.h>
00057 #endif
00058 
00059 // Avoid unused parameter warnings by this template
00060 template<typename T>
00061 inline void UNUSED_PARAMETER_WARNING_AVOID(T){}
00062 
00064 
00084 IndentHandler::IndentHandler(int indenterID, QWidget *mainWindow, QWidget *parent) : QWidget(parent)
00085     , _indenterSelectionCombobox(NULL)
00086     , _indenterParameterHelpButton(NULL)
00087     , _toolBoxContainerLayout(NULL)
00088     , _indenterParameterCategoriesToolBox(NULL)
00089     , _indenterSettings(NULL)
00090     , _mainWindow(NULL)
00091     , _errorMessageDialog(NULL)
00092     , _menuIndenter(NULL)
00093     , _actionLoadIndenterConfigFile(NULL)
00094     , _actionSaveIndenterConfigFile(NULL)
00095     , _actionCreateShellScript(NULL)
00096     , _actionResetIndenterParameters(NULL)
00097     , _parameterChangedCallback(NULL)
00098     , _windowClosedCallback(NULL)
00099 {
00100     Q_ASSERT_X( indenterID >= 0, "IndentHandler", "the selected indenterID is < 0" );
00101 
00102     setObjectName(QString::fromUtf8("indentHandler"));
00103 
00104     _mainWindow = mainWindow;
00105 
00106     initIndenterMenu();
00107 
00108     connect( _actionLoadIndenterConfigFile, SIGNAL(triggered()), this, SLOT(openConfigFileDialog()) );
00109     connect( _actionSaveIndenterConfigFile, SIGNAL(triggered()), this, SLOT(saveasIndentCfgFileDialog()) );
00110     connect( _actionCreateShellScript, SIGNAL(triggered()), this, SLOT(createIndenterCallShellScript()) );
00111     connect( _actionResetIndenterParameters, SIGNAL(triggered()), this, SLOT(resetIndenterParameter()) );
00112 
00113     // define this widgets resize behavior
00114     setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00115 
00116     // create vertical layout box, into which the toolbox will be added
00117     _toolBoxContainerLayout = new QVBoxLayout(this);
00118     _toolBoxContainerLayout->setMargin(2);
00119 
00120     // Create horizontal layout for indenter selector and help button.
00121     QHBoxLayout *hboxLayout = new QHBoxLayout();
00122     //hboxLayout->setMargin(2);
00123     _toolBoxContainerLayout->addLayout( hboxLayout );
00124 
00125     // Create the indenter selection combo box.
00126     _indenterSelectionCombobox = new QComboBox(this);
00127     _indenterSelectionCombobox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
00128     _indenterSelectionCombobox->setMinimumContentsLength(20);
00129     connect( _indenterSelectionCombobox, SIGNAL(activated(int)), this, SLOT(setIndenter(int)) );
00130     UiGuiSettings::getInstance()->registerObjectProperty(_indenterSelectionCombobox, "currentIndex", "selectedIndenter");
00131     hboxLayout->addWidget( _indenterSelectionCombobox );
00132 
00133     // Create the indenter parameter help button.
00134     _indenterParameterHelpButton = new QToolButton(this);
00135     _indenterParameterHelpButton->setObjectName(QString::fromUtf8("indenterParameterHelpButton"));
00136     _indenterParameterHelpButton->setIcon(QIcon(QString::fromUtf8(":/mainWindow/help.png")));
00137     hboxLayout->addWidget( _indenterParameterHelpButton );
00138     // Handle if the indenter parameter help button is pressed.
00139     connect( _indenterParameterHelpButton, SIGNAL(clicked()), this, SLOT(showIndenterManual()) );
00140 
00141     // create a toolbox and set its resize behavior
00142     _indenterParameterCategoriesToolBox = new QToolBox(this);
00143     _indenterParameterCategoriesToolBox->setObjectName(QString::fromUtf8("_indenterParameterCategoriesToolBox"));
00144 
00145 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
00146     connect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) );
00147 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
00148 
00149     //_indenterParameterCategoriesToolBox->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
00150     //_indenterParameterCategoriesToolBox->setMaximumSize(QSize(16777215, 16777215));
00151     // insert the toolbox into the vlayout
00152     _toolBoxContainerLayout->addWidget(_indenterParameterCategoriesToolBox);
00153 
00154     _indenterExecutableCallString = "";
00155     _indenterExecutableSuffix = "";
00156 
00157     _indenterDirctoryStr = SettingsPaths::getIndenterPath();
00158     _tempDirctoryStr = SettingsPaths::getTempPath();
00159     _settingsDirctoryStr = SettingsPaths::getSettingsPath();
00160     QDir indenterDirctory = QDir(_indenterDirctoryStr);
00161 
00162     if ( _mainWindow != NULL ) {
00163         _errorMessageDialog = new UiGuiErrorMessage(_mainWindow);
00164     }
00165     else {
00166         _errorMessageDialog = new UiGuiErrorMessage(this);
00167     }
00168 
00169     _indenterIniFileList = indenterDirctory.entryList( QStringList("uigui_*.ini") );
00170     if ( _indenterIniFileList.count() > 0 ) {
00171         // Take care if the selected indenterID is smaller or greater than the number of existing indenters
00172         if ( indenterID < 0 ) {
00173             indenterID = 0;
00174         }
00175         if ( indenterID >= _indenterIniFileList.count() ) {
00176             indenterID = _indenterIniFileList.count() - 1;
00177         }
00178 
00179         // Reads and parses the by indenterID defined indent ini file and creates toolbox entries
00180         readIndentIniFile( _indenterDirctoryStr + "/" + _indenterIniFileList.at(indenterID) );
00181 
00182         // Find out how the indenter can be executed.
00183         createIndenterCallString();
00184 
00185         // Load the users last settings made for this indenter.
00186         loadConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg" );
00187 
00188         // Fill the indenter selection combo box with the list of available indenters.
00189         if ( !getAvailableIndenters().isEmpty() ) {
00190             _indenterSelectionCombobox->addItems( getAvailableIndenters() );
00191             _indenterSelectionCombobox->setCurrentIndex( indenterID );
00192             connect( _indenterSelectionCombobox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(selectedIndenterIndexChanged(int)) );
00193         }
00194     }
00195     else {
00196         _errorMessageDialog->showMessage(tr("No indenter ini files"), tr("There exists no indenter ini files in the directory \"") + QDir(_indenterDirctoryStr).absolutePath() + "\".");
00197     }
00198 
00199     retranslateUi();
00200 }
00201 
00202 
00206 IndentHandler::~IndentHandler() {
00207     // Generate the parameter string that will be saved to the indenters config file.
00208     QString parameterString = getParameterString();
00209     if ( !_indenterFileName.isEmpty() ) {
00210         saveConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg", parameterString );
00211     }
00212 
00213     delete _errorMessageDialog;
00214 }
00215 
00216 
00220 void IndentHandler::initIndenterMenu() {
00221     if ( _menuIndenter == NULL ) {
00222         _actionLoadIndenterConfigFile = new QAction(this);
00223         _actionLoadIndenterConfigFile->setObjectName(QString::fromUtf8("_actionLoadIndenterConfigFile"));
00224         _actionLoadIndenterConfigFile->setIcon(QIcon(QString::fromUtf8(":/mainWindow/load_indent_cfg.png")));
00225 
00226         _actionSaveIndenterConfigFile = new QAction(this);
00227         _actionSaveIndenterConfigFile->setObjectName(QString::fromUtf8("_actionSaveIndenterConfigFile"));
00228         _actionSaveIndenterConfigFile->setIcon(QIcon(QString::fromUtf8(":/mainWindow/save_indent_cfg.png")));
00229 
00230         _actionCreateShellScript = new QAction(this);
00231         _actionCreateShellScript->setObjectName(QString::fromUtf8("_actionCreateShellScript"));
00232         _actionCreateShellScript->setIcon(QIcon(QString::fromUtf8(":/mainWindow/shell.png")));
00233 
00234         _actionResetIndenterParameters = new QAction(this);
00235         _actionResetIndenterParameters->setObjectName(QString::fromUtf8("_actionResetIndenterParameters"));
00236         _actionResetIndenterParameters->setIcon(QIcon(QString::fromUtf8(":/mainWindow/view-refresh.png")));
00237 
00238         _menuIndenter = new QMenu(this);
00239         _menuIndenter->setObjectName(QString::fromUtf8("_menuIndenter"));
00240         _menuIndenter->addAction(_actionLoadIndenterConfigFile);
00241         _menuIndenter->addAction(_actionSaveIndenterConfigFile);
00242         _menuIndenter->addAction(_actionCreateShellScript);
00243         _menuIndenter->addAction(_actionResetIndenterParameters);
00244     }
00245 }
00246 
00247 
00251 QMenu* IndentHandler::getIndenterMenu() {
00252     return _menuIndenter;
00253 }
00254 
00255 
00259 QList<QAction*> IndentHandler::getIndenterMenuActions() {
00260     QList<QAction*> actionList;
00261     actionList << _actionLoadIndenterConfigFile << _actionSaveIndenterConfigFile << _actionCreateShellScript << _actionResetIndenterParameters;
00262     return actionList;
00263 }
00264 
00265 
00269 void IndentHandler::contextMenuEvent( QContextMenuEvent *event ) {
00270     getIndenterMenu()->exec( event->globalPos() );
00271 }
00272 
00273 
00278 QString IndentHandler::generateShellScript(const QString &configFilename) {
00279     QString indenterCompleteCallString;
00280     QString parameterInputFile;
00281     QString parameterOuputFile;
00282     QString parameterParameterFile;
00283     QString replaceInputFileCommand;
00284 
00285     // Define the placeholder for parameter variables either in batch or bash programming.
00286 #if defined(Q_OS_WIN32)
00287     QString shellParameterPlaceholder = "%1";
00288 #else
00289     QString shellParameterPlaceholder = "$1";
00290 #endif
00291 
00292     parameterInputFile = " " + _inputFileParameter + "\"" + shellParameterPlaceholder + "\"";
00293 
00294     if ( _outputFileParameter != "none" && _outputFileParameter != "stdout" ) {
00295         if ( _outputFileName == _inputFileName ) {
00296             parameterOuputFile = " " + _outputFileParameter + "\"" + shellParameterPlaceholder + "\"";
00297         }
00298         else {
00299             parameterOuputFile = " " + _outputFileParameter + _outputFileName + ".tmp";
00300         }
00301     }
00302 
00303     // If the config file name is empty it is assumed that all parameters are sent via command line call
00304     if ( _globalConfigFilename.isEmpty() ) {
00305         parameterParameterFile = " " + getParameterString();
00306     }
00307     // else if needed add the parameter to the indenter call string where the config file can be found.
00308     else if (_useCfgFileParameter != "none") {
00309         parameterParameterFile = " " + _useCfgFileParameter + "\"./" + configFilename + "\"";
00310     }
00311 
00312     // Assemble indenter call string for parameters according to the set order.
00313     if ( _parameterOrder == "ipo" ) {
00314         indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile;
00315     }
00316     else if ( _parameterOrder == "pio" ) {
00317         indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile;
00318     }
00319     else if ( _parameterOrder == "poi" ) {
00320         indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile;
00321     }
00322     else {
00323         indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile;
00324     }
00325 
00326     // Generate the indenter call string either for win32 or other systems.
00327 #if defined(Q_OS_WIN32)
00328     indenterCompleteCallString = _indenterExecutableCallString + indenterCompleteCallString;
00329 #else
00330     indenterCompleteCallString = "#!/bin/bash\n" + _indenterExecutableCallString + indenterCompleteCallString;
00331 #endif
00332 
00333     // If the indenter writes to stdout pipe the output into a file
00334     if ( _outputFileParameter == "stdout" ) {
00335         indenterCompleteCallString = indenterCompleteCallString + " >" + _outputFileName + ".tmp";
00336     }
00337 
00338     // If the output filename is not the same as the input filename copy the output over the input.
00339     if ( _outputFileName != _inputFileName ) {
00340 #if defined(Q_OS_WIN32)
00341         replaceInputFileCommand = "move /Y " + _outputFileName + ".tmp \"" + shellParameterPlaceholder + "\"\n";
00342 #else
00343         replaceInputFileCommand = "mv " + _outputFileName + ".tmp \"" + shellParameterPlaceholder + "\"\n";
00344 #endif
00345     }
00346 
00347 #if defined(Q_OS_WIN32)
00348     QString shellScript( TemplateBatchScript::getTemplateBatchScript() );
00349     shellScript = shellScript.replace("__INDENTERCALLSTRING2__", indenterCompleteCallString + "\n" + replaceInputFileCommand);
00350     indenterCompleteCallString = indenterCompleteCallString.replace("%1", "%%G");
00351     replaceInputFileCommand = replaceInputFileCommand.replace("%1", "%%G");
00352     shellScript = shellScript.replace("__INDENTERCALLSTRING1__", indenterCompleteCallString + "\n" + replaceInputFileCommand);
00353 #else
00354     QString shellScript( TemplateBatchScript::getTemplateBatchScript() );
00355     shellScript = shellScript.replace("__INDENTERCALLSTRING2__", indenterCompleteCallString + "\n" + replaceInputFileCommand);
00356     indenterCompleteCallString = indenterCompleteCallString.replace("$1", "$file2indent");
00357     replaceInputFileCommand = replaceInputFileCommand.replace("$1", "$file2indent");
00358     shellScript = shellScript.replace("__INDENTERCALLSTRING1__", indenterCompleteCallString + "\n" + replaceInputFileCommand);
00359 #endif
00360 
00361     return shellScript;
00362 }
00363 
00364 
00371 QString IndentHandler::callIndenter(QString sourceCode, QString inputFileExtension) {
00372     if ( _indenterExecutableSuffix == ".js" ) {
00373         return callJavaScriptIndenter(sourceCode);
00374     }
00375     else {
00376         return callExecutableIndenter(sourceCode, inputFileExtension);
00377     }
00378 }
00379 
00380 
00387 QString IndentHandler::callJavaScriptIndenter(QString sourceCode) {
00388     QScriptEngine engine;
00389 
00390     engine.globalObject().setProperty("unformattedCode", sourceCode);
00391 
00392     QFile jsDecoderFile( _indenterExecutableCallString );
00393     QString jsDecoderCode;
00394     if (jsDecoderFile.open(QFile::ReadOnly)) {
00395         jsDecoderCode = jsDecoderFile.readAll();
00396     }
00397     jsDecoderFile.close();
00398 
00399     QScriptValue value = engine.evaluate(jsDecoderCode);
00400     return value.toString();
00401 }
00402 
00403 
00410 QString IndentHandler::callExecutableIndenter(QString sourceCode, QString inputFileExtension) {
00411     Q_ASSERT_X( !_inputFileName.isEmpty(), "callIndenter", "_inputFileName is empty" );
00412 //    Q_ASSERT_X( !_outputFileName.isEmpty(), "callIndenter", "_outputFileName is empty" );
00413     Q_ASSERT_X( !_indenterFileName.isEmpty(), "callIndenter", "_indenterFileName is empty" );
00414 
00415     if ( _indenterFileName.isEmpty() ) {
00416         return "";
00417     }
00418 
00419     QString formattedSourceCode;
00420     QString indenterCompleteCallString;
00421     QString parameterInputFile;
00422     QString parameterOuputFile;
00423     QString parameterParameterFile;
00424     QProcess indentProcess;
00425     QString processReturnString;
00426 
00427     // Generate the parameter string that will be saved to the indenters config file
00428     QString parameterString = getParameterString();
00429 
00430     if ( !_globalConfigFilename.isEmpty() ) {
00431         saveConfigFile( _tempDirctoryStr + "/" + _globalConfigFilename, parameterString );
00432     }
00433 
00434     // Only add a dot to file extension if the string is not empty
00435     if ( !inputFileExtension.isEmpty() ) {
00436         inputFileExtension = "." + inputFileExtension;
00437     }
00438 
00439     // Delete any previously used input src file and create a new input src file.
00440     QFile::remove(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension);
00441     QFile inputSrcFile(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension);
00442     // Write the source code to the input file for the indenter
00443     if ( inputSrcFile.open( QFile::ReadWrite | QFile::Text ) ) {
00444         inputSrcFile.write( sourceCode.toUtf8() );
00445         inputSrcFile.close();
00446         qDebug() << __LINE__ << " " << __FUNCTION__ << ": Wrote to be indented source code to file " << inputSrcFile.fileName();
00447     }
00448     else {
00449         qCritical() << __LINE__ << " " << __FUNCTION__ << ": Couldn't write to be indented source code to file " << inputSrcFile.fileName();
00450     }
00451 
00452     // Set the input file for the to be called indenter.
00453     if ( _inputFileParameter.trimmed() == "<" || _inputFileParameter == "stdin" ) {
00454         parameterInputFile = "";
00455         indentProcess.setStandardInputFile( inputSrcFile.fileName() );
00456     }
00457     else {
00458         parameterInputFile = " " + _inputFileParameter + _inputFileName + inputFileExtension;
00459     }
00460 
00461     // Set the output file for the to be called indenter.
00462     if ( _outputFileParameter != "none" && _outputFileParameter != "stdout" ) {
00463         parameterOuputFile = " " + _outputFileParameter + _outputFileName + inputFileExtension;
00464     }
00465 
00466 #ifdef Q_OS_WIN32
00467     // Paths may contain Unicode or other foreign characters. Windows commands line tools will
00468     // receive als falsely encoded path string by QProcess or they connot correctly handle
00469     // the Unicode path on their own.
00470     // Because of this the path gets converted to Windows short paths using the 8.3 notation.
00471 
00472     qDebug() << __LINE__ << " " << __FUNCTION__ << ": Temp dir before trying to convert it to short Windows path is" << _tempDirctoryStr;
00473 
00474     // At first convert the temp path to Windows like separators.
00475     QString tempDirctoryStrHelper = QDir::toNativeSeparators(_tempDirctoryStr).replace("\\", "\\\\");
00476     // Then convert the QString to a WCHAR array and NULL terminate it.
00477     WCHAR *tempDirctoryWindowsStr = new WCHAR[ tempDirctoryStrHelper.length()+1 ];
00478     tempDirctoryStrHelper.toWCharArray( tempDirctoryWindowsStr );
00479     tempDirctoryWindowsStr[ tempDirctoryStrHelper.length() ] = (WCHAR)NULL;
00480 
00481     // Get the length of the resulting short path.
00482     long length = 0;
00483     TCHAR *buffer = NULL;
00484     length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, NULL, 0);
00485 
00486     // If the short path could be retrieved, create a correct sized buffer, store the
00487     // short path in it and convert all back to QString.
00488     if ( length != 0 ) {
00489 #ifdef UNICODE
00490         buffer = new WCHAR[length];
00491         length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, buffer, length);
00492         tempDirctoryStrHelper = QString::fromWCharArray( buffer );
00493 #else
00494         buffer = new TCHAR[length];
00495         length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, buffer, length);
00496         tempDirctoryStrHelper = buffer;
00497 #endif
00498         _tempDirctoryStr = QDir::fromNativeSeparators(tempDirctoryStrHelper).replace("//", "/");
00499         delete [] buffer;
00500 
00501         // Check whether the short path still contains some kind of non ascii characters.
00502         if ( _tempDirctoryStr.length() != _tempDirctoryStr.toAscii().length() ) {
00503             qWarning() << __LINE__ << " " << __FUNCTION__ << ": Shortened path still contains non ascii characters. Could cause some indenters not to work properly!";
00504         }
00505     }
00506     else {
00507         qWarning() << __LINE__ << " " << __FUNCTION__ << ": Couldn't retrieve a short version of the temporary path!";
00508     }
00509 
00510     qDebug() << __LINE__ << " " << __FUNCTION__ << ": Temp dir after trying to convert it to short Windows path is " << _tempDirctoryStr;
00511 
00512     delete [] tempDirctoryWindowsStr;
00513 #endif
00514 
00515     // If the config file name is empty it is assumed that all parameters are sent via command line call
00516     if ( _globalConfigFilename.isEmpty() ) {
00517         parameterParameterFile = " " + parameterString;
00518     }
00519     // if needed add the parameter to the indenter call string where the config file can be found
00520     else if (_useCfgFileParameter != "none") {
00521         parameterParameterFile = " " + _useCfgFileParameter + "\"" + _tempDirctoryStr + "/" + _globalConfigFilename + "\"";
00522     }
00523 
00524     // Assemble indenter call string for parameters according to the set order.
00525     if ( _parameterOrder == "ipo" ) {
00526         indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile;
00527     }
00528     else if ( _parameterOrder == "pio" ) {
00529         indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile;
00530     }
00531     else if ( _parameterOrder == "poi" ) {
00532         indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile;
00533     }
00534     else {
00535         indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile;
00536     }
00537 
00538     // If no indenter executable call string could be created before, show an error message.
00539     if ( _indenterExecutableCallString.isEmpty() ) {
00540         _errorMessageDialog->showMessage(tr("No indenter executable"),
00541             tr("There exists no indenter executable with the name \"%1\" in the directory \"%2\" nor in the global environment.").arg(_indenterFileName).arg(_indenterDirctoryStr) );
00542         return sourceCode;
00543     }
00544 
00545     // Generate the indenter call string either for win32 or other systems.
00546     indenterCompleteCallString = _indenterExecutableCallString + indenterCompleteCallString;
00547 
00548     // errors and standard outputs from the process call are merged together
00549     //indentProcess.setReadChannelMode(QProcess::MergedChannels);
00550 
00551     // Set the directory where the indenter will be executed for the process' environment as PWD.
00552     QStringList env = indentProcess.environment();
00553     env << "PWD=" + QFileInfo(_tempDirctoryStr).absoluteFilePath();
00554     indentProcess.setEnvironment( env );
00555 
00556     // Set the directory for the indenter execution
00557     indentProcess.setWorkingDirectory( QFileInfo(_tempDirctoryStr).absoluteFilePath() );
00558 
00559     qDebug() << __LINE__ << " " << __FUNCTION__ << ": Will call the indenter in the directory " << indentProcess.workingDirectory() << " using this commandline call: " << indenterCompleteCallString;
00560 
00561     indentProcess.start(indenterCompleteCallString);
00562 
00563     processReturnString = "";
00564     bool calledProcessSuccessfully = indentProcess.waitForFinished(10000);
00565     // test if there was an error during starting the process of the indenter
00566     if ( !calledProcessSuccessfully ) {
00567         processReturnString = "<html><body>";
00568         processReturnString += tr("<b>Returned error message:</b> ") + indentProcess.errorString() + "<br>";
00569 
00570         switch ( indentProcess.error() ) {
00571             case QProcess::FailedToStart :
00572                 processReturnString += tr("<b>Reason could be:</b> ") + "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.<br>";
00573                 break;
00574             case QProcess::Crashed :
00575                 processReturnString += "The process crashed some time after starting successfully.<br>";
00576                 break;
00577             case QProcess::Timedout :
00578                 processReturnString += "The called indenter did not response for over 10 seconds, so aborted its execution.<br>";
00579                 break;
00580             case QProcess::WriteError :
00581                 processReturnString += "An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.<br>";
00582                 break;
00583             case QProcess::ReadError :
00584                 processReturnString += "An error occurred when attempting to read from the process. For example, the process may not be running.<br>";
00585                 break;
00586             case QProcess::UnknownError :
00587                 processReturnString += "An unknown error occurred. This is the default return value of error().<br>";
00588                 break;
00589             default :
00590                 break;
00591         }
00592         processReturnString += tr("<br><b>Callstring was:</b> ") + encodeToHTML(indenterCompleteCallString);
00593         processReturnString += tr("<br><br><b>Indenter output was:</b><pre>") + "<br>" +
00594             "(STDOUT):" + encodeToHTML( indentProcess.readAllStandardOutput() ) + "<br>" +
00595             "(STDERR):" + encodeToHTML( indentProcess.readAllStandardError() ) + "<br>" +
00596             "</pre></html></body>";
00597         qWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString;
00598         QApplication::restoreOverrideCursor();
00599         _errorMessageDialog->showMessage(tr("Error calling Indenter"), processReturnString);
00600     }
00601 
00602 
00603     // If the indenter returned an error code != 0 show its output.
00604     if ( indentProcess.exitCode() != 0 ) {
00605         QString exitCode;
00606         exitCode.setNum(indentProcess.exitCode());
00607         processReturnString = tr("<b>Indenter returned with exit code:</b> ") + exitCode + "<br>" +
00608             tr("<b>Indent console output was:</b> ") + "<br>" +
00609             "(STDOUT):" + encodeToHTML( indentProcess.readAllStandardOutput() ) + "<br>" +
00610             "(STDERR):" + encodeToHTML( indentProcess.readAllStandardError() ) + "<br>" +
00611             tr("<br><b>Callstring was:</b> ") + encodeToHTML(indenterCompleteCallString) +
00612             "</html></body>";
00613         qWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString;
00614         QApplication::restoreOverrideCursor();
00615         _errorMessageDialog->showMessage( tr("Indenter returned error"), processReturnString );
00616     }
00617 
00618     // Only get the formatted source code, if calling the indenter did succeed.
00619     if ( calledProcessSuccessfully ) {
00620         // If the indenter results are written to stdout, read them from there...
00621         if ( indentProcess.exitCode() == 0 && _outputFileParameter == "stdout"  ) {
00622             formattedSourceCode = indentProcess.readAllStandardOutput();
00623             qDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from StdOut.";
00624         }
00625         // ... else read the output file generated by the indenter call.
00626         else {
00627             QFile outSrcFile(_tempDirctoryStr + "/" + _outputFileName + inputFileExtension);
00628             if ( outSrcFile.open(QFile::ReadOnly | QFile::Text) ) {
00629                 QTextStream outSrcStrm(&outSrcFile);
00630                 outSrcStrm.setCodec( QTextCodec::codecForName("UTF-8") );
00631                 formattedSourceCode = outSrcStrm.readAll();
00632                 outSrcFile.close();
00633                 qDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from file " << outSrcFile.fileName();
00634             }
00635             else {
00636                 qCritical() << __LINE__ << " " << __FUNCTION__ << ": Couldn't read indenter output from file " << outSrcFile.fileName();
00637             }
00638         }
00639     }
00640     else {
00641         return sourceCode;
00642     }
00643 
00644     // Delete the temporary input and output files.
00645     QFile::remove(_tempDirctoryStr + "/" + _outputFileName + inputFileExtension);
00646     QFile::remove(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension);
00647 
00648     return formattedSourceCode;
00649 }
00650 
00651 
00655 QString IndentHandler::getParameterString() {
00656     QString parameterString = "";
00657 
00658     // generate parameter string for all boolean values
00659     foreach (ParamBoolean pBoolean, _paramBooleans) {
00660         if ( pBoolean.checkBox->isChecked() ) {
00661             if ( !pBoolean.trueString.isEmpty() ) {
00662                 parameterString += pBoolean.trueString + _cfgFileParameterEnding;
00663             }
00664         }
00665         else {
00666             if ( !pBoolean.falseString.isEmpty() ) {
00667                 parameterString += pBoolean.falseString + _cfgFileParameterEnding;
00668             }
00669         }
00670     }
00671 
00672     // generate parameter string for all numeric values
00673     foreach (ParamNumeric pNumeric, _paramNumerics) {
00674         if ( pNumeric.valueEnabledChkBox->isChecked() ) {
00675             parameterString += pNumeric.paramCallName + QString::number( pNumeric.spinBox->value() ) + _cfgFileParameterEnding;
00676         }
00677     }
00678 
00679     // generate parameter string for all string values
00680     foreach (ParamString pString, _paramStrings) {
00681         if ( !pString.lineEdit->text().isEmpty() && pString.valueEnabledChkBox->isChecked() ) {
00682             // Create parameter definition for each value devided by a | sign.
00683             foreach (QString paramValue, pString.lineEdit->text().split("|")) {
00684                 parameterString += pString.paramCallName + paramValue + _cfgFileParameterEnding;
00685             }
00686         }
00687     }
00688 
00689     // generate parameter string for all multiple choice values
00690     foreach (ParamMultiple pMultiple, _paramMultiples) {
00691         if ( pMultiple.valueEnabledChkBox->isChecked() ) {
00692             parameterString += pMultiple.choicesStrings.at( pMultiple.comboBox->currentIndex () ) + _cfgFileParameterEnding;
00693         }
00694     }
00695 
00696     return parameterString;
00697 }
00698 
00699 
00703 void IndentHandler::saveConfigFile(QString filePathName, QString paramString) {
00704     QFile::remove( filePathName );
00705     QFile cfgFile( filePathName );
00706 
00707     cfgFile.open( QFile::ReadWrite | QFile::Text );
00708     cfgFile.write( paramString.toAscii() );
00709     cfgFile.close();
00710 }
00711 
00712 
00716 bool IndentHandler::loadConfigFile(QString filePathName) {
00717     QFile cfgFile(filePathName);
00718     int index;
00719     int crPos;
00720     int paramValue = 0;
00721     QString paramValueStr = "";
00722     QString cfgFileData = "";
00723 
00724     // If the to be loaded config file does not exist leave all values as they are and return false.
00725     if ( !cfgFile.exists() ) {
00726         return false;
00727     }
00728     // else if the to be read config file exists, retrieve its whole content.
00729     else {
00730         // Open the config file and read all data
00731         cfgFile.open( QFile::ReadOnly | QFile::Text );
00732         cfgFileData = cfgFile.readAll();
00733         cfgFile.close();
00734     }
00735 
00736     // Search for name of each boolean parameter and set its value if found.
00737     foreach (ParamBoolean pBoolean, _paramBooleans) {
00738         // boolean value that will be assigned to the checkbox
00739         bool paramValue = false;
00740 
00741         // first search for the longer parameter string
00742         // the true parameter string is longer than the false string
00743         if ( pBoolean.trueString.length() > pBoolean.falseString.length() ) {
00744             // search for the true string
00745             index = cfgFileData.indexOf( pBoolean.trueString, 0, Qt::CaseInsensitive );
00746             // if true string found set the parameter value to true
00747             if ( index != -1 ) {
00748                 paramValue = true;
00749             }
00750             // if true string not found, search for false string
00751             else {
00752                 index = cfgFileData.indexOf( pBoolean.falseString, 0, Qt::CaseInsensitive );
00753                 // if false string found set the parameter value to false
00754                 if ( index != -1 ) {
00755                     paramValue = false;
00756                 }
00757                 // neither true nor false parameter found so use default value
00758                 else {
00759                     paramValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool();
00760                 }
00761             }
00762         }
00763         // the false parameter string is longer than the true string
00764         else {
00765             // search for the false string
00766             index = cfgFileData.indexOf( pBoolean.falseString, 0, Qt::CaseInsensitive );
00767             // if false string found set the parameter value to false
00768             if ( index != -1 ) {
00769                 paramValue = false;
00770             }
00771             // if false string not found, search for true string
00772             else {
00773                 index = cfgFileData.indexOf( pBoolean.trueString, 0, Qt::CaseInsensitive );
00774                 // if true string found set the parameter value to true
00775                 if ( index != -1 ) {
00776                     paramValue = true;
00777                 }
00778                 // neither true nor false parameter found so use default value
00779                 else {
00780                     paramValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool();
00781                 }
00782             }
00783         }
00784         pBoolean.checkBox->setChecked(paramValue);
00785     }
00786 
00787     // Search for name of each numeric parameter and set the value found behind it.
00788     foreach (ParamNumeric pNumeric, _paramNumerics) {
00789         index = cfgFileData.indexOf( pNumeric.paramCallName, 0, Qt::CaseInsensitive );
00790         // parameter was found in config file
00791         if ( index != -1 ) {
00792             // set index after the parameter name, so in front of the number
00793             index += pNumeric.paramCallName.length();
00794 
00795             // Find the end of the parameter by searching for set config file parameter ending. Most of time this is a carriage return.
00796             crPos = cfgFileData.indexOf( _cfgFileParameterEnding, index+1 );
00797 
00798             // get the number and convert it to int
00799             QString test = cfgFileData.mid( index, crPos - index );
00800             paramValue = cfgFileData.mid( index, crPos - index ).toInt(NULL);
00801 
00802             // disable the signal-slot connection. Otherwise signal is emmitted each time when value is set
00803             QObject::disconnect(pNumeric.spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings()));
00804             pNumeric.spinBox->setValue( paramValue );
00805             pNumeric.valueEnabledChkBox->setChecked( true );
00806             QObject::connect(pNumeric.spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings()));
00807         }
00808         // parameter was not found in config file
00809         else {
00810             int defaultValue = _indenterSettings->value(pNumeric.paramName + "/ValueDefault").toInt();
00811             pNumeric.spinBox->setValue( defaultValue );
00812             pNumeric.valueEnabledChkBox->setChecked( false );
00813         }
00814     }
00815 
00816     // Search for name of each string parameter and set it.
00817     foreach (ParamString pString, _paramStrings) {
00818         paramValueStr = "";
00819         // The number of the found values for this parameter name.
00820         int numberOfValues = 0;
00821         index = cfgFileData.indexOf( pString.paramCallName, 0, Qt::CaseInsensitive );
00822         // If parameter was found in config file
00823         if ( index != -1 ) {
00824             while ( index != -1 ) {
00825                 numberOfValues++;
00826 
00827                 // Set index after the parameter name, so it points to the front of the string value.
00828                 index += pString.paramCallName.length();
00829 
00830                 // Find the end of the parameter by searching for set config file parameter ending. Most of time this is a carriage return.
00831                 crPos = cfgFileData.indexOf( _cfgFileParameterEnding, index+1 );
00832 
00833                 // Get the string and remember it.
00834                 if ( numberOfValues < 2 ) {
00835                     paramValueStr = QString( cfgFileData.mid( index, crPos - index ) );
00836                 }
00837                 // If the same parameter has been set multiple times, concatenate the strings dvivided by a |.
00838                 else {
00839                     paramValueStr = paramValueStr + "|" + QString( cfgFileData.mid( index, crPos - index ) );
00840                 }
00841 
00842                 // Get next value for this setting, if one exists.
00843                 index = cfgFileData.indexOf( pString.paramCallName, crPos+1, Qt::CaseInsensitive );
00844             }
00845             // Set the text for the line edit.
00846             pString.lineEdit->setText( paramValueStr );
00847             pString.valueEnabledChkBox->setChecked( true );
00848         }
00849         // Parameter was not found in config file
00850         else {
00851             paramValueStr = _indenterSettings->value(pString.paramName + "/ValueDefault").toString();
00852             pString.lineEdit->setText( paramValueStr );
00853             pString.valueEnabledChkBox->setChecked( false );
00854         }
00855     }
00856 
00857     // search for name of each multiple choice parameter and set it
00858     foreach (ParamMultiple pMultiple, _paramMultiples) {
00859         int i = 0;
00860         index = -1;
00861 
00862         // search for all parameter names of the multiple choice list
00863         // if one is found, set it and leave the while loop
00864         while ( i < pMultiple.choicesStrings.count() && index == -1 ) {
00865             index = cfgFileData.indexOf( pMultiple.choicesStrings.at(i), 0, Qt::CaseInsensitive );
00866             if ( index != -1 ) {
00867                 pMultiple.comboBox->setCurrentIndex( i );
00868                 pMultiple.valueEnabledChkBox->setChecked( true );
00869             }
00870             i++;
00871         }
00872 
00873         // parameter was not set in config file, so use default value
00874         if ( index == -1 ) {
00875             int defaultValue = _indenterSettings->value(pMultiple.paramName + "/ValueDefault").toInt();
00876             pMultiple.comboBox->setCurrentIndex( defaultValue );
00877             pMultiple.valueEnabledChkBox->setChecked( false );
00878         }
00879     }
00880 
00881     return true;
00882 }
00883 
00884 
00888 void IndentHandler::resetToDefaultValues() {
00889     // Search for name of each boolean parameter and set its value if found.
00890     foreach (ParamBoolean pBoolean, _paramBooleans) {
00891         // Boolean value that will be assigned to the checkbox.
00892         bool defaultValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool();
00893         pBoolean.checkBox->setChecked( defaultValue );
00894     }
00895 
00896     // Search for name of each numeric parameter and set the value found behind it.
00897     foreach (ParamNumeric pNumeric, _paramNumerics) {
00898         int defaultValue = _indenterSettings->value(pNumeric.paramName + "/ValueDefault").toInt();
00899         pNumeric.spinBox->setValue( defaultValue );
00900         pNumeric.valueEnabledChkBox->setChecked( _indenterSettings->value(pNumeric.paramName + "/Enabled").toBool() );
00901     }
00902 
00903     // Search for name of each string parameter and set it.
00904     foreach (ParamString pString, _paramStrings) {
00905         QString defaultValue = _indenterSettings->value(pString.paramName + "/ValueDefault").toString();
00906         pString.lineEdit->setText( defaultValue );
00907         pString.valueEnabledChkBox->setChecked( _indenterSettings->value(pString.paramName + "/Enabled").toBool() );
00908     }
00909 
00910     // Search for name of each multiple choice parameter and set it.
00911     foreach (ParamMultiple pMultiple, _paramMultiples) {
00912         int defaultValue = _indenterSettings->value(pMultiple.paramName + "/ValueDefault").toInt();
00913         pMultiple.comboBox->setCurrentIndex( defaultValue );
00914         pMultiple.valueEnabledChkBox->setChecked( _indenterSettings->value(pMultiple.paramName + "/Enabled").toBool() );
00915     }
00916 }
00917 
00918 
00922 void IndentHandler::readIndentIniFile(QString iniFilePath) {
00923     Q_ASSERT_X( !iniFilePath.isEmpty(), "readIndentIniFile", "iniFilePath is empty" );
00924 
00925     // open the ini-file that contains all available indenter settings with their additional infos
00926     _indenterSettings = new UiGuiIniFileParser(iniFilePath);
00927 
00928     QStringList categories;
00929     //QString indenterGroupString = "";
00930     QString paramToolTip = "";
00931 
00932 
00933     //
00934     //  parse ini file indenter header
00935     //
00936 
00937     _indenterName = _indenterSettings->value("header/indenterName").toString();
00938     _indenterFileName = _indenterSettings->value("header/indenterFileName").toString();
00939     _globalConfigFilename = _indenterSettings->value("header/configFilename").toString();
00940     _useCfgFileParameter = _indenterSettings->value("header/useCfgFileParameter").toString();
00941     _cfgFileParameterEnding = _indenterSettings->value("header/cfgFileParameterEnding").toString();
00942     if ( _cfgFileParameterEnding == "cr" ) {
00943         _cfgFileParameterEnding = "\n";
00944     }
00945     _indenterShowHelpParameter = _indenterSettings->value("header/showHelpParameter").toString();
00946 
00947     if ( _indenterFileName.isEmpty() ) {
00948         _errorMessageDialog->showMessage( tr("Indenter ini file header error"),
00949             tr("The loaded indenter ini file \"%1\"has a faulty header. At least the indenters file name is not set.").arg(iniFilePath) );
00950     }
00951 
00952     // Read the parameter order. Possible values are (p=parameter[file] i=inputfile o=outputfile)
00953     // pio, ipo, iop
00954     _parameterOrder = _indenterSettings->value("header/parameterOrder", "pio").toString();
00955     _inputFileParameter = _indenterSettings->value("header/inputFileParameter").toString();
00956     _inputFileName = _indenterSettings->value("header/inputFileName").toString();
00957     _outputFileParameter = _indenterSettings->value("header/outputFileParameter").toString();
00958     _outputFileName = _indenterSettings->value("header/outputFileName").toString();
00959     _fileTypes = _indenterSettings->value("header/fileTypes").toString();
00960     _fileTypes.replace('|', " ");
00961 
00962     // read the categories names which are separated by "|"
00963     QString categoriesStr = _indenterSettings->value("header/categories").toString();
00964     categories = categoriesStr.split("|");
00965     // Assure that the category list is never empty. At least contain a "general" section.
00966     if ( categories.isEmpty() ) {
00967         categories.append("General");
00968     }
00969 
00970     IndenterParameterCategoryPage categoryPage;
00971 
00972     // create a page for each category and store its references in a toolboxpage-array
00973     foreach (QString category, categories) {
00974         categoryPage.widget = new QWidget();
00975         categoryPage.widget->setObjectName(category);
00976         categoryPage.widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
00977         categoryPage.vboxLayout = new QVBoxLayout(categoryPage.widget);
00978         categoryPage.vboxLayout->setSpacing(6);
00979         categoryPage.vboxLayout->setMargin(9);
00980         categoryPage.vboxLayout->setObjectName(category);
00981         _indenterParameterCategoryPages.append(categoryPage);
00982         _indenterParameterCategoriesToolBox->addItem(categoryPage.widget, category);
00983     }
00984 
00985 
00986     //
00987     //  parse ini file indenter parameters
00988     //
00989 
00990     // read all possible parameters written in brackets []
00991     _indenterParameters = _indenterSettings->childGroups();
00992 
00993     // read each parameter to create the corresponding input field
00994     foreach (QString indenterParameter, _indenterParameters) {
00995         // if it is not the indent header definition read the parameter and add it to
00996         // the corresponding category toolbox page
00997         if ( indenterParameter != "header") {
00998             // read to which category the parameter belongs
00999             int category = _indenterSettings->value(indenterParameter + "/Category").toInt();
01000             // Assure that the category number is never greater than the available categories.
01001             if ( category > _indenterParameterCategoryPages.size()-1 ) {
01002                 category = _indenterParameterCategoryPages.size()-1;
01003             }
01004             // read which type of input field the parameter needs
01005             QString editType = _indenterSettings->value(indenterParameter + "/EditorType").toString();
01006 
01007             // edit type is numeric so create a spinbox with label
01008             if ( editType == "numeric" ) {
01009                 // read the parameter name as it is used at the command line or in its config file
01010                 QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString();
01011 
01012                 // create checkbox which enables or disables the parameter
01013                 QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget );
01014                 chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() );
01015                 chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." );
01016                 chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
01017                 int left, top, right, bottom;
01018                 chkBox->getContentsMargins( &left, &top, &right, &bottom );
01019                 chkBox->setContentsMargins( left, top, 0, bottom );
01020 
01021                 // create the spinbox
01022                 QSpinBox *spinBox = new QSpinBox( _indenterParameterCategoryPages.at(category).widget );
01023                 paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString();
01024                 spinBox->setToolTip( paramToolTip );
01025                 spinBox->setMaximumWidth(50);
01026                 spinBox->setMinimumWidth(50);
01027                 if ( _mainWindow != NULL ) {
01028                     spinBox->installEventFilter( _mainWindow );
01029                 }
01030                 if ( _indenterSettings->value(indenterParameter + "/MinVal").toString() != "" ) {
01031                     spinBox->setMinimum( _indenterSettings->value(indenterParameter + "/MinVal").toInt() );
01032                 }
01033                 else {
01034                     spinBox->setMinimum( 0 );
01035                 }
01036                 if ( _indenterSettings->value(indenterParameter + "/MaxVal").toString() != "" ) {
01037                     spinBox->setMaximum( _indenterSettings->value(indenterParameter + "/MaxVal").toInt() );
01038                 }
01039                 else {
01040                     spinBox->setMaximum( 2000 );
01041                 }
01042 
01043                 // create the label
01044                 QLabel *label = new QLabel( _indenterParameterCategoryPages.at(category).widget );
01045                 label->setText(indenterParameter);
01046                 label->setBuddy(spinBox);
01047                 label->setToolTip( paramToolTip );
01048                 if ( _mainWindow != NULL ) {
01049                     label->installEventFilter( _mainWindow );
01050                 }
01051 
01052                 // put all into a layout and add it to the toolbox page
01053                 QHBoxLayout *hboxLayout = new QHBoxLayout();
01054                 hboxLayout->addWidget(chkBox);
01055                 hboxLayout->addWidget(spinBox);
01056                 hboxLayout->addWidget(label);
01057                 _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout);
01058 
01059                 // remember parameter name and reference to its spinbox
01060                 ParamNumeric paramNumeric;
01061                 paramNumeric.paramName = indenterParameter;
01062                 paramNumeric.paramCallName = parameterCallName;
01063                 paramNumeric.spinBox = spinBox;
01064                 paramNumeric.label = label;
01065                 paramNumeric.valueEnabledChkBox = chkBox;
01066                 paramNumeric.spinBox->setValue( _indenterSettings->value(paramNumeric.paramName + "/ValueDefault").toInt() );
01067                 _paramNumerics.append(paramNumeric);
01068 
01069                 QObject::connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings()));
01070                 QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings()));
01071 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01072                 connect( spinBox, SIGNAL(valueChanged(int)), this, SLOT(updateDrawing()) );
01073 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01074             }
01075             // edit type is boolean so create a checkbox
01076             else if ( editType == "boolean" ) {
01077                 // create the checkbox, make its settings and add it to the toolbox page
01078                 QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget );
01079                 chkBox->setText(indenterParameter);
01080                 paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString();
01081                 chkBox->setToolTip( paramToolTip );
01082                 if ( _mainWindow != NULL ) {
01083                     chkBox->installEventFilter( _mainWindow );
01084                 }
01085                 _indenterParameterCategoryPages.at(category).vboxLayout->addWidget(chkBox);
01086 
01087                 // remember parameter name and reference to its checkbox
01088                 ParamBoolean paramBoolean;
01089                 paramBoolean.paramName = indenterParameter;
01090                 paramBoolean.checkBox = chkBox;
01091                 QStringList trueFalseStrings = _indenterSettings->value(indenterParameter + "/TrueFalse").toString().split("|");
01092                 paramBoolean.trueString = trueFalseStrings.at(0);
01093                 paramBoolean.falseString = trueFalseStrings.at(1);
01094                 paramBoolean.checkBox->setChecked( _indenterSettings->value(paramBoolean.paramName + "/ValueDefault").toBool() );
01095                 _paramBooleans.append(paramBoolean);
01096 
01097                 QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings()));
01098             }
01099             // edit type is numeric so create a line edit with label
01100             else if ( editType == "string" ) {
01101                 // read the parameter name as it is used at the command line or in its config file
01102                 QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString();
01103 
01104                 // create check box which enables or disables the parameter
01105                 QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget );
01106                 chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() );
01107                 chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." );
01108                 chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
01109                 int left, top, right, bottom;
01110                 chkBox->getContentsMargins( &left, &top, &right, &bottom );
01111                 chkBox->setContentsMargins( left, top, 0, bottom );
01112 
01113                 // create the line edit
01114                 QLineEdit *lineEdit = new QLineEdit( _indenterParameterCategoryPages.at(category).widget );
01115                 paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString();
01116                 lineEdit->setToolTip( paramToolTip );
01117                 lineEdit->setMaximumWidth(50);
01118                 lineEdit->setMinimumWidth(50);
01119                 if ( _mainWindow != NULL ) {
01120                     lineEdit->installEventFilter( _mainWindow );
01121                 }
01122 
01123                 // create the label
01124                 QLabel *label = new QLabel( _indenterParameterCategoryPages.at(category).widget );
01125                 label->setText(indenterParameter);
01126                 label->setBuddy(lineEdit);
01127                 label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
01128                 label->setToolTip( paramToolTip );
01129                 if ( _mainWindow != NULL ) {
01130                     label->installEventFilter( _mainWindow );
01131                 }
01132 
01133                 // put all into a layout and add it to the toolbox page
01134                 QHBoxLayout *hboxLayout = new QHBoxLayout();
01135                 hboxLayout->addWidget(chkBox);
01136                 hboxLayout->addWidget(lineEdit);
01137                 hboxLayout->addWidget(label);
01138                 _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout);
01139 
01140                 // remember parameter name and reference to its line edit
01141                 ParamString paramString;
01142                 paramString.paramName = indenterParameter;
01143                 paramString.paramCallName = parameterCallName;
01144                 paramString.lineEdit = lineEdit;
01145                 paramString.label = label;
01146                 paramString.valueEnabledChkBox = chkBox;
01147                 paramString.lineEdit->setText( _indenterSettings->value(paramString.paramName + "/ValueDefault").toString() );
01148                 _paramStrings.append(paramString);
01149 
01150                 QObject::connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(handleChangedIndenterSettings()));
01151                 QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings()));
01152 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01153                 connect( lineEdit, SIGNAL(textChanged(const QString)), this, SLOT(updateDrawing()) );
01154 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01155             }
01156             // edit type is multiple so create a combobox with label
01157             else if ( editType == "multiple" ) {
01158                 // read the parameter name as it is used at the command line or in its config file
01159                 QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString();
01160 
01161                 // create checkbox which enables or disables the parameter
01162                 QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget );
01163                 chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() );
01164                 chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." );
01165                 chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
01166                 int left, top, right, bottom;
01167                 chkBox->getContentsMargins( &left, &top, &right, &bottom );
01168                 chkBox->setContentsMargins( left, top, 0, bottom );
01169 
01170                 // create the combo box
01171                 QComboBox *comboBox = new QComboBox( _indenterParameterCategoryPages.at(category).widget );
01172                 QStringList choicesStrings = _indenterSettings->value(indenterParameter + "/Choices").toString().split("|");
01173                 QStringList choicesStringsReadable = _indenterSettings->value(indenterParameter + "/ChoicesReadable").toString().split("|", QString::SkipEmptyParts);
01174                 if ( choicesStringsReadable.isEmpty() ) {
01175                     comboBox->addItems( choicesStrings );
01176                 }
01177                 else {
01178                     comboBox->addItems( choicesStringsReadable );
01179                 }
01180                 paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString();
01181                 comboBox->setToolTip( paramToolTip );
01182                 if ( _mainWindow != NULL ) {
01183                     comboBox->installEventFilter( _mainWindow );
01184                 }
01185 
01186                 // put all into a layout and add it to the toolbox page
01187                 QHBoxLayout *hboxLayout = new QHBoxLayout();
01188                 hboxLayout->addWidget(chkBox);
01189                 hboxLayout->addWidget(comboBox);
01190                 _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout);
01191 
01192                 // remember parameter name and reference to its lineedit
01193                 ParamMultiple paramMultiple;
01194                 paramMultiple.paramName = indenterParameter;
01195                 paramMultiple.paramCallName = parameterCallName;
01196                 paramMultiple.comboBox = comboBox;
01197                 paramMultiple.choicesStrings = choicesStrings;
01198                 paramMultiple.choicesStringsReadable = choicesStringsReadable;
01199                 paramMultiple.valueEnabledChkBox = chkBox;
01200                 paramMultiple.comboBox->setCurrentIndex( _indenterSettings->value(paramMultiple.paramName + "/ValueDefault").toInt() );
01201                 _paramMultiples.append(paramMultiple);
01202 
01203                 QObject::connect(comboBox, SIGNAL(activated(int)), this, SLOT(handleChangedIndenterSettings()));
01204                 QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings()));
01205 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01206                 connect( comboBox, SIGNAL(activated(int)), this, SLOT(updateDrawing()) );
01207 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01208             }
01209         }
01210     }
01211 
01212     // put a spacer at each page end
01213     foreach (IndenterParameterCategoryPage categoryPage, _indenterParameterCategoryPages) {
01214         categoryPage.vboxLayout->addStretch();
01215     }
01216 }
01217 
01218 
01225 QStringList IndentHandler::getAvailableIndenters() {
01226     QStringList indenterNamesList;
01227 
01228     // Loop for every existing uigui ini file
01229     foreach (QString indenterIniFile, _indenterIniFileList) {
01230         // Open the ini file and search for the indenter name
01231         QFile file(_indenterDirctoryStr + "/" + indenterIniFile);
01232         if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
01233             int index = -1;
01234             QByteArray line;
01235             // Search for the string "indenterName=" and get the following string until line end.
01236             while ( index == -1 &&  !file.atEnd() ) {
01237                 line = file.readLine();
01238                 index = line.indexOf( "indenterName=", 0);
01239             }
01240 
01241             if ( index == 0 ) {
01242                 line = line.remove(0, 13);
01243                 indenterNamesList << line.trimmed();
01244             }
01245         }
01246     }
01247     return indenterNamesList;
01248 }
01249 
01250 
01254 void IndentHandler::setIndenter(int indenterID) {
01255     QApplication::setOverrideCursor(Qt::WaitCursor);
01256 
01257 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01258     disconnect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) );
01259 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01260 
01261     // Generate the parameter string that will be saved to the indenters config file.
01262     QString parameterString = getParameterString();
01263     if ( !_indenterFileName.isEmpty() ) {
01264         saveConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg", parameterString );
01265     }
01266 
01267     // Take care if the selected indenterID is smaller or greater than the number of existing indenters
01268     if ( indenterID < 0 ) {
01269         indenterID = 0;
01270     }
01271     if ( indenterID >= _indenterIniFileList.count() ) {
01272         indenterID = _indenterIniFileList.count() - 1;
01273     }
01274 
01275     // remove all pages from the toolbox
01276     for (int i = 0; i < _indenterParameterCategoriesToolBox->count(); i++) {
01277         _indenterParameterCategoriesToolBox->removeItem(i);
01278     }
01279 
01280     // delete all toolbox pages and by this its children
01281     foreach (IndenterParameterCategoryPage categoryPage, _indenterParameterCategoryPages) {
01282         delete categoryPage.widget;
01283     }
01284 
01285     // empty all lists, which stored infos for the toolbox pages and its widgets
01286     _indenterParameterCategoryPages.clear();
01287     _paramStrings.clear();
01288     _paramNumerics.clear();
01289     _paramBooleans.clear();
01290     _paramMultiples.clear();
01291     delete _indenterSettings;
01292 
01293 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01294     QWidget dummyWidget;
01295     _indenterParameterCategoriesToolBox->addItem(&dummyWidget, "dummyText");
01296 #endif
01297 
01298     readIndentIniFile( _indenterDirctoryStr + "/" + _indenterIniFileList.at(indenterID) );
01299 
01300     // Find out how the indenter can be executed.
01301     createIndenterCallString();
01302 
01303     // Load the users last settings made for this indenter.
01304     loadConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg" );
01305 
01306     handleChangedIndenterSettings();
01307 
01308     QApplication::restoreOverrideCursor();
01309 
01310 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01311     connect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) );
01312     _indenterParameterCategoriesToolBox->removeItem( _indenterParameterCategoriesToolBox->indexOf(&dummyWidget) );
01313 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01314 }
01315 
01316 
01320 QString IndentHandler::getPossibleIndenterFileExtensions() {
01321     return _fileTypes;
01322 }
01323 
01324 
01328 QString IndentHandler::getIndenterCfgFile() {
01329     QFileInfo fileInfo( _indenterDirctoryStr + "/" + _globalConfigFilename );
01330     return fileInfo.absoluteFilePath();
01331 }
01332 
01333 
01337 bool IndentHandler::createIndenterCallString() {
01338     QProcess indentProcess;
01339 
01340     if ( _indenterFileName.isEmpty() ) {
01341         return false;
01342     }
01343 
01344     // First try to call the indenter inside of the data dir, using some suffix
01345     // ------------------------------------------------------------------------
01346 
01347     // Set the directory for the indenter execution
01348     indentProcess.setWorkingDirectory( QFileInfo(_indenterDirctoryStr).absoluteFilePath() );
01349 
01350     foreach ( QString suffix, QStringList() << "" << ".exe" << ".bat" << ".com" << ".sh" ) {
01351         _indenterExecutableSuffix = suffix;
01352         _indenterExecutableCallString = QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName;
01353         _indenterExecutableCallString += suffix;
01354 
01355         // Only try to call the indenter, if the file exists.
01356         if ( QFile::exists(_indenterExecutableCallString) ) {
01357             // Only try to call the indenter directly if it is no php file
01358             if ( QFileInfo(_indenterExecutableCallString).suffix().toLower() != "php" ) {
01359                 indentProcess.start( "\"" + _indenterExecutableCallString +  + "\" " + _indenterShowHelpParameter );
01360                 if ( indentProcess.waitForFinished(2000) ) {
01361                     _indenterExecutableCallString = "\"" + _indenterExecutableCallString + "\"";
01362                     return true;
01363                 }
01364                 else if ( indentProcess.error() == QProcess::Timedout ) {
01365                     _indenterExecutableCallString = "\"" + _indenterExecutableCallString + "\"";
01366                     return true;
01367                 }
01368             }
01369 
01370             // Test for needed interpreters
01371             // ----------------------------
01372             // If the file could not be executed, try to find a shebang at its start or test if its a php file.
01373             QString interpreterName = "";
01374             QFile indenterExecutable( _indenterExecutableCallString );
01375 
01376             // If indenter executable file has .php as suffix, use php as default interpreter
01377             if ( QFileInfo(_indenterExecutableCallString).suffix().toLower() == "php" ) {
01378                 interpreterName = "php -f";
01379             }
01380             // Else try to open the file and read the shebang.
01381             else if ( indenterExecutable.open(QFile::ReadOnly) ) {
01382                 // Read the first line of the file.
01383                 QTextStream indenterExecutableContent(&indenterExecutable);
01384                 QString firstLineOfIndenterExe = indenterExecutableContent.readLine(75);
01385                 indenterExecutable.close();
01386 
01387                 // If the initial shebang is found, read the named intepreter. e.g. perl
01388                 if ( firstLineOfIndenterExe.startsWith("#!") ) {
01389                     // Get the rightmost word. by splitting the string into only full words.
01390                     interpreterName = firstLineOfIndenterExe.split( "/" ).last();
01391                 }
01392             }
01393 
01394             // Try to call the interpreter, if it exists.
01395             if ( !interpreterName.isEmpty() ) {
01396                 _indenterExecutableCallString = interpreterName + " \"" + _indenterExecutableCallString + "\"";
01397                 indentProcess.start( interpreterName + " -h");
01398                 if ( indentProcess.waitForFinished(2000) ) {
01399                     return true;
01400                 }
01401                 else if ( indentProcess.error() == QProcess::Timedout ) {
01402                     return true;
01403                 }
01404                 // now we know an interpreter is needed but it could not be called, so inform the user.
01405                 else {
01406                     _errorMessageDialog->showMessage( tr("Interpreter needed"),
01407                         tr("To use the selected indenter the program \"%1\" needs to be available in the global environment. You should add an entry to your path settings.").arg(interpreterName) );
01408                     return true;
01409                 }
01410             }
01411         }
01412     }
01413 
01414 
01415     // If unsuccessful try if the indenter executable is a JavaScript file
01416     // -------------------------------------------------------------------
01417     _indenterExecutableSuffix = ".js";
01418     _indenterExecutableCallString = QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName;
01419     _indenterExecutableCallString += _indenterExecutableSuffix;
01420     if ( QFile::exists(_indenterExecutableCallString) ) {
01421         return true;
01422     }
01423 
01424 
01425     // If unsuccessful try to call the indenter global, using some suffix
01426     // ------------------------------------------------------------------
01427     foreach ( QString suffix, QStringList() << "" << ".exe" << ".bat" << ".com" << ".sh" ) {
01428         _indenterExecutableSuffix = suffix;
01429         _indenterExecutableCallString = _indenterFileName + suffix;
01430         indentProcess.start( _indenterExecutableCallString + " " + _indenterShowHelpParameter );
01431         if ( indentProcess.waitForFinished(2000) ) {
01432             return true;
01433         }
01434         else if ( indentProcess.error() == QProcess::Timedout ) {
01435             return true;
01436         }
01437     }
01438 
01439 
01440     // If even globally calling the indenter fails, try calling .com and .exe via wine
01441     // -------------------------------------------------------------------------------
01442     _indenterExecutableCallString = "\"" + QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName;
01443 
01444     foreach ( QString suffix, QStringList() << ".exe" << ".com" ) {
01445         _indenterExecutableSuffix = suffix;
01446         if ( QFile::exists(_indenterDirctoryStr + "/" + _indenterFileName + suffix) ) {
01447             QProcess wineTestProcess;
01448             wineTestProcess.start("wine --version");
01449             // if the process of wine was not callable assume that wine is not installed
01450             if ( !wineTestProcess.waitForFinished(2000) ) {
01451                 _errorMessageDialog->showMessage(tr("wine not installed"), tr("There exists only a win32 executable of the indenter and wine does not seem to be installed. Please install wine to be able to run the indenter.") );
01452                 _indenterExecutableCallString = "";
01453                 return false;
01454             }
01455             else {
01456                 _indenterExecutableCallString = "\"" + QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/";
01457                 _indenterExecutableCallString += _indenterFileName + suffix + "\"";
01458                 _indenterExecutableCallString = "wine " + _indenterExecutableCallString;
01459 
01460                 return true;
01461             }
01462         }
01463     }
01464 
01465     _indenterExecutableCallString = "";
01466     _indenterExecutableSuffix = "";
01467     return false;
01468 }
01469 
01470 
01474 QString IndentHandler::getManual() {
01475     if ( _indenterSettings != NULL ) {
01476         return _indenterSettings->value("header/manual").toString();
01477     }
01478     else {
01479         return "";
01480     }
01481 }
01482 
01483 
01487 void IndentHandler::showIndenterManual() {
01488     QString manualReference = getManual();
01489     QDesktopServices::openUrl( manualReference );
01490 }
01491 
01492 
01496 void IndentHandler::retranslateUi() {
01497     _indenterSelectionCombobox->setToolTip( tr("<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\" white-space: pre-wrap; font-family:MS Shell Dlg; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;\"><p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Shows the currently chosen indenters name and lets you choose other available indenters</p></body></html>") );
01498     _indenterParameterHelpButton->setToolTip( tr("Brings you to the online manual of the currently selected indenter, where you can get further help on the possible parameters.") );
01499 
01500     _actionLoadIndenterConfigFile->setText(QApplication::translate("IndentHandler", "Load Indenter Config File", 0, QApplication::UnicodeUTF8));
01501     _actionLoadIndenterConfigFile->setStatusTip(QApplication::translate("IndentHandler", "Opens a file dialog to load the original config file of the indenter.", 0, QApplication::UnicodeUTF8));
01502     _actionLoadIndenterConfigFile->setShortcut(QApplication::translate("IndentHandler", "Alt+O", 0, QApplication::UnicodeUTF8));
01503 
01504     _actionSaveIndenterConfigFile->setText(QApplication::translate("IndentHandler", "Save Indenter Config File", 0, QApplication::UnicodeUTF8));
01505     _actionSaveIndenterConfigFile->setStatusTip(QApplication::translate("IndentHandler", "Opens a dialog to save the current indenter configuration to a file.", 0, QApplication::UnicodeUTF8));
01506     _actionSaveIndenterConfigFile->setShortcut(QApplication::translate("IndentHandler", "Alt+S", 0, QApplication::UnicodeUTF8));
01507 
01508     _actionCreateShellScript->setText(QApplication::translate("IndentHandler", "Create Indenter Call Shell Script", 0, QApplication::UnicodeUTF8));
01509     _actionCreateShellScript->setToolTip(QApplication::translate("IndentHandler", "Create a shell script that calls the current selected indenter for formatting an as parameter given file with the current indent settings.", 0, QApplication::UnicodeUTF8));
01510     _actionCreateShellScript->setStatusTip(QApplication::translate("IndentHandler", "Create a shell script that calls the current selected indenter for formatting an as parameter given file with the current indent settings.", 0, QApplication::UnicodeUTF8));
01511 
01512     _actionResetIndenterParameters->setText(QApplication::translate("IndentHandler", "Reset indenter parameters", 0, QApplication::UnicodeUTF8));
01513     _actionResetIndenterParameters->setToolTip(QApplication::translate("IndentHandler", "Resets all indenter parameters to the default values.", 0, QApplication::UnicodeUTF8));
01514     _actionResetIndenterParameters->setStatusTip(QApplication::translate("IndentHandler", "Resets all indenter parameters to the default values.", 0, QApplication::UnicodeUTF8));
01515 }
01516 
01517 
01521 QString IndentHandler::getCurrentIndenterName() {
01522     QString currentIndenterName = _indenterSelectionCombobox->currentText();
01523 
01524     // Remove the supported programming languages from indenters name, which are set in braces.
01525     if ( currentIndenterName.indexOf("(") > 0 ) {
01526         // Using index-1 to also leave out the blank before the brace.
01527         currentIndenterName = currentIndenterName.left( currentIndenterName.indexOf("(")-1 );
01528     }
01529 
01530     return currentIndenterName;
01531 }
01532 
01533 
01539 void IndentHandler::openConfigFileDialog() {
01540     QString configFilePath;
01541 
01542     configFilePath = QFileDialog::getOpenFileName( NULL, tr("Choose indenter config file"), getIndenterCfgFile(), "All files (*.*)" );
01543 
01544     if (configFilePath != "") {
01545         // If the config file was loaded successfully, inform any who is interested about it.
01546         if ( loadConfigFile(configFilePath) )
01547             handleChangedIndenterSettings();
01548     }
01549 }
01550 
01551 
01557 void IndentHandler::saveasIndentCfgFileDialog() {
01558     QString fileExtensions = tr("All files")+" (*.*)";
01559 
01560     //QString openedSourceFileContent = openFileDialog( tr("Choose source code file"), "./", fileExtensions );
01561     QString fileName = QFileDialog::getSaveFileName( this, tr("Save indent config file"), getIndenterCfgFile(), fileExtensions);
01562 
01563     if (fileName != "") {
01564         QFile::remove(fileName);
01565         QFile outCfgFile(fileName);
01566         outCfgFile.open( QFile::ReadWrite | QFile::Text );
01567         outCfgFile.write( getParameterString().toAscii() );
01568         outCfgFile.close();
01569     }
01570 }
01571 
01572 
01579 void IndentHandler::createIndenterCallShellScript() {
01580     QString shellScriptExtension;
01581 #if defined(Q_OS_WIN32)
01582     shellScriptExtension = "bat";
01583 #else
01584     shellScriptExtension = "sh";
01585 #endif
01586 
01587     QString fileExtensions = tr("Shell Script")+" (*."+shellScriptExtension+");;"+tr("All files")+" (*.*)";
01588 
01589     QString currentIndenterName = getCurrentIndenterName();
01590     currentIndenterName = currentIndenterName.replace(" ", "_");
01591 
01592     QString shellScriptFileName = QFileDialog::getSaveFileName( this, tr("Save shell script"), "call_"+currentIndenterName+"."+shellScriptExtension, fileExtensions);
01593 
01594     // Saving has been canceled if the filename is empty
01595     if ( shellScriptFileName.isEmpty() ) {
01596         return;
01597     }
01598 
01599     // Delete any old file, write the new contents and set executable permissions.
01600     QFile::remove(shellScriptFileName);
01601     QFile outSrcFile(shellScriptFileName);
01602     if ( outSrcFile.open( QFile::ReadWrite | QFile::Text ) ) {
01603         QString shellScriptConfigFilename = QFileInfo(shellScriptFileName).baseName() + "." + QFileInfo(_globalConfigFilename).suffix();
01604 
01605         // Get the content of the shell/batch script.
01606         QString indenterCallShellScript = generateShellScript(shellScriptConfigFilename);
01607 
01608         // Replace placeholder for script name in script template.
01609         indenterCallShellScript = indenterCallShellScript.replace( "__INDENTERCALLSTRINGSCRIPTNAME__", QFileInfo(shellScriptFileName).fileName() );
01610 
01611         outSrcFile.write( indenterCallShellScript.toAscii() );
01612 #if !defined(Q_OS_WIN32)
01613         // For none Windows systems set the files executable flag
01614         outSrcFile.setPermissions( outSrcFile.permissions() | QFile::ExeOwner | QFile::ExeUser| QFile::ExeGroup );
01615 #endif
01616         outSrcFile.close();
01617 
01618         // Save the indenter config file to the same directory, where the shell srcipt was saved to,
01619         // because the script will reference it there via "./".
01620         if ( !_globalConfigFilename.isEmpty() ) {
01621             saveConfigFile( QFileInfo(shellScriptFileName).path() + "/" + shellScriptConfigFilename, getParameterString() );
01622         }
01623     }
01624 }
01625 
01626 
01631 void IndentHandler::resetIndenterParameter() {
01632     int messageBoxAnswer = QMessageBox::question(this, tr("Really reset parameters?"), tr("Do you really want to reset the indenter parameters to the default values?"), QMessageBox::Yes | QMessageBox::Abort );
01633     if ( messageBoxAnswer == QMessageBox::Yes ) {
01634         resetToDefaultValues();
01635     }
01636 }
01637 
01638 
01644 bool IndentHandler::event( QEvent *event ) {
01645     if ( event->type() == QEvent::WindowActivate ) {
01646         event->accept();
01647         return true;
01648     }
01649     else if ( event->type() == QEvent::WindowDeactivate ) {
01650         event->accept();
01651         return true;
01652     }
01653     else {
01654         event->ignore();
01655         return QWidget::event(event);
01656     }
01657 }
01658 
01659 
01666 void IndentHandler::setParameterChangedCallback( void(*paramChangedCallback)(void) ) {
01667     _parameterChangedCallback = paramChangedCallback;
01668 }
01669 
01670 
01676 void IndentHandler::handleChangedIndenterSettings() {
01677     emit( indenterSettingsChanged() );
01678 
01679     if ( _parameterChangedCallback != NULL ) {
01680         _parameterChangedCallback();
01681     }
01682 }
01683 
01684 
01690 void IndentHandler::setWindowClosedCallback( void(*winClosedCallback)(void) ) {
01691     _windowClosedCallback = winClosedCallback;
01692 }
01693 
01694 
01700 void IndentHandler::closeEvent(QCloseEvent *event) {
01701     if ( _windowClosedCallback != NULL ) {
01702         _windowClosedCallback();
01703     }
01704     event->accept();
01705 }
01706 
01707 
01711 int IndentHandler::getIndenterId() {
01712     return _indenterSelectionCombobox->currentIndex();
01713 }
01714 
01715 
01716 void IndentHandler::updateDrawing() {
01717 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01718     if ( isVisible() ) {
01719         QRect savedGeometry = geometry();
01720         setGeometry( savedGeometry.adjusted(0,0,0,1) );
01721         repaint();
01722         setGeometry( savedGeometry );
01723     }
01724 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01725 }
01726 
01727 void IndentHandler::wheelEvent( QWheelEvent *event ) {
01728     UNUSED_PARAMETER_WARNING_AVOID(event);
01729 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
01730     QWidget::wheelEvent( event );
01731     updateDrawing();
01732 #endif // UNIVERSALINDENTGUI_NPP_EXPORTS
01733 }
01734 
01735 
01739 //TODO: This function should go into a string helper/tool class/file.
01740 QString IndentHandler::encodeToHTML(const QString &text) {
01741     QString htmlText = text;
01742     htmlText.replace("&", "&amp;");
01743     htmlText.replace("<", "&lt;");
01744     htmlText.replace(">", "&gt;");
01745     htmlText.replace('"', "&quot;");
01746     htmlText.replace("'", "&#39;");
01747     htmlText.replace("^", "&circ;");
01748     htmlText.replace("~", "&tilde;");
01749     htmlText.replace("€", "&euro;");
01750     htmlText.replace("©", "&copy;");
01751     return htmlText;
01752 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines