UniversalIndentGUI 1.2.0
|
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("&", "&"); 01743 htmlText.replace("<", "<"); 01744 htmlText.replace(">", ">"); 01745 htmlText.replace('"', """); 01746 htmlText.replace("'", "'"); 01747 htmlText.replace("^", "ˆ"); 01748 htmlText.replace("~", "˜"); 01749 htmlText.replace("€", "€"); 01750 htmlText.replace("©", "©"); 01751 return htmlText; 01752 }