diff options
Diffstat (limited to 'src')
126 files changed, 23946 insertions, 0 deletions
diff --git a/src/AboutDialog.cpp b/src/AboutDialog.cpp new file mode 100755 index 0000000..aa4953a --- /dev/null +++ b/src/AboutDialog.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "AboutDialog.h" +#include "ui_AboutDialog.h" + +#include "UiGuiVersion.h" + +#include <QUrl> +#include <QDesktopServices> +#include <QScrollBar> +#include <QTimer> +#include <QLocale> + +/*! + \class AboutDialog + \brief Displays a dialog window with information about UniversalIndentGUI +*/ + +/*! + \brief The constructor calls the setup function for the ui created by uic and adds + the GPL text to the text edit. + */ +AboutDialog::AboutDialog(QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags) + , _dialogForm(NULL) + , _timer(NULL) + { + _dialogForm = new Ui::AboutDialog(); + _dialogForm->setupUi(this); + + _dialogForm->authorTextBrowser->setOpenExternalLinks( true ); + _dialogForm->creditsTextBrowser->setOpenExternalLinks( true ); + + QString versionString = _dialogForm->versionTextBrowser->toHtml(); + versionString = versionString.arg(PROGRAM_VERSION_STRING).arg( UiGuiVersion::getBuildRevision() ).arg( UiGuiVersion::getBuildDate() ); + _dialogForm->versionTextBrowser->setHtml(versionString); + + _dialogForm->creditsTextBrowser->setHtml("<html><head></head><body>" + "<pre> </br></pre>" + "<h3 align='center'>Thanks go out to</h3>" + "<p align='center'><a href=\"http://www.csie.nctu.edu.tw/~chtai/\"><b>Nelson Tai</b></a> for Chinese translation, good ideas and always fast answers.</p></br>" + "<p align='center'><a href=\"http://www.hartwork.org/\"><b>Sebastian Pipping</b></a> for helping me bring UiGUI into the Debian repository and other good ideas.</p></br>" + "<p align='center'><a href=\"http://korytskyy.lviv.ua/\"><b>Oleksandr</b></a> for Ukrainian and Russian translation.</p></br>" + "<p align='center'><b>Erwan "leg"</b> for French translation and the icon logo.</p></br>" + "<p align='center'>The <a href=\"http://www.scintilla.org/\"><b>Scintilla</b></a> project for their great text editing component.</p></br>" + "<p align='center'><a href=\"http://www.riverbankcomputing.co.uk/software/qscintilla/\"><b>Riverbank</b></a> for their Scintilla Qt wrapper QScintilla.</p></br>" + "<p align='center'>The <a href=\"http://astyle.sourceforge.net/\"><b>Artistic Style</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://invisible-island.net/bcpp/\"><b>BCPP</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.siber.com/sct/tools/cbl-beau.html\"><b>Cobol Beautifier</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://csstidy.sourceforge.net/\"><b>CSSTidy</b></a> project.</p></br>" + "<p align='center'>The <a href=\"ftp://ftp.ifremer.fr/ifremer/ditigo/fortran90/\"><b>Fortran 90 PPR</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.gnu.org/software/indent/\"><b>GNU Indent</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://sourceforge.net/projects/gcgreatcode/\"><b>GreatCode</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://linux.com.hk/penguin/man/1/hindent.html\"><b>hindent</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.digital-mines.com/htb/\"><b>HTB</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://tidy.sourceforge.net/\"><b>HTML Tidy</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://code.gosu.pl/\"><b>JsDecoder</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://jsppp.sourceforge.net/\"><b>JSPPP</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://perltidy.sourceforge.net/\"><b>Perltidy</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://beautifyphp.sourceforge.net/\"><b>PHP_Beautifier</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.waterproof.fr/products/phpCodeBeautifier/\"><b>phpCB</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://sourceforge.net/projects/phpstylist/\"><b>PHP Stylist</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://coverage.livinglogic.de/Tools/scripts/pindent.py.html\"><b>pindent</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://psti.equinoxbase.com/\"><b>Pl/Sql tidy</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.arachnoid.com/ruby/rubyBeautifier.html\"><b>Ruby Beautifier</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://raa.ruby-lang.org/project/ruby_formatter/\"><b>Ruby Formatter</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://www.bolthole.com/AWK.html\"><b>Shell Indent</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://uncrustify.sourceforge.net/\"><b>Uncrustify</b></a> project, specially <b>Ben Gardner</b>.</p></br>" + "<p align='center'>The <a href=\"http://www.daansystems.com/vbsbeaut/\"><b>VBSBeautifier</b></a> project.</p></br>" + "<p align='center'>The <a href=\"http://xmlindent.sourceforge.net/\"><b>XML Indent</b></a> project.</p></br>" + "<p align='center'><b>Nirvash</b> for the initial Japanese translation.</p></br>" + "<p align='center'>The <a href=\"http://tango.freedesktop.org/Tango_Desktop_Project/\"><b>Tango Project</b></a> for their icons.</p></br>" + "<p align='center'><a href=\"http://www.famfamfam.com/\"><b>famfamfam</b></a> for the flag icons.</p></br>" + "<p align='center'><a href=\"http://trolltech.com/\"><b>Trolltech</b></a> for their really great GUI framework <img src=\":/aboutDialog/qt_logo.png\"/>.</p></br>" + "<h3 align='center'>My girlfriend (meanwhile also wife) for putting my head right and not sit all the time in front of my computer ;-)</h3>" + "</body></html>"); + + _scrollDirection = 1; + _scrollSpeed = 100; + _timer = new QTimer(this); + connect( _timer, SIGNAL(timeout()), this, SLOT(scroll()) ); + connect( this, SIGNAL(accepted()), _timer, SLOT(stop()) ); +} + + +/*! + \brief Catches language change events and retranslates all needed widgets. + */ +void AboutDialog::changeEvent(QEvent *event) { + if (event->type() == QEvent::LanguageChange) { + _dialogForm->retranslateUi(this); + + QString versionString = _dialogForm->versionTextBrowser->toHtml(); + versionString = versionString.arg(PROGRAM_VERSION_STRING).arg( UiGuiVersion::getBuildRevision() ).arg( UiGuiVersion::getBuildDate() ); + _dialogForm->versionTextBrowser->setHtml(versionString); + } + else { + QWidget::changeEvent(event); + } +} + + +/*! + \brief Reimplements the dialog execution function to init the credits scroller. + */ +int AboutDialog::exec() { + //creditsTextBrowser->verticalScrollBar()->setValue(0); + _timer->start(_scrollSpeed); + return QDialog::exec(); +} + + +/*! + \brief This slot is called each _timer timeout to scroll the credits textbrowser. + Also changes the scroll direction and speed when reaching the start or end. + */ +void AboutDialog::scroll() { + QScrollBar *scrollBar = _dialogForm->creditsTextBrowser->verticalScrollBar(); + scrollBar->setValue( scrollBar->value()+_scrollDirection ); + + if ( scrollBar->value() == scrollBar->maximum() ) { + // Toggle scroll direction and change scroll speed; + _scrollDirection = -1; + _scrollSpeed = 5; + _timer->stop(); + _timer->start(_scrollSpeed); + } + else if ( scrollBar->value() == scrollBar->minimum() ) { + // Toggle scroll direction and change scroll speed; + _scrollDirection = 1; + _scrollSpeed = 100; + _timer->stop(); + _timer->start(_scrollSpeed); + } + + _dialogForm->creditsTextBrowser->update(); +} + + +/*! + \brief Shows the about dialog and also starts the credits scroller. + */ +void AboutDialog::show() { + _timer->start(_scrollSpeed); + QDialog::show(); +} diff --git a/src/AboutDialog.h b/src/AboutDialog.h new file mode 100755 index 0000000..f713d71 --- /dev/null +++ b/src/AboutDialog.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include <QDialog> + +namespace Ui { + class AboutDialog; +} + + +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + AboutDialog(QWidget *parent = NULL, Qt::WindowFlags flags = 0); + +public slots: + int exec(); + void show(); + +private slots: + void scroll(); + +private: + void changeEvent(QEvent *event); + + Ui::AboutDialog* _dialogForm; + int _scrollDirection; + int _scrollSpeed; + QTimer *_timer; +}; + +#endif // ABOUTDIALOG_H diff --git a/src/AboutDialog.ui b/src/AboutDialog.ui new file mode 100755 index 0000000..0e1e9d7 --- /dev/null +++ b/src/AboutDialog.ui @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AboutDialog</class> + <widget class="QDialog" name="AboutDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>588</width> + <height>512</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>588</width> + <height>333</height> + </size> + </property> + <property name="windowTitle"> + <string>About UniversalIndentGUI</string> + </property> + <property name="windowIcon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/info.png</normaloff>:/mainWindow/info.png</iconset> + </property> + <layout class="QVBoxLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="frame"> + <property name="styleSheet"> + <string notr="true">QFrame#frame { background-color: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #FFFF60, stop:0.5 #D8C304, stop:1 #FFFF60 ); border: 2px solid #A89C57; border-radius: 4px;}</string> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="bannerLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>570</width> + <height>87</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>570</width> + <height>87</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../resources/Icons.qrc">:/aboutDialog/banner.png</pixmap> + </property> + </widget> + </item> + <item> + <widget class="QTextBrowser" name="versionTextBrowser"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>25</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">QTextBrowser{background-color:transparent}</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="html"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'sans-serif'; font-size:large;">Version %1 rev.%2, %3</span></p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QTextBrowser" name="authorTextBrowser"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="styleSheet"> + <string notr="true">QTextBrowser{background-color:transparent}</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="html"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;">... is a cross platform compatible GUI for several code formatter, beautifier and indenter like GreatCode, AStyle (Artistic Styler), GNU Indent, BCPP and so on. Main feature is a live preview to directly see how the selected formatting option affects the source code.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;"><br />Written by : </span><a href="http://www.thomas-schweitzer.de"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium; text-decoration: underline; color:#0000ff;">Thomas Schweitzer</span></a></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;">Project Homepage : </span><a href="http://universalindent.sourceforge.net"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium; text-decoration: underline; color:#0000ff;">http://universalindent.sourceforge.net</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;">License: UniversalIndentGui is released under the GPL 2. For details read the included file LICENSE.GPL visit </span><a href="http://www.gnu.org/licenses/gpl.html"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium; text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;">.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Trebuchet MS,Helvetica,sans-serif'; font-size:medium;">Credits:</span></p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QTextBrowser" name="creditsTextBrowser"> + <property name="styleSheet"> + <string notr="true">QTextBrowser#creditsTextBrowser{border:2px solid rgba(0,0,0,10%); background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0,0,0,80%), stop:0.1 rgba(0,0,0,15%), stop:0.9 rgba(0,0,0,15%), stop:1 rgba(0,0,0,80%) )}</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>131</width> + <height>31</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="okButton"> + <property name="styleSheet"> + <string notr="true">QPushButton#okButton { background-color: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #DCB28A, stop:0.5 #B8784B, stop:1 #DCB28A ); border: 2px solid #A89C57; border-radius: 4px;} QPushButton:hover#okButton { background-color: qlineargradient( x1:0, y1:0, x2:0, y2:1, stop:0 #B8784B, stop:0.5 #DCB28A, stop:1 #B8784B ); } QPushButton:pressed#okButton{ border: 2px solid #D8CB75 }</string> + </property> + <property name="text"> + <string> OK </string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections> + <connection> + <sender>okButton</sender> + <signal>clicked()</signal> + <receiver>AboutDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>278</x> + <y>253</y> + </hint> + <hint type="destinationlabel"> + <x>96</x> + <y>254</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/AboutDialogGraphicsView.cpp b/src/AboutDialogGraphicsView.cpp new file mode 100755 index 0000000..d97cc70 --- /dev/null +++ b/src/AboutDialogGraphicsView.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** +* Copyright (C) 2006-2012 by Thomas Schweitzer * +* thomas-schweitzer(at)arcor.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License version 2.0 as * +* published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program in the file LICENSE.GPL; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "AboutDialogGraphicsView.h" + +#include "AboutDialog.h" + +#include <QtGui> +#include <QDesktopWidget> +#include <QDate> +#include <QTimeLine> +#include <QSplashScreen> + +/*! + \class AboutDialogGraphicsView + \brief A container for the real \a AboutDialog. Makes the 3D animation possible. + + The 3D animation shall suggest the user, that he is looking at his desktop, while + this animation is done. Since this is not directly possible, \a AboutDialogGraphicsView + when shown starts in frameless fullscreen mode with a screenshot of the desktop as background. +*/ + +/*! + \brief The constructor initializes everything needed for the 3D animation. + */ +AboutDialogGraphicsView::AboutDialogGraphicsView(AboutDialog *aboutDialog, QWidget *parentWindow) : QGraphicsView(parentWindow) + , _aboutDialog(NULL) + , _graphicsProxyWidget(NULL) + , _parentWindow(NULL) + , _timeLine(NULL) + , _aboutDialogAsSplashScreen(NULL) +{ + _parentWindow = parentWindow; + setWindowFlags(Qt::SplashScreen); + +#ifdef Q_OS_LINUX + QRect availableGeometry = QApplication::desktop()->availableGeometry(); + QRect newGeometry = QRect( availableGeometry.x(), availableGeometry.y(), availableGeometry.width(), availableGeometry.height() ); +#else + QRect newGeometry = QRect( -1,-1, QApplication::desktop()->rect().width()+2, QApplication::desktop()->rect().height()+2 ); +#endif + setGeometry( newGeometry ); + + _aboutDialog = aboutDialog; + + _windowTitleBarWidth = 0; + _windowPosOffset = 0; + + QGraphicsScene *scene = new QGraphicsScene(this); + setSceneRect( newGeometry ); + _aboutDialogAsSplashScreen = new QSplashScreen(this); + _graphicsProxyWidget = scene->addWidget(_aboutDialogAsSplashScreen); + _graphicsProxyWidget->setWindowFlags( Qt::ToolTip ); + + setScene( scene ); + setRenderHint(QPainter::Antialiasing); + + setCacheMode(QGraphicsView::CacheBackground); + setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + + connect(_aboutDialog, SIGNAL(finished(int)), this, SLOT(hide())); + + //setWindowOpacity(0.9); + + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setStyleSheet("AboutDialogGraphicsView { border: 0px; }"); + + _timeLine = new QTimeLine(1000, this); + _timeLine->setFrameRange(270, 0); + //_timeLine->setUpdateInterval(10); + //_timeLine->setCurveShape(QTimeLine::EaseInCurve); + connect(_timeLine, SIGNAL(frameChanged(int)), this, SLOT(updateStep(int))); +} + + +AboutDialogGraphicsView::~AboutDialogGraphicsView(void) { +} + + +/*! + \brief Grabs a screenshot of the full desktop and shows that as background. Above that background the + AboutDialog 3D animation is shown. Also grabs the content of the AboutDialog itself. + */ +void AboutDialogGraphicsView::show() { + // Because on X11 system the window decoration is only available after a widget has been shown once, + // we can detect _windowTitleBarWidth here for the first time. + _windowTitleBarWidth = _parentWindow->geometry().y() - _parentWindow->y(); + // If the _windowTitleBarWidth could not be determined, try it a second way. Even the chances are low to get good results. + if ( _windowTitleBarWidth == 0 ) + _windowTitleBarWidth = _parentWindow->frameGeometry().height() - _parentWindow->geometry().height(); +#ifdef Q_OS_LINUX + if ( _windowTitleBarWidth == 0 ) { + //TODO: 27 pixel is a fix value for the Ubuntu 10.4 default window theme and so just a workaround for that specific case. + _windowPosOffset = 27; + _windowTitleBarWidth = 27; + } +#endif + QPixmap originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), QApplication::desktop()->availableGeometry().x(), QApplication::desktop()->availableGeometry().y(), geometry().width(), geometry().height() ); + QBrush brush(originalPixmap); + QTransform transform; + transform.translate(0, QApplication::desktop()->availableGeometry().y()); + brush.setTransform(transform); + + setBackgroundBrush(brush); + + _aboutDialogAsSplashScreen->setPixmap( QPixmap::grabWidget(_aboutDialog) ); + _graphicsProxyWidget->setGeometry( _aboutDialog->geometry() ); + _aboutDialog->hide(); + _graphicsProxyWidget->setPos( _parentWindow->geometry().x()+(_parentWindow->geometry().width()-_graphicsProxyWidget->geometry().width()) / 2, _parentWindow->y()+_windowTitleBarWidth-_windowPosOffset); + + QRectF r = _graphicsProxyWidget->boundingRect(); + _graphicsProxyWidget->setTransform(QTransform() + .translate(r.width() / 2, -_windowTitleBarWidth) + .rotate(270, Qt::XAxis) + //.rotate(90, Qt::YAxis) + //.rotate(5, Qt::ZAxis) + //.scale(1 + 1.5 * step, 1 + 1.5 * step) + .translate(-r.width() / 2, _windowTitleBarWidth)); + + _graphicsProxyWidget->show(); + //_aboutDialogAsSplashScreen->show(); + QGraphicsView::show(); + + connect(_timeLine, SIGNAL(finished()), this, SLOT(showAboutDialog())); + _timeLine->setDirection(QTimeLine::Forward); + _timeLine->start(); +} + + +/*! + \brief Does the next calculation/transformation step. + */ +void AboutDialogGraphicsView::updateStep(int step) { + QRectF r = _graphicsProxyWidget->boundingRect(); + _graphicsProxyWidget->setTransform(QTransform() + .translate(r.width() / 2, -_windowTitleBarWidth) + .rotate(step, Qt::XAxis) + //.rotate(step, Qt::YAxis) + //.rotate(step * 5, Qt::ZAxis) + //.scale(1 + 1.5 * step, 1 + 1.5 * step) + .translate(-r.width() / 2, _windowTitleBarWidth)); + //update(); +} + + +/*! + \brief Stops the 3D animation, moves the AboutDialog to the correct place and really shows it. + */ +void AboutDialogGraphicsView::showAboutDialog() { + //hide(); + disconnect(_timeLine, SIGNAL(finished()), this, SLOT(showAboutDialog())); + _aboutDialog->move( int(_parentWindow->geometry().x()+(_parentWindow->geometry().width()-_graphicsProxyWidget->geometry().width()) / 2), _parentWindow->y()+_windowTitleBarWidth-_windowPosOffset ); + _aboutDialog->exec(); +} + + +/*! + \brief Does not directly hide the AboutDialog but instead starts the "fade out" 3D animation. + */ +void AboutDialogGraphicsView::hide() { + _graphicsProxyWidget->setPos( _parentWindow->geometry().x()+(_parentWindow->geometry().width()-_graphicsProxyWidget->geometry().width()) / 2, _parentWindow->y()+_windowTitleBarWidth-_windowPosOffset); + + QRectF r = _graphicsProxyWidget->boundingRect(); + _graphicsProxyWidget->setTransform(QTransform() + .translate(r.width() / 2, -_windowTitleBarWidth) + .rotate(0, Qt::XAxis) + //.rotate(90, Qt::YAxis) + //.rotate(5, Qt::ZAxis) + //.scale(1 + 1.5 * step, 1 + 1.5 * step) + .translate(-r.width() / 2, _windowTitleBarWidth)); + + _graphicsProxyWidget->show(); + //_aboutDialogAsSplashScreen->show(); + QGraphicsView::show(); + + connect(_timeLine, SIGNAL(finished()), this, SLOT(hideReally())); + _timeLine->setDirection(QTimeLine::Backward); + _timeLine->start(); +} + + +/*! + \brief This slot really hides this AboutDialog container. + */ +void AboutDialogGraphicsView::hideReally() { + disconnect(_timeLine, SIGNAL(finished()), this, SLOT(hideReally())); + QGraphicsView::hide(); + _parentWindow->activateWindow(); +} diff --git a/src/AboutDialogGraphicsView.h b/src/AboutDialogGraphicsView.h new file mode 100755 index 0000000..ba22c0e --- /dev/null +++ b/src/AboutDialogGraphicsView.h @@ -0,0 +1,56 @@ +/*************************************************************************** +* Copyright (C) 2006-2012 by Thomas Schweitzer * +* thomas-schweitzer(at)arcor.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License version 2.0 as * +* published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program in the file LICENSE.GPL; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#ifndef ABOUTDIALOGGRAPHICSVIEW_H +#define ABOUTDIALOGGRAPHICSVIEW_H + +#include <QGraphicsView> + +class AboutDialog; + +class QTimeLine; +class QSplashScreen; + + +class AboutDialogGraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + AboutDialogGraphicsView(AboutDialog *aboutDialog, QWidget *parentWindow = NULL); + ~AboutDialogGraphicsView(void); + +public slots: + void show(); + void hide(); + +private slots: + void updateStep(int step); + void showAboutDialog(); + void hideReally(); + +private: + AboutDialog *_aboutDialog; + QGraphicsProxyWidget *_graphicsProxyWidget; + QWidget *_parentWindow; + QTimeLine *_timeLine; + QSplashScreen *_aboutDialogAsSplashScreen; + int _windowTitleBarWidth; + int _windowPosOffset; +}; + +#endif // ABOUTDIALOGGRAPHICSVIEW_H diff --git a/src/FindDialog.ui b/src/FindDialog.ui new file mode 100755 index 0000000..943f5a5 --- /dev/null +++ b/src/FindDialog.ui @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FindDialog</class>
+ <widget class="QDialog" name="FindDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>227</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Find</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Find what:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBox">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Find options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="checkBox">
+ <property name="text">
+ <string>Match case</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBox_2">
+ <property name="text">
+ <string>Match whole word</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBox_3">
+ <property name="text">
+ <string>Search forward</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBox_4">
+ <property name="text">
+ <string>Use Regular Expressions</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMaximumSize</enum>
+ </property>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>Find Next</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_2">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/IndentHandler.cpp b/src/IndentHandler.cpp new file mode 100755 index 0000000..a1109c4 --- /dev/null +++ b/src/IndentHandler.cpp @@ -0,0 +1,1752 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "IndentHandler.h" + +#include "UiGuiSettings.h" +#include "UiGuiErrorMessage.h" +#include "TemplateBatchScript.h" +#include "UiGuiIniFileParser.h" +#include "SettingsPaths.h" + +#include <QToolBox> +#include <QVBoxLayout> +#include <QApplication> +#include <QCheckBox> +#include <QComboBox> +#include <QToolButton> +#include <QFile> +#include <QProcess> +#include <QSettings> +#include <QStringList> +#include <QLineEdit> +#include <QSpinBox> +#include <QLabel> +#include <QByteArray> +#include <QDir> +#include <QMessageBox> +#include <QMainWindow> +#include <QTextStream> +#include <QTextCodec> +#include <QtScript> +#include <QDesktopServices> +#include <QMenu> +#include <QAction> +#include <QContextMenuEvent> +#include <QFileDialog> +#include <QtDebug> + +#ifdef Q_OS_WIN32 +#include <Windows.h> +#endif + +// Avoid unused parameter warnings by this template +template<typename T> +inline void UNUSED_PARAMETER_WARNING_AVOID(T){} + +//! \defgroup grp_Indenter All concerning handling of the indenter. + +/*! + \class IndentHandler + \ingroup grp_Indenter + \brief A widget for handling many indenters that are configured by an ini file. + + This is a widget that is used by the main window. It handles access to the + indenter config file and calls the chosen indenter to reformat the source text. + Calls the indenter each time a setting has been changed and informs + the main window about the reformatted source code. +*/ + + +/*! + \brief Constructor of the indent handler. + + By calling this constructor the indenter to be loaded, can be selected by setting + its \a indenterID, which is the number of found indenter ini files in alphabetic + order starting at index 0. + */ +IndentHandler::IndentHandler(int indenterID, QWidget *mainWindow, QWidget *parent) : QWidget(parent) + , _indenterSelectionCombobox(NULL) + , _indenterParameterHelpButton(NULL) + , _toolBoxContainerLayout(NULL) + , _indenterParameterCategoriesToolBox(NULL) + , _indenterSettings(NULL) + , _mainWindow(NULL) + , _errorMessageDialog(NULL) + , _menuIndenter(NULL) + , _actionLoadIndenterConfigFile(NULL) + , _actionSaveIndenterConfigFile(NULL) + , _actionCreateShellScript(NULL) + , _actionResetIndenterParameters(NULL) + , _parameterChangedCallback(NULL) + , _windowClosedCallback(NULL) +{ + Q_ASSERT_X( indenterID >= 0, "IndentHandler", "the selected indenterID is < 0" ); + + setObjectName(QString::fromUtf8("indentHandler")); + + _mainWindow = mainWindow; + + initIndenterMenu(); + + connect( _actionLoadIndenterConfigFile, SIGNAL(triggered()), this, SLOT(openConfigFileDialog()) ); + connect( _actionSaveIndenterConfigFile, SIGNAL(triggered()), this, SLOT(saveasIndentCfgFileDialog()) ); + connect( _actionCreateShellScript, SIGNAL(triggered()), this, SLOT(createIndenterCallShellScript()) ); + connect( _actionResetIndenterParameters, SIGNAL(triggered()), this, SLOT(resetIndenterParameter()) ); + + // define this widgets resize behavior + setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + + // create vertical layout box, into which the toolbox will be added + _toolBoxContainerLayout = new QVBoxLayout(this); + _toolBoxContainerLayout->setMargin(2); + + // Create horizontal layout for indenter selector and help button. + QHBoxLayout *hboxLayout = new QHBoxLayout(); + //hboxLayout->setMargin(2); + _toolBoxContainerLayout->addLayout( hboxLayout ); + + // Create the indenter selection combo box. + _indenterSelectionCombobox = new QComboBox(this); + _indenterSelectionCombobox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + _indenterSelectionCombobox->setMinimumContentsLength(20); + connect( _indenterSelectionCombobox, SIGNAL(activated(int)), this, SLOT(setIndenter(int)) ); + UiGuiSettings::getInstance()->registerObjectProperty(_indenterSelectionCombobox, "currentIndex", "selectedIndenter"); + hboxLayout->addWidget( _indenterSelectionCombobox ); + + // Create the indenter parameter help button. + _indenterParameterHelpButton = new QToolButton(this); + _indenterParameterHelpButton->setObjectName(QString::fromUtf8("indenterParameterHelpButton")); + _indenterParameterHelpButton->setIcon(QIcon(QString::fromUtf8(":/mainWindow/help.png"))); + hboxLayout->addWidget( _indenterParameterHelpButton ); + // Handle if the indenter parameter help button is pressed. + connect( _indenterParameterHelpButton, SIGNAL(clicked()), this, SLOT(showIndenterManual()) ); + + // create a toolbox and set its resize behavior + _indenterParameterCategoriesToolBox = new QToolBox(this); + _indenterParameterCategoriesToolBox->setObjectName(QString::fromUtf8("_indenterParameterCategoriesToolBox")); + +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + connect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS + + //_indenterParameterCategoriesToolBox->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + //_indenterParameterCategoriesToolBox->setMaximumSize(QSize(16777215, 16777215)); + // insert the toolbox into the vlayout + _toolBoxContainerLayout->addWidget(_indenterParameterCategoriesToolBox); + + _indenterExecutableCallString = ""; + _indenterExecutableSuffix = ""; + + _indenterDirctoryStr = SettingsPaths::getIndenterPath(); + _tempDirctoryStr = SettingsPaths::getTempPath(); + _settingsDirctoryStr = SettingsPaths::getSettingsPath(); + QDir indenterDirctory = QDir(_indenterDirctoryStr); + + if ( _mainWindow != NULL ) { + _errorMessageDialog = new UiGuiErrorMessage(_mainWindow); + } + else { + _errorMessageDialog = new UiGuiErrorMessage(this); + } + + _indenterIniFileList = indenterDirctory.entryList( QStringList("uigui_*.ini") ); + if ( _indenterIniFileList.count() > 0 ) { + // Take care if the selected indenterID is smaller or greater than the number of existing indenters + if ( indenterID < 0 ) { + indenterID = 0; + } + if ( indenterID >= _indenterIniFileList.count() ) { + indenterID = _indenterIniFileList.count() - 1; + } + + // Reads and parses the by indenterID defined indent ini file and creates toolbox entries + readIndentIniFile( _indenterDirctoryStr + "/" + _indenterIniFileList.at(indenterID) ); + + // Find out how the indenter can be executed. + createIndenterCallString(); + + // Load the users last settings made for this indenter. + loadConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg" ); + + // Fill the indenter selection combo box with the list of available indenters. + if ( !getAvailableIndenters().isEmpty() ) { + _indenterSelectionCombobox->addItems( getAvailableIndenters() ); + _indenterSelectionCombobox->setCurrentIndex( indenterID ); + connect( _indenterSelectionCombobox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(selectedIndenterIndexChanged(int)) ); + } + } + else { + _errorMessageDialog->showMessage(tr("No indenter ini files"), tr("There exists no indenter ini files in the directory \"") + QDir(_indenterDirctoryStr).absolutePath() + "\"."); + } + + retranslateUi(); +} + + +/*! + \brief Implicitly writes the current indenter parameters to the indenters config file. + */ +IndentHandler::~IndentHandler() { + // Generate the parameter string that will be saved to the indenters config file. + QString parameterString = getParameterString(); + if ( !_indenterFileName.isEmpty() ) { + saveConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg", parameterString ); + } + + delete _errorMessageDialog; +} + + +/*! + \brief Initializes the context menu used for some actions like saving the indenter config file. + */ +void IndentHandler::initIndenterMenu() { + if ( _menuIndenter == NULL ) { + _actionLoadIndenterConfigFile = new QAction(this); + _actionLoadIndenterConfigFile->setObjectName(QString::fromUtf8("_actionLoadIndenterConfigFile")); + _actionLoadIndenterConfigFile->setIcon(QIcon(QString::fromUtf8(":/mainWindow/load_indent_cfg.png"))); + + _actionSaveIndenterConfigFile = new QAction(this); + _actionSaveIndenterConfigFile->setObjectName(QString::fromUtf8("_actionSaveIndenterConfigFile")); + _actionSaveIndenterConfigFile->setIcon(QIcon(QString::fromUtf8(":/mainWindow/save_indent_cfg.png"))); + + _actionCreateShellScript = new QAction(this); + _actionCreateShellScript->setObjectName(QString::fromUtf8("_actionCreateShellScript")); + _actionCreateShellScript->setIcon(QIcon(QString::fromUtf8(":/mainWindow/shell.png"))); + + _actionResetIndenterParameters = new QAction(this); + _actionResetIndenterParameters->setObjectName(QString::fromUtf8("_actionResetIndenterParameters")); + _actionResetIndenterParameters->setIcon(QIcon(QString::fromUtf8(":/mainWindow/view-refresh.png"))); + + _menuIndenter = new QMenu(this); + _menuIndenter->setObjectName(QString::fromUtf8("_menuIndenter")); + _menuIndenter->addAction(_actionLoadIndenterConfigFile); + _menuIndenter->addAction(_actionSaveIndenterConfigFile); + _menuIndenter->addAction(_actionCreateShellScript); + _menuIndenter->addAction(_actionResetIndenterParameters); + } +} + + +/*! + \brief Returns the context menu used for some actions like saving the indenter config file. + */ +QMenu* IndentHandler::getIndenterMenu() { + return _menuIndenter; +} + + +/*! + \brief Returns the actions of the context menu used for some actions like saving the indenter config file. + */ +QList<QAction*> IndentHandler::getIndenterMenuActions() { + QList<QAction*> actionList; + actionList << _actionLoadIndenterConfigFile << _actionSaveIndenterConfigFile << _actionCreateShellScript << _actionResetIndenterParameters; + return actionList; +} + + +/*! + \brief Opens the context menu, used for some actions like saving the indenter config file, at the event position. + */ +void IndentHandler::contextMenuEvent( QContextMenuEvent *event ) { + getIndenterMenu()->exec( event->globalPos() ); +} + + +/*! + \brief Creates the content for a shell script that can be used as a external tool call + to indent an as parameter defined file. + */ +QString IndentHandler::generateShellScript(const QString &configFilename) { + QString indenterCompleteCallString; + QString parameterInputFile; + QString parameterOuputFile; + QString parameterParameterFile; + QString replaceInputFileCommand; + + // Define the placeholder for parameter variables either in batch or bash programming. +#if defined(Q_OS_WIN32) + QString shellParameterPlaceholder = "%1"; +#else + QString shellParameterPlaceholder = "$1"; +#endif + + parameterInputFile = " " + _inputFileParameter + "\"" + shellParameterPlaceholder + "\""; + + if ( _outputFileParameter != "none" && _outputFileParameter != "stdout" ) { + if ( _outputFileName == _inputFileName ) { + parameterOuputFile = " " + _outputFileParameter + "\"" + shellParameterPlaceholder + "\""; + } + else { + parameterOuputFile = " " + _outputFileParameter + _outputFileName + ".tmp"; + } + } + + // If the config file name is empty it is assumed that all parameters are sent via command line call + if ( _globalConfigFilename.isEmpty() ) { + parameterParameterFile = " " + getParameterString(); + } + // else if needed add the parameter to the indenter call string where the config file can be found. + else if (_useCfgFileParameter != "none") { + parameterParameterFile = " " + _useCfgFileParameter + "\"./" + configFilename + "\""; + } + + // Assemble indenter call string for parameters according to the set order. + if ( _parameterOrder == "ipo" ) { + indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile; + } + else if ( _parameterOrder == "pio" ) { + indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile; + } + else if ( _parameterOrder == "poi" ) { + indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile; + } + else { + indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile; + } + + // Generate the indenter call string either for win32 or other systems. +#if defined(Q_OS_WIN32) + indenterCompleteCallString = _indenterExecutableCallString + indenterCompleteCallString; +#else + indenterCompleteCallString = "#!/bin/bash\n" + _indenterExecutableCallString + indenterCompleteCallString; +#endif + + // If the indenter writes to stdout pipe the output into a file + if ( _outputFileParameter == "stdout" ) { + indenterCompleteCallString = indenterCompleteCallString + " >" + _outputFileName + ".tmp"; + } + + // If the output filename is not the same as the input filename copy the output over the input. + if ( _outputFileName != _inputFileName ) { +#if defined(Q_OS_WIN32) + replaceInputFileCommand = "move /Y " + _outputFileName + ".tmp \"" + shellParameterPlaceholder + "\"\n"; +#else + replaceInputFileCommand = "mv " + _outputFileName + ".tmp \"" + shellParameterPlaceholder + "\"\n"; +#endif + } + +#if defined(Q_OS_WIN32) + QString shellScript( TemplateBatchScript::getTemplateBatchScript() ); + shellScript = shellScript.replace("__INDENTERCALLSTRING2__", indenterCompleteCallString + "\n" + replaceInputFileCommand); + indenterCompleteCallString = indenterCompleteCallString.replace("%1", "%%G"); + replaceInputFileCommand = replaceInputFileCommand.replace("%1", "%%G"); + shellScript = shellScript.replace("__INDENTERCALLSTRING1__", indenterCompleteCallString + "\n" + replaceInputFileCommand); +#else + QString shellScript( TemplateBatchScript::getTemplateBatchScript() ); + shellScript = shellScript.replace("__INDENTERCALLSTRING2__", indenterCompleteCallString + "\n" + replaceInputFileCommand); + indenterCompleteCallString = indenterCompleteCallString.replace("$1", "$file2indent"); + replaceInputFileCommand = replaceInputFileCommand.replace("$1", "$file2indent"); + shellScript = shellScript.replace("__INDENTERCALLSTRING1__", indenterCompleteCallString + "\n" + replaceInputFileCommand); +#endif + + return shellScript; +} + + +/*! + \brief Format \a sourceCode by calling the indenter. + + The \a inputFileExtension has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +QString IndentHandler::callIndenter(QString sourceCode, QString inputFileExtension) { + if ( _indenterExecutableSuffix == ".js" ) { + return callJavaScriptIndenter(sourceCode); + } + else { + return callExecutableIndenter(sourceCode, inputFileExtension); + } +} + + +/*! + \brief Format \a sourceCode by calling the interpreted JavaScript code of the indenter. + + The \a inputFileExtension has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +QString IndentHandler::callJavaScriptIndenter(QString sourceCode) { + QScriptEngine engine; + + engine.globalObject().setProperty("unformattedCode", sourceCode); + + QFile jsDecoderFile( _indenterExecutableCallString ); + QString jsDecoderCode; + if (jsDecoderFile.open(QFile::ReadOnly)) { + jsDecoderCode = jsDecoderFile.readAll(); + } + jsDecoderFile.close(); + + QScriptValue value = engine.evaluate(jsDecoderCode); + return value.toString(); +} + + +/*! + \brief Format \a sourceCode by calling the binary executable of the indenter. + + The \a inputFileExtension has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +QString IndentHandler::callExecutableIndenter(QString sourceCode, QString inputFileExtension) { + Q_ASSERT_X( !_inputFileName.isEmpty(), "callIndenter", "_inputFileName is empty" ); +// Q_ASSERT_X( !_outputFileName.isEmpty(), "callIndenter", "_outputFileName is empty" ); + Q_ASSERT_X( !_indenterFileName.isEmpty(), "callIndenter", "_indenterFileName is empty" ); + + if ( _indenterFileName.isEmpty() ) { + return ""; + } + + QString formattedSourceCode; + QString indenterCompleteCallString; + QString parameterInputFile; + QString parameterOuputFile; + QString parameterParameterFile; + QProcess indentProcess; + QString processReturnString; + + // Generate the parameter string that will be saved to the indenters config file + QString parameterString = getParameterString(); + + if ( !_globalConfigFilename.isEmpty() ) { + saveConfigFile( _tempDirctoryStr + "/" + _globalConfigFilename, parameterString ); + } + + // Only add a dot to file extension if the string is not empty + if ( !inputFileExtension.isEmpty() ) { + inputFileExtension = "." + inputFileExtension; + } + + // Delete any previously used input src file and create a new input src file. + QFile::remove(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension); + QFile inputSrcFile(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension); + // Write the source code to the input file for the indenter + if ( inputSrcFile.open( QFile::ReadWrite | QFile::Text ) ) { + inputSrcFile.write( sourceCode.toUtf8() ); + inputSrcFile.close(); + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Wrote to be indented source code to file " << inputSrcFile.fileName(); + } + else { + qCritical() << __LINE__ << " " << __FUNCTION__ << ": Couldn't write to be indented source code to file " << inputSrcFile.fileName(); + } + + // Set the input file for the to be called indenter. + if ( _inputFileParameter.trimmed() == "<" || _inputFileParameter == "stdin" ) { + parameterInputFile = ""; + indentProcess.setStandardInputFile( inputSrcFile.fileName() ); + } + else { + parameterInputFile = " " + _inputFileParameter + _inputFileName + inputFileExtension; + } + + // Set the output file for the to be called indenter. + if ( _outputFileParameter != "none" && _outputFileParameter != "stdout" ) { + parameterOuputFile = " " + _outputFileParameter + _outputFileName + inputFileExtension; + } + +#ifdef Q_OS_WIN32 + // Paths may contain Unicode or other foreign characters. Windows commands line tools will + // receive als falsely encoded path string by QProcess or they connot correctly handle + // the Unicode path on their own. + // Because of this the path gets converted to Windows short paths using the 8.3 notation. + + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Temp dir before trying to convert it to short Windows path is" << _tempDirctoryStr; + + // At first convert the temp path to Windows like separators. + QString tempDirctoryStrHelper = QDir::toNativeSeparators(_tempDirctoryStr).replace("\\", "\\\\"); + // Then convert the QString to a WCHAR array and NULL terminate it. + WCHAR *tempDirctoryWindowsStr = new WCHAR[ tempDirctoryStrHelper.length()+1 ]; + tempDirctoryStrHelper.toWCharArray( tempDirctoryWindowsStr ); + tempDirctoryWindowsStr[ tempDirctoryStrHelper.length() ] = (WCHAR)NULL; + + // Get the length of the resulting short path. + long length = 0; + TCHAR *buffer = NULL; + length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, NULL, 0); + + // If the short path could be retrieved, create a correct sized buffer, store the + // short path in it and convert all back to QString. + if ( length != 0 ) { +#ifdef UNICODE + buffer = new WCHAR[length]; + length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, buffer, length); + tempDirctoryStrHelper = QString::fromWCharArray( buffer ); +#else + buffer = new TCHAR[length]; + length = GetShortPathName((LPCTSTR)tempDirctoryWindowsStr, buffer, length); + tempDirctoryStrHelper = buffer; +#endif + _tempDirctoryStr = QDir::fromNativeSeparators(tempDirctoryStrHelper).replace("//", "/"); + delete [] buffer; + + // Check whether the short path still contains some kind of non ascii characters. + if ( _tempDirctoryStr.length() != _tempDirctoryStr.toAscii().length() ) { + qWarning() << __LINE__ << " " << __FUNCTION__ << ": Shortened path still contains non ascii characters. Could cause some indenters not to work properly!"; + } + } + else { + qWarning() << __LINE__ << " " << __FUNCTION__ << ": Couldn't retrieve a short version of the temporary path!"; + } + + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Temp dir after trying to convert it to short Windows path is " << _tempDirctoryStr; + + delete [] tempDirctoryWindowsStr; +#endif + + // If the config file name is empty it is assumed that all parameters are sent via command line call + if ( _globalConfigFilename.isEmpty() ) { + parameterParameterFile = " " + parameterString; + } + // if needed add the parameter to the indenter call string where the config file can be found + else if (_useCfgFileParameter != "none") { + parameterParameterFile = " " + _useCfgFileParameter + "\"" + _tempDirctoryStr + "/" + _globalConfigFilename + "\""; + } + + // Assemble indenter call string for parameters according to the set order. + if ( _parameterOrder == "ipo" ) { + indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile; + } + else if ( _parameterOrder == "pio" ) { + indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile; + } + else if ( _parameterOrder == "poi" ) { + indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile; + } + else { + indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile; + } + + // If no indenter executable call string could be created before, show an error message. + if ( _indenterExecutableCallString.isEmpty() ) { + _errorMessageDialog->showMessage(tr("No indenter executable"), + tr("There exists no indenter executable with the name \"%1\" in the directory \"%2\" nor in the global environment.").arg(_indenterFileName).arg(_indenterDirctoryStr) ); + return sourceCode; + } + + // Generate the indenter call string either for win32 or other systems. + indenterCompleteCallString = _indenterExecutableCallString + indenterCompleteCallString; + + // errors and standard outputs from the process call are merged together + //indentProcess.setReadChannelMode(QProcess::MergedChannels); + + // Set the directory where the indenter will be executed for the process' environment as PWD. + QStringList env = indentProcess.environment(); + env << "PWD=" + QFileInfo(_tempDirctoryStr).absoluteFilePath(); + indentProcess.setEnvironment( env ); + + // Set the directory for the indenter execution + indentProcess.setWorkingDirectory( QFileInfo(_tempDirctoryStr).absoluteFilePath() ); + + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Will call the indenter in the directory " << indentProcess.workingDirectory() << " using this commandline call: " << indenterCompleteCallString; + + indentProcess.start(indenterCompleteCallString); + + processReturnString = ""; + bool calledProcessSuccessfully = indentProcess.waitForFinished(10000); + // test if there was an error during starting the process of the indenter + if ( !calledProcessSuccessfully ) { + processReturnString = "<html><body>"; + processReturnString += tr("<b>Returned error message:</b> ") + indentProcess.errorString() + "<br>"; + + switch ( indentProcess.error() ) { + case QProcess::FailedToStart : + 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>"; + break; + case QProcess::Crashed : + processReturnString += "The process crashed some time after starting successfully.<br>"; + break; + case QProcess::Timedout : + processReturnString += "The called indenter did not response for over 10 seconds, so aborted its execution.<br>"; + break; + case QProcess::WriteError : + 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>"; + break; + case QProcess::ReadError : + processReturnString += "An error occurred when attempting to read from the process. For example, the process may not be running.<br>"; + break; + case QProcess::UnknownError : + processReturnString += "An unknown error occurred. This is the default return value of error().<br>"; + break; + default : + break; + } + processReturnString += tr("<br><b>Callstring was:</b> ") + encodeToHTML(indenterCompleteCallString); + processReturnString += tr("<br><br><b>Indenter output was:</b><pre>") + "<br>" + + "(STDOUT):" + encodeToHTML( indentProcess.readAllStandardOutput() ) + "<br>" + + "(STDERR):" + encodeToHTML( indentProcess.readAllStandardError() ) + "<br>" + + "</pre></html></body>"; + qWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString; + QApplication::restoreOverrideCursor(); + _errorMessageDialog->showMessage(tr("Error calling Indenter"), processReturnString); + } + + + // If the indenter returned an error code != 0 show its output. + if ( indentProcess.exitCode() != 0 ) { + QString exitCode; + exitCode.setNum(indentProcess.exitCode()); + processReturnString = tr("<b>Indenter returned with exit code:</b> ") + exitCode + "<br>" + + tr("<b>Indent console output was:</b> ") + "<br>" + + "(STDOUT):" + encodeToHTML( indentProcess.readAllStandardOutput() ) + "<br>" + + "(STDERR):" + encodeToHTML( indentProcess.readAllStandardError() ) + "<br>" + + tr("<br><b>Callstring was:</b> ") + encodeToHTML(indenterCompleteCallString) + + "</html></body>"; + qWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString; + QApplication::restoreOverrideCursor(); + _errorMessageDialog->showMessage( tr("Indenter returned error"), processReturnString ); + } + + // Only get the formatted source code, if calling the indenter did succeed. + if ( calledProcessSuccessfully ) { + // If the indenter results are written to stdout, read them from there... + if ( indentProcess.exitCode() == 0 && _outputFileParameter == "stdout" ) { + formattedSourceCode = indentProcess.readAllStandardOutput(); + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from StdOut."; + } + // ... else read the output file generated by the indenter call. + else { + QFile outSrcFile(_tempDirctoryStr + "/" + _outputFileName + inputFileExtension); + if ( outSrcFile.open(QFile::ReadOnly | QFile::Text) ) { + QTextStream outSrcStrm(&outSrcFile); + outSrcStrm.setCodec( QTextCodec::codecForName("UTF-8") ); + formattedSourceCode = outSrcStrm.readAll(); + outSrcFile.close(); + qDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from file " << outSrcFile.fileName(); + } + else { + qCritical() << __LINE__ << " " << __FUNCTION__ << ": Couldn't read indenter output from file " << outSrcFile.fileName(); + } + } + } + else { + return sourceCode; + } + + // Delete the temporary input and output files. + QFile::remove(_tempDirctoryStr + "/" + _outputFileName + inputFileExtension); + QFile::remove(_tempDirctoryStr + "/" + _inputFileName + inputFileExtension); + + return formattedSourceCode; +} + + +/*! + \brief Generates and returns a string with all parameters needed to call the indenter. + */ +QString IndentHandler::getParameterString() { + QString parameterString = ""; + + // generate parameter string for all boolean values + foreach (ParamBoolean pBoolean, _paramBooleans) { + if ( pBoolean.checkBox->isChecked() ) { + if ( !pBoolean.trueString.isEmpty() ) { + parameterString += pBoolean.trueString + _cfgFileParameterEnding; + } + } + else { + if ( !pBoolean.falseString.isEmpty() ) { + parameterString += pBoolean.falseString + _cfgFileParameterEnding; + } + } + } + + // generate parameter string for all numeric values + foreach (ParamNumeric pNumeric, _paramNumerics) { + if ( pNumeric.valueEnabledChkBox->isChecked() ) { + parameterString += pNumeric.paramCallName + QString::number( pNumeric.spinBox->value() ) + _cfgFileParameterEnding; + } + } + + // generate parameter string for all string values + foreach (ParamString pString, _paramStrings) { + if ( !pString.lineEdit->text().isEmpty() && pString.valueEnabledChkBox->isChecked() ) { + // Create parameter definition for each value devided by a | sign. + foreach (QString paramValue, pString.lineEdit->text().split("|")) { + parameterString += pString.paramCallName + paramValue + _cfgFileParameterEnding; + } + } + } + + // generate parameter string for all multiple choice values + foreach (ParamMultiple pMultiple, _paramMultiples) { + if ( pMultiple.valueEnabledChkBox->isChecked() ) { + parameterString += pMultiple.choicesStrings.at( pMultiple.comboBox->currentIndex () ) + _cfgFileParameterEnding; + } + } + + return parameterString; +} + + +/*! + \brief Write settings for the indenter to a config file. + */ +void IndentHandler::saveConfigFile(QString filePathName, QString paramString) { + QFile::remove( filePathName ); + QFile cfgFile( filePathName ); + + cfgFile.open( QFile::ReadWrite | QFile::Text ); + cfgFile.write( paramString.toAscii() ); + cfgFile.close(); +} + + +/*! + \brief Load the config file for the indenter and apply the settings made there. + */ +bool IndentHandler::loadConfigFile(QString filePathName) { + QFile cfgFile(filePathName); + int index; + int crPos; + int paramValue = 0; + QString paramValueStr = ""; + QString cfgFileData = ""; + + // If the to be loaded config file does not exist leave all values as they are and return false. + if ( !cfgFile.exists() ) { + return false; + } + // else if the to be read config file exists, retrieve its whole content. + else { + // Open the config file and read all data + cfgFile.open( QFile::ReadOnly | QFile::Text ); + cfgFileData = cfgFile.readAll(); + cfgFile.close(); + } + + // Search for name of each boolean parameter and set its value if found. + foreach (ParamBoolean pBoolean, _paramBooleans) { + // boolean value that will be assigned to the checkbox + bool paramValue = false; + + // first search for the longer parameter string + // the true parameter string is longer than the false string + if ( pBoolean.trueString.length() > pBoolean.falseString.length() ) { + // search for the true string + index = cfgFileData.indexOf( pBoolean.trueString, 0, Qt::CaseInsensitive ); + // if true string found set the parameter value to true + if ( index != -1 ) { + paramValue = true; + } + // if true string not found, search for false string + else { + index = cfgFileData.indexOf( pBoolean.falseString, 0, Qt::CaseInsensitive ); + // if false string found set the parameter value to false + if ( index != -1 ) { + paramValue = false; + } + // neither true nor false parameter found so use default value + else { + paramValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool(); + } + } + } + // the false parameter string is longer than the true string + else { + // search for the false string + index = cfgFileData.indexOf( pBoolean.falseString, 0, Qt::CaseInsensitive ); + // if false string found set the parameter value to false + if ( index != -1 ) { + paramValue = false; + } + // if false string not found, search for true string + else { + index = cfgFileData.indexOf( pBoolean.trueString, 0, Qt::CaseInsensitive ); + // if true string found set the parameter value to true + if ( index != -1 ) { + paramValue = true; + } + // neither true nor false parameter found so use default value + else { + paramValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool(); + } + } + } + pBoolean.checkBox->setChecked(paramValue); + } + + // Search for name of each numeric parameter and set the value found behind it. + foreach (ParamNumeric pNumeric, _paramNumerics) { + index = cfgFileData.indexOf( pNumeric.paramCallName, 0, Qt::CaseInsensitive ); + // parameter was found in config file + if ( index != -1 ) { + // set index after the parameter name, so in front of the number + index += pNumeric.paramCallName.length(); + + // Find the end of the parameter by searching for set config file parameter ending. Most of time this is a carriage return. + crPos = cfgFileData.indexOf( _cfgFileParameterEnding, index+1 ); + + // get the number and convert it to int + QString test = cfgFileData.mid( index, crPos - index ); + paramValue = cfgFileData.mid( index, crPos - index ).toInt(NULL); + + // disable the signal-slot connection. Otherwise signal is emmitted each time when value is set + QObject::disconnect(pNumeric.spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings())); + pNumeric.spinBox->setValue( paramValue ); + pNumeric.valueEnabledChkBox->setChecked( true ); + QObject::connect(pNumeric.spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings())); + } + // parameter was not found in config file + else { + int defaultValue = _indenterSettings->value(pNumeric.paramName + "/ValueDefault").toInt(); + pNumeric.spinBox->setValue( defaultValue ); + pNumeric.valueEnabledChkBox->setChecked( false ); + } + } + + // Search for name of each string parameter and set it. + foreach (ParamString pString, _paramStrings) { + paramValueStr = ""; + // The number of the found values for this parameter name. + int numberOfValues = 0; + index = cfgFileData.indexOf( pString.paramCallName, 0, Qt::CaseInsensitive ); + // If parameter was found in config file + if ( index != -1 ) { + while ( index != -1 ) { + numberOfValues++; + + // Set index after the parameter name, so it points to the front of the string value. + index += pString.paramCallName.length(); + + // Find the end of the parameter by searching for set config file parameter ending. Most of time this is a carriage return. + crPos = cfgFileData.indexOf( _cfgFileParameterEnding, index+1 ); + + // Get the string and remember it. + if ( numberOfValues < 2 ) { + paramValueStr = QString( cfgFileData.mid( index, crPos - index ) ); + } + // If the same parameter has been set multiple times, concatenate the strings dvivided by a |. + else { + paramValueStr = paramValueStr + "|" + QString( cfgFileData.mid( index, crPos - index ) ); + } + + // Get next value for this setting, if one exists. + index = cfgFileData.indexOf( pString.paramCallName, crPos+1, Qt::CaseInsensitive ); + } + // Set the text for the line edit. + pString.lineEdit->setText( paramValueStr ); + pString.valueEnabledChkBox->setChecked( true ); + } + // Parameter was not found in config file + else { + paramValueStr = _indenterSettings->value(pString.paramName + "/ValueDefault").toString(); + pString.lineEdit->setText( paramValueStr ); + pString.valueEnabledChkBox->setChecked( false ); + } + } + + // search for name of each multiple choice parameter and set it + foreach (ParamMultiple pMultiple, _paramMultiples) { + int i = 0; + index = -1; + + // search for all parameter names of the multiple choice list + // if one is found, set it and leave the while loop + while ( i < pMultiple.choicesStrings.count() && index == -1 ) { + index = cfgFileData.indexOf( pMultiple.choicesStrings.at(i), 0, Qt::CaseInsensitive ); + if ( index != -1 ) { + pMultiple.comboBox->setCurrentIndex( i ); + pMultiple.valueEnabledChkBox->setChecked( true ); + } + i++; + } + + // parameter was not set in config file, so use default value + if ( index == -1 ) { + int defaultValue = _indenterSettings->value(pMultiple.paramName + "/ValueDefault").toInt(); + pMultiple.comboBox->setCurrentIndex( defaultValue ); + pMultiple.valueEnabledChkBox->setChecked( false ); + } + } + + return true; +} + + +/*! + \brief Sets all indenter parameters to their default values defined in the ini file. + */ +void IndentHandler::resetToDefaultValues() { + // Search for name of each boolean parameter and set its value if found. + foreach (ParamBoolean pBoolean, _paramBooleans) { + // Boolean value that will be assigned to the checkbox. + bool defaultValue = _indenterSettings->value(pBoolean.paramName + "/ValueDefault").toBool(); + pBoolean.checkBox->setChecked( defaultValue ); + } + + // Search for name of each numeric parameter and set the value found behind it. + foreach (ParamNumeric pNumeric, _paramNumerics) { + int defaultValue = _indenterSettings->value(pNumeric.paramName + "/ValueDefault").toInt(); + pNumeric.spinBox->setValue( defaultValue ); + pNumeric.valueEnabledChkBox->setChecked( _indenterSettings->value(pNumeric.paramName + "/Enabled").toBool() ); + } + + // Search for name of each string parameter and set it. + foreach (ParamString pString, _paramStrings) { + QString defaultValue = _indenterSettings->value(pString.paramName + "/ValueDefault").toString(); + pString.lineEdit->setText( defaultValue ); + pString.valueEnabledChkBox->setChecked( _indenterSettings->value(pString.paramName + "/Enabled").toBool() ); + } + + // Search for name of each multiple choice parameter and set it. + foreach (ParamMultiple pMultiple, _paramMultiples) { + int defaultValue = _indenterSettings->value(pMultiple.paramName + "/ValueDefault").toInt(); + pMultiple.comboBox->setCurrentIndex( defaultValue ); + pMultiple.valueEnabledChkBox->setChecked( _indenterSettings->value(pMultiple.paramName + "/Enabled").toBool() ); + } +} + + +/*! + \brief Opens and parses the indenter ini file that is declared by \a iniFilePath. + */ +void IndentHandler::readIndentIniFile(QString iniFilePath) { + Q_ASSERT_X( !iniFilePath.isEmpty(), "readIndentIniFile", "iniFilePath is empty" ); + + // open the ini-file that contains all available indenter settings with their additional infos + _indenterSettings = new UiGuiIniFileParser(iniFilePath); + + QStringList categories; + //QString indenterGroupString = ""; + QString paramToolTip = ""; + + + // + // parse ini file indenter header + // + + _indenterName = _indenterSettings->value("header/indenterName").toString(); + _indenterFileName = _indenterSettings->value("header/indenterFileName").toString(); + _globalConfigFilename = _indenterSettings->value("header/configFilename").toString(); + _useCfgFileParameter = _indenterSettings->value("header/useCfgFileParameter").toString(); + _cfgFileParameterEnding = _indenterSettings->value("header/cfgFileParameterEnding").toString(); + if ( _cfgFileParameterEnding == "cr" ) { + _cfgFileParameterEnding = "\n"; + } + _indenterShowHelpParameter = _indenterSettings->value("header/showHelpParameter").toString(); + + if ( _indenterFileName.isEmpty() ) { + _errorMessageDialog->showMessage( tr("Indenter ini file header error"), + tr("The loaded indenter ini file \"%1\"has a faulty header. At least the indenters file name is not set.").arg(iniFilePath) ); + } + + // Read the parameter order. Possible values are (p=parameter[file] i=inputfile o=outputfile) + // pio, ipo, iop + _parameterOrder = _indenterSettings->value("header/parameterOrder", "pio").toString(); + _inputFileParameter = _indenterSettings->value("header/inputFileParameter").toString(); + _inputFileName = _indenterSettings->value("header/inputFileName").toString(); + _outputFileParameter = _indenterSettings->value("header/outputFileParameter").toString(); + _outputFileName = _indenterSettings->value("header/outputFileName").toString(); + _fileTypes = _indenterSettings->value("header/fileTypes").toString(); + _fileTypes.replace('|', " "); + + // read the categories names which are separated by "|" + QString categoriesStr = _indenterSettings->value("header/categories").toString(); + categories = categoriesStr.split("|"); + // Assure that the category list is never empty. At least contain a "general" section. + if ( categories.isEmpty() ) { + categories.append("General"); + } + + IndenterParameterCategoryPage categoryPage; + + // create a page for each category and store its references in a toolboxpage-array + foreach (QString category, categories) { + categoryPage.widget = new QWidget(); + categoryPage.widget->setObjectName(category); + categoryPage.widget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + categoryPage.vboxLayout = new QVBoxLayout(categoryPage.widget); + categoryPage.vboxLayout->setSpacing(6); + categoryPage.vboxLayout->setMargin(9); + categoryPage.vboxLayout->setObjectName(category); + _indenterParameterCategoryPages.append(categoryPage); + _indenterParameterCategoriesToolBox->addItem(categoryPage.widget, category); + } + + + // + // parse ini file indenter parameters + // + + // read all possible parameters written in brackets [] + _indenterParameters = _indenterSettings->childGroups(); + + // read each parameter to create the corresponding input field + foreach (QString indenterParameter, _indenterParameters) { + // if it is not the indent header definition read the parameter and add it to + // the corresponding category toolbox page + if ( indenterParameter != "header") { + // read to which category the parameter belongs + int category = _indenterSettings->value(indenterParameter + "/Category").toInt(); + // Assure that the category number is never greater than the available categories. + if ( category > _indenterParameterCategoryPages.size()-1 ) { + category = _indenterParameterCategoryPages.size()-1; + } + // read which type of input field the parameter needs + QString editType = _indenterSettings->value(indenterParameter + "/EditorType").toString(); + + // edit type is numeric so create a spinbox with label + if ( editType == "numeric" ) { + // read the parameter name as it is used at the command line or in its config file + QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString(); + + // create checkbox which enables or disables the parameter + QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget ); + chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() ); + chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." ); + chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + int left, top, right, bottom; + chkBox->getContentsMargins( &left, &top, &right, &bottom ); + chkBox->setContentsMargins( left, top, 0, bottom ); + + // create the spinbox + QSpinBox *spinBox = new QSpinBox( _indenterParameterCategoryPages.at(category).widget ); + paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString(); + spinBox->setToolTip( paramToolTip ); + spinBox->setMaximumWidth(50); + spinBox->setMinimumWidth(50); + if ( _mainWindow != NULL ) { + spinBox->installEventFilter( _mainWindow ); + } + if ( _indenterSettings->value(indenterParameter + "/MinVal").toString() != "" ) { + spinBox->setMinimum( _indenterSettings->value(indenterParameter + "/MinVal").toInt() ); + } + else { + spinBox->setMinimum( 0 ); + } + if ( _indenterSettings->value(indenterParameter + "/MaxVal").toString() != "" ) { + spinBox->setMaximum( _indenterSettings->value(indenterParameter + "/MaxVal").toInt() ); + } + else { + spinBox->setMaximum( 2000 ); + } + + // create the label + QLabel *label = new QLabel( _indenterParameterCategoryPages.at(category).widget ); + label->setText(indenterParameter); + label->setBuddy(spinBox); + label->setToolTip( paramToolTip ); + if ( _mainWindow != NULL ) { + label->installEventFilter( _mainWindow ); + } + + // put all into a layout and add it to the toolbox page + QHBoxLayout *hboxLayout = new QHBoxLayout(); + hboxLayout->addWidget(chkBox); + hboxLayout->addWidget(spinBox); + hboxLayout->addWidget(label); + _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout); + + // remember parameter name and reference to its spinbox + ParamNumeric paramNumeric; + paramNumeric.paramName = indenterParameter; + paramNumeric.paramCallName = parameterCallName; + paramNumeric.spinBox = spinBox; + paramNumeric.label = label; + paramNumeric.valueEnabledChkBox = chkBox; + paramNumeric.spinBox->setValue( _indenterSettings->value(paramNumeric.paramName + "/ValueDefault").toInt() ); + _paramNumerics.append(paramNumeric); + + QObject::connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(handleChangedIndenterSettings())); + QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings())); +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + connect( spinBox, SIGNAL(valueChanged(int)), this, SLOT(updateDrawing()) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS + } + // edit type is boolean so create a checkbox + else if ( editType == "boolean" ) { + // create the checkbox, make its settings and add it to the toolbox page + QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget ); + chkBox->setText(indenterParameter); + paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString(); + chkBox->setToolTip( paramToolTip ); + if ( _mainWindow != NULL ) { + chkBox->installEventFilter( _mainWindow ); + } + _indenterParameterCategoryPages.at(category).vboxLayout->addWidget(chkBox); + + // remember parameter name and reference to its checkbox + ParamBoolean paramBoolean; + paramBoolean.paramName = indenterParameter; + paramBoolean.checkBox = chkBox; + QStringList trueFalseStrings = _indenterSettings->value(indenterParameter + "/TrueFalse").toString().split("|"); + paramBoolean.trueString = trueFalseStrings.at(0); + paramBoolean.falseString = trueFalseStrings.at(1); + paramBoolean.checkBox->setChecked( _indenterSettings->value(paramBoolean.paramName + "/ValueDefault").toBool() ); + _paramBooleans.append(paramBoolean); + + QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings())); + } + // edit type is numeric so create a line edit with label + else if ( editType == "string" ) { + // read the parameter name as it is used at the command line or in its config file + QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString(); + + // create check box which enables or disables the parameter + QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget ); + chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() ); + chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." ); + chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + int left, top, right, bottom; + chkBox->getContentsMargins( &left, &top, &right, &bottom ); + chkBox->setContentsMargins( left, top, 0, bottom ); + + // create the line edit + QLineEdit *lineEdit = new QLineEdit( _indenterParameterCategoryPages.at(category).widget ); + paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString(); + lineEdit->setToolTip( paramToolTip ); + lineEdit->setMaximumWidth(50); + lineEdit->setMinimumWidth(50); + if ( _mainWindow != NULL ) { + lineEdit->installEventFilter( _mainWindow ); + } + + // create the label + QLabel *label = new QLabel( _indenterParameterCategoryPages.at(category).widget ); + label->setText(indenterParameter); + label->setBuddy(lineEdit); + label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + label->setToolTip( paramToolTip ); + if ( _mainWindow != NULL ) { + label->installEventFilter( _mainWindow ); + } + + // put all into a layout and add it to the toolbox page + QHBoxLayout *hboxLayout = new QHBoxLayout(); + hboxLayout->addWidget(chkBox); + hboxLayout->addWidget(lineEdit); + hboxLayout->addWidget(label); + _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout); + + // remember parameter name and reference to its line edit + ParamString paramString; + paramString.paramName = indenterParameter; + paramString.paramCallName = parameterCallName; + paramString.lineEdit = lineEdit; + paramString.label = label; + paramString.valueEnabledChkBox = chkBox; + paramString.lineEdit->setText( _indenterSettings->value(paramString.paramName + "/ValueDefault").toString() ); + _paramStrings.append(paramString); + + QObject::connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(handleChangedIndenterSettings())); + QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings())); +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + connect( lineEdit, SIGNAL(textChanged(const QString)), this, SLOT(updateDrawing()) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS + } + // edit type is multiple so create a combobox with label + else if ( editType == "multiple" ) { + // read the parameter name as it is used at the command line or in its config file + QString parameterCallName = _indenterSettings->value(indenterParameter + "/CallName").toString(); + + // create checkbox which enables or disables the parameter + QCheckBox *chkBox = new QCheckBox( _indenterParameterCategoryPages.at(category).widget ); + chkBox->setChecked( _indenterSettings->value(indenterParameter + "/Enabled").toBool() ); + chkBox->setToolTip( "Enables/disables the parameter. If disabled the indenters default value will be used." ); + chkBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + int left, top, right, bottom; + chkBox->getContentsMargins( &left, &top, &right, &bottom ); + chkBox->setContentsMargins( left, top, 0, bottom ); + + // create the combo box + QComboBox *comboBox = new QComboBox( _indenterParameterCategoryPages.at(category).widget ); + QStringList choicesStrings = _indenterSettings->value(indenterParameter + "/Choices").toString().split("|"); + QStringList choicesStringsReadable = _indenterSettings->value(indenterParameter + "/ChoicesReadable").toString().split("|", QString::SkipEmptyParts); + if ( choicesStringsReadable.isEmpty() ) { + comboBox->addItems( choicesStrings ); + } + else { + comboBox->addItems( choicesStringsReadable ); + } + paramToolTip = _indenterSettings->value(indenterParameter + "/Description").toString(); + comboBox->setToolTip( paramToolTip ); + if ( _mainWindow != NULL ) { + comboBox->installEventFilter( _mainWindow ); + } + + // put all into a layout and add it to the toolbox page + QHBoxLayout *hboxLayout = new QHBoxLayout(); + hboxLayout->addWidget(chkBox); + hboxLayout->addWidget(comboBox); + _indenterParameterCategoryPages.at(category).vboxLayout->addLayout(hboxLayout); + + // remember parameter name and reference to its lineedit + ParamMultiple paramMultiple; + paramMultiple.paramName = indenterParameter; + paramMultiple.paramCallName = parameterCallName; + paramMultiple.comboBox = comboBox; + paramMultiple.choicesStrings = choicesStrings; + paramMultiple.choicesStringsReadable = choicesStringsReadable; + paramMultiple.valueEnabledChkBox = chkBox; + paramMultiple.comboBox->setCurrentIndex( _indenterSettings->value(paramMultiple.paramName + "/ValueDefault").toInt() ); + _paramMultiples.append(paramMultiple); + + QObject::connect(comboBox, SIGNAL(activated(int)), this, SLOT(handleChangedIndenterSettings())); + QObject::connect(chkBox, SIGNAL(clicked()), this, SLOT(handleChangedIndenterSettings())); +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + connect( comboBox, SIGNAL(activated(int)), this, SLOT(updateDrawing()) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS + } + } + } + + // put a spacer at each page end + foreach (IndenterParameterCategoryPage categoryPage, _indenterParameterCategoryPages) { + categoryPage.vboxLayout->addStretch(); + } +} + + +/*! + \brief Searches and returns all indenters a configuration file is found for. + + Opens all uigui ini files found in the list \a _indenterIniFileList, opens each ini file + and reads the there defined real name of the indenter. These names are being returned as QStringList. + */ +QStringList IndentHandler::getAvailableIndenters() { + QStringList indenterNamesList; + + // Loop for every existing uigui ini file + foreach (QString indenterIniFile, _indenterIniFileList) { + // Open the ini file and search for the indenter name + QFile file(_indenterDirctoryStr + "/" + indenterIniFile); + if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { + int index = -1; + QByteArray line; + // Search for the string "indenterName=" and get the following string until line end. + while ( index == -1 && !file.atEnd() ) { + line = file.readLine(); + index = line.indexOf( "indenterName=", 0); + } + + if ( index == 0 ) { + line = line.remove(0, 13); + indenterNamesList << line.trimmed(); + } + } + } + return indenterNamesList; +} + + +/*! + \brief Deletes all elements in the toolbox and initializes the indenter selected by \a indenterID. + */ +void IndentHandler::setIndenter(int indenterID) { + QApplication::setOverrideCursor(Qt::WaitCursor); + +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + disconnect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS + + // Generate the parameter string that will be saved to the indenters config file. + QString parameterString = getParameterString(); + if ( !_indenterFileName.isEmpty() ) { + saveConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg", parameterString ); + } + + // Take care if the selected indenterID is smaller or greater than the number of existing indenters + if ( indenterID < 0 ) { + indenterID = 0; + } + if ( indenterID >= _indenterIniFileList.count() ) { + indenterID = _indenterIniFileList.count() - 1; + } + + // remove all pages from the toolbox + for (int i = 0; i < _indenterParameterCategoriesToolBox->count(); i++) { + _indenterParameterCategoriesToolBox->removeItem(i); + } + + // delete all toolbox pages and by this its children + foreach (IndenterParameterCategoryPage categoryPage, _indenterParameterCategoryPages) { + delete categoryPage.widget; + } + + // empty all lists, which stored infos for the toolbox pages and its widgets + _indenterParameterCategoryPages.clear(); + _paramStrings.clear(); + _paramNumerics.clear(); + _paramBooleans.clear(); + _paramMultiples.clear(); + delete _indenterSettings; + +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + QWidget dummyWidget; + _indenterParameterCategoriesToolBox->addItem(&dummyWidget, "dummyText"); +#endif + + readIndentIniFile( _indenterDirctoryStr + "/" + _indenterIniFileList.at(indenterID) ); + + // Find out how the indenter can be executed. + createIndenterCallString(); + + // Load the users last settings made for this indenter. + loadConfigFile( _settingsDirctoryStr + "/" + _indenterFileName + ".cfg" ); + + handleChangedIndenterSettings(); + + QApplication::restoreOverrideCursor(); + +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + connect( _indenterParameterCategoriesToolBox, SIGNAL(currentChanged(int)), this, SLOT(updateDrawing()) ); + _indenterParameterCategoriesToolBox->removeItem( _indenterParameterCategoriesToolBox->indexOf(&dummyWidget) ); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS +} + + +/*! + \brief Returns a string containing by the indenter supported file types/extensions divided by a space. + */ +QString IndentHandler::getPossibleIndenterFileExtensions() { + return _fileTypes; +} + + +/*! + \brief Returns the path and filename of the current indenter config file. + */ +QString IndentHandler::getIndenterCfgFile() { + QFileInfo fileInfo( _indenterDirctoryStr + "/" + _globalConfigFilename ); + return fileInfo.absoluteFilePath(); +} + + +/*! + \brief Tries to create a call path string for the indenter executable. If successful returns true. + */ +bool IndentHandler::createIndenterCallString() { + QProcess indentProcess; + + if ( _indenterFileName.isEmpty() ) { + return false; + } + + // First try to call the indenter inside of the data dir, using some suffix + // ------------------------------------------------------------------------ + + // Set the directory for the indenter execution + indentProcess.setWorkingDirectory( QFileInfo(_indenterDirctoryStr).absoluteFilePath() ); + + foreach ( QString suffix, QStringList() << "" << ".exe" << ".bat" << ".com" << ".sh" ) { + _indenterExecutableSuffix = suffix; + _indenterExecutableCallString = QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName; + _indenterExecutableCallString += suffix; + + // Only try to call the indenter, if the file exists. + if ( QFile::exists(_indenterExecutableCallString) ) { + // Only try to call the indenter directly if it is no php file + if ( QFileInfo(_indenterExecutableCallString).suffix().toLower() != "php" ) { + indentProcess.start( "\"" + _indenterExecutableCallString + + "\" " + _indenterShowHelpParameter ); + if ( indentProcess.waitForFinished(2000) ) { + _indenterExecutableCallString = "\"" + _indenterExecutableCallString + "\""; + return true; + } + else if ( indentProcess.error() == QProcess::Timedout ) { + _indenterExecutableCallString = "\"" + _indenterExecutableCallString + "\""; + return true; + } + } + + // Test for needed interpreters + // ---------------------------- + // If the file could not be executed, try to find a shebang at its start or test if its a php file. + QString interpreterName = ""; + QFile indenterExecutable( _indenterExecutableCallString ); + + // If indenter executable file has .php as suffix, use php as default interpreter + if ( QFileInfo(_indenterExecutableCallString).suffix().toLower() == "php" ) { + interpreterName = "php -f"; + } + // Else try to open the file and read the shebang. + else if ( indenterExecutable.open(QFile::ReadOnly) ) { + // Read the first line of the file. + QTextStream indenterExecutableContent(&indenterExecutable); + QString firstLineOfIndenterExe = indenterExecutableContent.readLine(75); + indenterExecutable.close(); + + // If the initial shebang is found, read the named intepreter. e.g. perl + if ( firstLineOfIndenterExe.startsWith("#!") ) { + // Get the rightmost word. by splitting the string into only full words. + interpreterName = firstLineOfIndenterExe.split( "/" ).last(); + } + } + + // Try to call the interpreter, if it exists. + if ( !interpreterName.isEmpty() ) { + _indenterExecutableCallString = interpreterName + " \"" + _indenterExecutableCallString + "\""; + indentProcess.start( interpreterName + " -h"); + if ( indentProcess.waitForFinished(2000) ) { + return true; + } + else if ( indentProcess.error() == QProcess::Timedout ) { + return true; + } + // now we know an interpreter is needed but it could not be called, so inform the user. + else { + _errorMessageDialog->showMessage( tr("Interpreter needed"), + 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) ); + return true; + } + } + } + } + + + // If unsuccessful try if the indenter executable is a JavaScript file + // ------------------------------------------------------------------- + _indenterExecutableSuffix = ".js"; + _indenterExecutableCallString = QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName; + _indenterExecutableCallString += _indenterExecutableSuffix; + if ( QFile::exists(_indenterExecutableCallString) ) { + return true; + } + + + // If unsuccessful try to call the indenter global, using some suffix + // ------------------------------------------------------------------ + foreach ( QString suffix, QStringList() << "" << ".exe" << ".bat" << ".com" << ".sh" ) { + _indenterExecutableSuffix = suffix; + _indenterExecutableCallString = _indenterFileName + suffix; + indentProcess.start( _indenterExecutableCallString + " " + _indenterShowHelpParameter ); + if ( indentProcess.waitForFinished(2000) ) { + return true; + } + else if ( indentProcess.error() == QProcess::Timedout ) { + return true; + } + } + + + // If even globally calling the indenter fails, try calling .com and .exe via wine + // ------------------------------------------------------------------------------- + _indenterExecutableCallString = "\"" + QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/" + _indenterFileName; + + foreach ( QString suffix, QStringList() << ".exe" << ".com" ) { + _indenterExecutableSuffix = suffix; + if ( QFile::exists(_indenterDirctoryStr + "/" + _indenterFileName + suffix) ) { + QProcess wineTestProcess; + wineTestProcess.start("wine --version"); + // if the process of wine was not callable assume that wine is not installed + if ( !wineTestProcess.waitForFinished(2000) ) { + _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.") ); + _indenterExecutableCallString = ""; + return false; + } + else { + _indenterExecutableCallString = "\"" + QFileInfo(_indenterDirctoryStr).absoluteFilePath() + "/"; + _indenterExecutableCallString += _indenterFileName + suffix + "\""; + _indenterExecutableCallString = "wine " + _indenterExecutableCallString; + + return true; + } + } + } + + _indenterExecutableCallString = ""; + _indenterExecutableSuffix = ""; + return false; +} + + +/*! + \brief Returns a string that points to where the indenters manual can be found. + */ +QString IndentHandler::getManual() { + if ( _indenterSettings != NULL ) { + return _indenterSettings->value("header/manual").toString(); + } + else { + return ""; + } +} + + +/*! + \brief This slot gets the reference to the indenters manual and opens it. + */ +void IndentHandler::showIndenterManual() { + QString manualReference = getManual(); + QDesktopServices::openUrl( manualReference ); +} + + +/*! + \brief Can be called to update all widgets text to the currently selected language. + */ +void IndentHandler::retranslateUi() { + _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>") ); + _indenterParameterHelpButton->setToolTip( tr("Brings you to the online manual of the currently selected indenter, where you can get further help on the possible parameters.") ); + + _actionLoadIndenterConfigFile->setText(QApplication::translate("IndentHandler", "Load Indenter Config File", 0, QApplication::UnicodeUTF8)); + _actionLoadIndenterConfigFile->setStatusTip(QApplication::translate("IndentHandler", "Opens a file dialog to load the original config file of the indenter.", 0, QApplication::UnicodeUTF8)); + _actionLoadIndenterConfigFile->setShortcut(QApplication::translate("IndentHandler", "Alt+O", 0, QApplication::UnicodeUTF8)); + + _actionSaveIndenterConfigFile->setText(QApplication::translate("IndentHandler", "Save Indenter Config File", 0, QApplication::UnicodeUTF8)); + _actionSaveIndenterConfigFile->setStatusTip(QApplication::translate("IndentHandler", "Opens a dialog to save the current indenter configuration to a file.", 0, QApplication::UnicodeUTF8)); + _actionSaveIndenterConfigFile->setShortcut(QApplication::translate("IndentHandler", "Alt+S", 0, QApplication::UnicodeUTF8)); + + _actionCreateShellScript->setText(QApplication::translate("IndentHandler", "Create Indenter Call Shell Script", 0, QApplication::UnicodeUTF8)); + _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)); + _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)); + + _actionResetIndenterParameters->setText(QApplication::translate("IndentHandler", "Reset indenter parameters", 0, QApplication::UnicodeUTF8)); + _actionResetIndenterParameters->setToolTip(QApplication::translate("IndentHandler", "Resets all indenter parameters to the default values.", 0, QApplication::UnicodeUTF8)); + _actionResetIndenterParameters->setStatusTip(QApplication::translate("IndentHandler", "Resets all indenter parameters to the default values.", 0, QApplication::UnicodeUTF8)); +} + + +/*! + \brief Returns the name of the currently selected indenter. + */ +QString IndentHandler::getCurrentIndenterName() { + QString currentIndenterName = _indenterSelectionCombobox->currentText(); + + // Remove the supported programming languages from indenters name, which are set in braces. + if ( currentIndenterName.indexOf("(") > 0 ) { + // Using index-1 to also leave out the blank before the brace. + currentIndenterName = currentIndenterName.left( currentIndenterName.indexOf("(")-1 ); + } + + return currentIndenterName; +} + + +/*! + \brief Shows a file open dialog to open an existing config file for the currently selected indenter. + + If the file was successfully opened the indent handler is called to load the settings and update itself. +*/ +void IndentHandler::openConfigFileDialog() { + QString configFilePath; + + configFilePath = QFileDialog::getOpenFileName( NULL, tr("Choose indenter config file"), getIndenterCfgFile(), "All files (*.*)" ); + + if (configFilePath != "") { + // If the config file was loaded successfully, inform any who is interested about it. + if ( loadConfigFile(configFilePath) ) + handleChangedIndenterSettings(); + } +} + + +/*! + \brief Calls the indenter config file save as dialog to save the config file under a chosen name. + + If the file already exists and it should be overwritten, a warning is shown before. +*/ +void IndentHandler::saveasIndentCfgFileDialog() { + QString fileExtensions = tr("All files")+" (*.*)"; + + //QString openedSourceFileContent = openFileDialog( tr("Choose source code file"), "./", fileExtensions ); + QString fileName = QFileDialog::getSaveFileName( this, tr("Save indent config file"), getIndenterCfgFile(), fileExtensions); + + if (fileName != "") { + QFile::remove(fileName); + QFile outCfgFile(fileName); + outCfgFile.open( QFile::ReadWrite | QFile::Text ); + outCfgFile.write( getParameterString().toAscii() ); + outCfgFile.close(); + } +} + + +/*! + \brief Invokes the indenter to create a shell script. + + Lets the indenter create a shell script for calling the indenter out of any + other application and open a save dialog for saving the shell script. +*/ +void IndentHandler::createIndenterCallShellScript() { + QString shellScriptExtension; +#if defined(Q_OS_WIN32) + shellScriptExtension = "bat"; +#else + shellScriptExtension = "sh"; +#endif + + QString fileExtensions = tr("Shell Script")+" (*."+shellScriptExtension+");;"+tr("All files")+" (*.*)"; + + QString currentIndenterName = getCurrentIndenterName(); + currentIndenterName = currentIndenterName.replace(" ", "_"); + + QString shellScriptFileName = QFileDialog::getSaveFileName( this, tr("Save shell script"), "call_"+currentIndenterName+"."+shellScriptExtension, fileExtensions); + + // Saving has been canceled if the filename is empty + if ( shellScriptFileName.isEmpty() ) { + return; + } + + // Delete any old file, write the new contents and set executable permissions. + QFile::remove(shellScriptFileName); + QFile outSrcFile(shellScriptFileName); + if ( outSrcFile.open( QFile::ReadWrite | QFile::Text ) ) { + QString shellScriptConfigFilename = QFileInfo(shellScriptFileName).baseName() + "." + QFileInfo(_globalConfigFilename).suffix(); + + // Get the content of the shell/batch script. + QString indenterCallShellScript = generateShellScript(shellScriptConfigFilename); + + // Replace placeholder for script name in script template. + indenterCallShellScript = indenterCallShellScript.replace( "__INDENTERCALLSTRINGSCRIPTNAME__", QFileInfo(shellScriptFileName).fileName() ); + + outSrcFile.write( indenterCallShellScript.toAscii() ); +#if !defined(Q_OS_WIN32) + // For none Windows systems set the files executable flag + outSrcFile.setPermissions( outSrcFile.permissions() | QFile::ExeOwner | QFile::ExeUser| QFile::ExeGroup ); +#endif + outSrcFile.close(); + + // Save the indenter config file to the same directory, where the shell srcipt was saved to, + // because the script will reference it there via "./". + if ( !_globalConfigFilename.isEmpty() ) { + saveConfigFile( QFileInfo(shellScriptFileName).path() + "/" + shellScriptConfigFilename, getParameterString() ); + } + } +} + + +/*! + \brief Resets all parameters to the indenters default values as they are specified in the uigui ini file + but asks the user whether to do it really. + */ +void IndentHandler::resetIndenterParameter() { + 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 ); + if ( messageBoxAnswer == QMessageBox::Yes ) { + resetToDefaultValues(); + } +} + + +/*! + \brief Catch some events and let some other be handled by the super class. + + Is needed for use as Notepad++ plugin. + */ +bool IndentHandler::event( QEvent *event ) { + if ( event->type() == QEvent::WindowActivate ) { + event->accept(); + return true; + } + else if ( event->type() == QEvent::WindowDeactivate ) { + event->accept(); + return true; + } + else { + event->ignore(); + return QWidget::event(event); + } +} + + +/*! + \brief Sets the function pointer \a _parameterChangedCallback to the given callback + function \a paramChangedCallback. + + Is needed for use as Notepad++ plugin. + */ +void IndentHandler::setParameterChangedCallback( void(*paramChangedCallback)(void) ) { + _parameterChangedCallback = paramChangedCallback; +} + + +/*! + \brief Emits the \a indenterSettingsChanged signal and if set executes the \a _parameterChangedCallback function. + + Is needed for use as Notepad++ plugin. + */ +void IndentHandler::handleChangedIndenterSettings() { + emit( indenterSettingsChanged() ); + + if ( _parameterChangedCallback != NULL ) { + _parameterChangedCallback(); + } +} + + +/*! + \brief Sets a callback function that shall be called, when the this indenter parameter window gets closed. + + Is needed for use as Notepad++ plugin. + */ +void IndentHandler::setWindowClosedCallback( void(*winClosedCallback)(void) ) { + _windowClosedCallback = winClosedCallback; +} + + +/*! + \brief Is called on this indenter parameter window close and if set calls the function \a _windowClosedCallback. + + Is needed for use as Notepad++ plugin. + */ +void IndentHandler::closeEvent(QCloseEvent *event) { + if ( _windowClosedCallback != NULL ) { + _windowClosedCallback(); + } + event->accept(); +} + + +/*! + \brief Returns the id (list index) of the currently selected indenter. + */ +int IndentHandler::getIndenterId() { + return _indenterSelectionCombobox->currentIndex(); +} + + +void IndentHandler::updateDrawing() { +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + if ( isVisible() ) { + QRect savedGeometry = geometry(); + setGeometry( savedGeometry.adjusted(0,0,0,1) ); + repaint(); + setGeometry( savedGeometry ); + } +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS +} + +void IndentHandler::wheelEvent( QWheelEvent *event ) { + UNUSED_PARAMETER_WARNING_AVOID(event); +#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS + QWidget::wheelEvent( event ); + updateDrawing(); +#endif // UNIVERSALINDENTGUI_NPP_EXPORTS +} + + +/*! + \brief Converts characters < > and & in the \a text to HTML codes < > and &. + */ +//TODO: This function should go into a string helper/tool class/file. +QString IndentHandler::encodeToHTML(const QString &text) { + QString htmlText = text; + htmlText.replace("&", "&"); + htmlText.replace("<", "<"); + htmlText.replace(">", ">"); + htmlText.replace('"', """); + htmlText.replace("'", "'"); + htmlText.replace("^", "ˆ"); + htmlText.replace("~", "˜"); + htmlText.replace("€", "€"); + htmlText.replace("©", "©"); + return htmlText; +} diff --git a/src/IndentHandler.h b/src/IndentHandler.h new file mode 100755 index 0000000..3ccb553 --- /dev/null +++ b/src/IndentHandler.h @@ -0,0 +1,183 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef INDENTHANDLER_H +#define INDENTHANDLER_H + +#include <QWidget> + +class UiGuiErrorMessage; +class UiGuiIniFileParser; + +class QMenu; +class QVBoxLayout; +class QLabel; +class QSpinBox; +class QComboBox; +class QCheckBox; +class QLineEdit; +class QToolButton; +class QToolBox; + + +class IndentHandler : public QWidget +{ + Q_OBJECT + +public: + IndentHandler(int indenterID, QWidget *mainWindow = NULL, QWidget *parent = NULL); + ~IndentHandler(); + + QString generateShellScript(const QString &configFilename); + QString callIndenter(QString sourceCode, QString inputFileExtension); + bool loadConfigFile(QString filePathName); + void resetToDefaultValues(); + QStringList getAvailableIndenters(); + QString getPossibleIndenterFileExtensions(); + QString getParameterString(); + QString getIndenterCfgFile(); + QString getManual(); + void retranslateUi(); + QString getCurrentIndenterName(); + QMenu* getIndenterMenu(); + QList<QAction*> getIndenterMenuActions(); + void contextMenuEvent( QContextMenuEvent *event ); + void setParameterChangedCallback( void(*paramChangedCallback)(void) ); + void setWindowClosedCallback( void(*winClosedCallback)(void) ); + int getIndenterId(); + +signals: + void indenterSettingsChanged(); + void selectedIndenterIndexChanged(int index); + +protected: + bool event( QEvent *event ); + void closeEvent(QCloseEvent *event); + void wheelEvent( QWheelEvent *event ); + +private slots: + void setIndenter(int indenterID); + void showIndenterManual(); + void openConfigFileDialog(); + void saveasIndentCfgFileDialog(); + void createIndenterCallShellScript(); + void resetIndenterParameter(); + void handleChangedIndenterSettings(); + void updateDrawing(); + +private: + QString callExecutableIndenter(QString sourceCode, QString inputFileExtension); + QString callJavaScriptIndenter(QString sourceCode); + void saveConfigFile(QString filePathName, QString parameterString); + void readIndentIniFile(QString iniFilePath); + bool createIndenterCallString(); + void initIndenterMenu(); + + //! Holds a reference to all created pages of the parameter categories toolbox and the pages boxlayout + struct IndenterParameterCategoryPage { + QWidget *widget; + QVBoxLayout *vboxLayout; + }; + QVector<IndenterParameterCategoryPage> _indenterParameterCategoryPages; + + //! Holds a reference to all checkboxes needed for boolean parameter setting and the parameters name + struct ParamBoolean { + QString paramName; + QString trueString; + QString falseString; + QCheckBox *checkBox; + }; + QVector<ParamBoolean> _paramBooleans; + + //! Holds a reference to all line edits needed for parameter setting and the parameters name + struct ParamString { + QString paramName; + QString paramCallName; + QCheckBox *valueEnabledChkBox; + QLineEdit *lineEdit; + QLabel *label; + }; + QVector<ParamString> _paramStrings; + + //! Hold a reference to all spin boxes needed for parameter setting and the parameters name + struct ParamNumeric { + QString paramName; + QString paramCallName; + QCheckBox *valueEnabledChkBox; + QSpinBox *spinBox; + QLabel *label; + }; + QVector<ParamNumeric> _paramNumerics; + + //! Hold a reference to all combo boxes needed for parameter setting and the parameters name + struct ParamMultiple { + QString paramName; + QString paramCallName; + QCheckBox *valueEnabledChkBox; + QComboBox *comboBox; + QStringList choicesStrings; + QStringList choicesStringsReadable; + }; + QVector<ParamMultiple> _paramMultiples; + + QComboBox *_indenterSelectionCombobox; + QToolButton *_indenterParameterHelpButton; + //! Vertical layout box, into which the toolbox will be added + QVBoxLayout *_toolBoxContainerLayout; + QToolBox *_indenterParameterCategoriesToolBox; + UiGuiIniFileParser *_indenterSettings; + QStringList _indenterParameters; + //! The indenters name in a descriptive form + QString _indenterName; + //! The indenters file name (w/o extension), that is being called + QString _indenterFileName; + QString _indenterDirctoryStr; + QString _tempDirctoryStr; + QString _settingsDirctoryStr; + QStringList _indenterIniFileList; + QString _parameterOrder; + QString _globalConfigFilename; + QString _cfgFileParameterEnding; + QString _inputFileParameter; + QString _inputFileName; + QString _outputFileParameter; + QString _outputFileName; + QString _fileTypes; + QString _useCfgFileParameter; + QString _indenterShowHelpParameter; + QWidget *_mainWindow; + UiGuiErrorMessage *_errorMessageDialog; + QString _indenterExecutableCallString; + QString _indenterExecutableSuffix; + + QMenu *_menuIndenter; + QAction *_actionLoadIndenterConfigFile; + QAction *_actionSaveIndenterConfigFile; + QAction *_actionCreateShellScript; + QAction *_actionResetIndenterParameters; + //! Needed for the NPP plugin. + void(*_parameterChangedCallback)(void); + //! Needed for the NPP plugin. + void(*_windowClosedCallback)(void); + + //TODO: This function should go into a string helper/tool class/file. + QString encodeToHTML(const QString &text); +}; + +#endif // INDENTHANDLER_H diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp new file mode 100755 index 0000000..f7b6185 --- /dev/null +++ b/src/MainWindow.cpp @@ -0,0 +1,1428 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "MainWindow.h" +#include "ui_MainWindow.h" + +#include "UiGuiVersion.h" +#include "debugging/TSLogger.h" +#include "SettingsPaths.h" + +#include "ui_ToolBarWidget.h" +#include "AboutDialog.h" +#include "AboutDialogGraphicsView.h" +#include "UiGuiSettings.h" +#include "UiGuiSettingsDialog.h" +#include "UiGuiHighlighter.h" +#include "IndentHandler.h" +#include "UpdateCheckDialog.h" + +#include <QWidget> +#include <QLabel> +#include <QString> +#include <QScrollBar> +#include <QTextCursor> +#include <QFileDialog> +#include <QTextStream> +#include <QTextDocument> +#include <QPrinter> +#include <QPrintDialog> +#include <QCloseEvent> +#include <QHelpEvent> +#include <QToolTip> +#include <QTranslator> +#include <QLocale> +#include <QTextCodec> +#include <QDate> +#include <QUrl> +#include <QMessageBox> +#include <QtDebug> + +#include <Qsci/qsciscintilla.h> +#include <Qsci/qsciprinter.h> + +using namespace tschweitzer; + +//! \defgroup grp_MainWindow All concerning main window functionality. + +/*! + \class MainWindow + \ingroup grp_MainWindow + \brief Is the main window of UniversalIndentGUI + + The MainWindow class is responsible for generating and displaying most of the gui elements. + Its look is set in the file "mainwindow.ui". An object for the indent handler is generated here + and user actions are being controlled. Is responsible for file open dialogs and indenter selection. + */ + +/*! + \brief Constructs the main window. + */ +MainWindow::MainWindow(QString file2OpenOnStart, QWidget *parent) : QMainWindow(parent) + , _mainWindowForm(NULL) + , _qSciSourceCodeEditor(NULL) + , _settings(NULL) + , _highlighter(NULL) + , _textEditVScrollBar(NULL) + , _aboutDialog(NULL) + , _aboutDialogGraphicsView(NULL) + , _settingsDialog(NULL) + , _encodingActionGroup(NULL) + , _saveEncodedActionGroup(NULL) + , _highlighterActionGroup(NULL) + , _uiGuiTranslator(NULL) + , _qTTranslator(NULL) + , _toolBarWidget(NULL) + , _indentHandler(NULL) + , _updateCheckDialog(NULL) + , _textEditLineColumnInfoLabel(NULL) +{ + // Init of some variables. + _sourceCodeChanged = false; + _scrollPositionChanged = false; + + // Create the _settings object, which loads all UiGui settings from a file. + _settings = UiGuiSettings::getInstance(); + + // Initialize the language of the application. + initApplicationLanguage(); + + // Creates the main window and initializes it. + initMainWindow(); + + // Create toolbar and insert it into the main window. + initToolBar(); + + // Create the text edit component using the QScintilla widget. + initTextEditor(); + + // Create and init the syntax highlighter. + initSyntaxHighlighter(); + + // Create and init the indenter. + initIndenter(); + + // Create some menus. + createEncodingMenu(); + createHighlighterMenu(); + + + // Generate about dialog box + _aboutDialog = new AboutDialog(this, Qt::SplashScreen); + _aboutDialogGraphicsView = new AboutDialogGraphicsView(_aboutDialog, this); + connect( _toolBarWidget->pbAbout, SIGNAL(clicked()), this, SLOT(showAboutDialog()) ); + connect( _mainWindowForm->actionAbout_UniversalIndentGUI, SIGNAL(triggered()), this, SLOT(showAboutDialog()) ); + + // Generate settings dialog box + _settingsDialog = new UiGuiSettingsDialog(this, _settings); + connect( _mainWindowForm->actionShowSettings, SIGNAL(triggered()), _settingsDialog, SLOT(showDialog()) ); + + // If a file that should be opened on start has been handed over to the constructor exists, load it + if ( QFile::exists(file2OpenOnStart) ) { + openSourceFileDialog(file2OpenOnStart); + } + // Otherwise load the last opened file, if this is enabled in the settings. + else { + loadLastOpenedFile(); + } + + updateSourceView(); + + // Check if a newer version is available but only if the setting for that is enabled and today not already a check has been done. + if ( _settings->getValueByName("CheckForUpdate").toBool() && QDate::currentDate() != _settings->getValueByName("LastUpdateCheck").toDate() ) { + _updateCheckDialog->checkForUpdate(); + } + + // Enable accept dropping of files. + setAcceptDrops(true); +} + + +/*! + \brief Initializes the main window by creating the main gui and make some _settings. + */ +void MainWindow::initMainWindow() { + // Generate gui as it is build in the file "mainwindow.ui" + _mainWindowForm = new Ui::MainWindowUi(); + _mainWindowForm->setupUi(this); + + // Handle last opened window size + // ------------------------------ + bool maximized = _settings->getValueByName("maximized").toBool(); + QPoint pos = _settings->getValueByName("position").toPoint(); + QSize size = _settings->getValueByName("size").toSize(); + resize(size); + move(pos); + if ( maximized ) { + showMaximized(); + } +#ifndef Q_OS_MAC // On Mac restoring the window state causes the screenshot no longer to work. + restoreState( _settings->getValueByName("MainWindowState").toByteArray() ); +#endif + + // Handle if first run of this version + // ----------------------------------- + QString readVersion = _settings->getValueByName("version").toString(); + // If version strings are not equal set first run true. + if ( readVersion != PROGRAM_VERSION_STRING ) { + _isFirstRunOfThisVersion = true; + } + else { + _isFirstRunOfThisVersion = false; + } + + // Get last selected file encoding + // ------------------------------- + _currentEncoding = _settings->getValueByName("encoding").toString(); + + _updateCheckDialog = new UpdateCheckDialog(_settings, this); + + // Register the load last file setting in the menu to the _settings object. + _settings->registerObjectProperty(_mainWindowForm->loadLastOpenedFileOnStartupAction, "checked", "loadLastSourceCodeFileOnStartup"); + + // Tell the QScintilla editor if it has to show white space. + connect( _mainWindowForm->whiteSpaceIsVisibleAction, SIGNAL(toggled(bool)), this, SLOT(setWhiteSpaceVisibility(bool)) ); + // Register the white space setting in the menu to the _settings object. + _settings->registerObjectProperty(_mainWindowForm->whiteSpaceIsVisibleAction, "checked", "whiteSpaceIsVisible"); + + // Connect the remaining menu items. + connect( _mainWindowForm->actionOpen_Source_File, SIGNAL(triggered()), this, SLOT(openSourceFileDialog()) ); + connect( _mainWindowForm->actionSave_Source_File_As, SIGNAL(triggered()), this, SLOT(saveasSourceFileDialog()) ); + connect( _mainWindowForm->actionSave_Source_File, SIGNAL(triggered()), this, SLOT(saveSourceFile()) ); + connect( _mainWindowForm->actionExportPDF, SIGNAL(triggered()), this, SLOT(exportToPDF()) ); + connect( _mainWindowForm->actionExportHTML, SIGNAL(triggered()), this, SLOT(exportToHTML()) ); + connect( _mainWindowForm->actionCheck_for_update, SIGNAL(triggered()), _updateCheckDialog, SLOT(checkForUpdateAndShowDialog()) ); + connect( _mainWindowForm->actionShowLog, SIGNAL(triggered()), debugging::TSLogger::getInstance(), SLOT(show()) ); + + // Init the menu for selecting one of the recently opened files. + updateRecentlyOpenedList(); + connect( _mainWindowForm->menuRecently_Opened_Files, SIGNAL(triggered(QAction*)), this, SLOT(openFileFromRecentlyOpenedList(QAction*)) ); + //connect( _settings, SIGNAL(recentlyOpenedListSize(int)), this, SLOT(updateRecentlyOpenedList()) ); + _settings->registerObjectSlot(this, "updateRecentlyOpenedList()", "recentlyOpenedListSize"); +} + + +/*! + \brief Creates and inits the tool bar. It is added to the main window. + */ +void MainWindow::initToolBar() { + // Create the tool bar and add it to the main window. + _toolBarWidget = new Ui::ToolBarWidget(); + QWidget* helpWidget = new QWidget(); + _toolBarWidget->setupUi(helpWidget); + _mainWindowForm->toolBar->addWidget(helpWidget); + _mainWindowForm->toolBar->setAllowedAreas( Qt::TopToolBarArea | Qt::BottomToolBarArea ); + + // Connect the tool bar widgets to their functions. + _settings->registerObjectProperty(_toolBarWidget->enableSyntaxHighlightningCheckBox, "checked", "SyntaxHighlightingEnabled"); + _toolBarWidget->enableSyntaxHighlightningCheckBox->hide(); + connect( _toolBarWidget->pbOpen_Source_File, SIGNAL(clicked()), this, SLOT(openSourceFileDialog()) ); + connect( _toolBarWidget->pbExit, SIGNAL(clicked()), this, SLOT(close())); + connect( _toolBarWidget->cbLivePreview, SIGNAL(toggled(bool)), this, SLOT(previewTurnedOnOff(bool)) ); + connect( _toolBarWidget->cbLivePreview, SIGNAL(toggled(bool)), _mainWindowForm->actionLive_Indent_Preview, SLOT(setChecked(bool)) ); + connect( _mainWindowForm->actionLive_Indent_Preview, SIGNAL(toggled(bool)), _toolBarWidget->cbLivePreview, SLOT(setChecked(bool)) ); +} + + +/*! + \brief Create and initialize the text editor component. It uses the QScintilla widget. + */ +void MainWindow::initTextEditor() { + // Create the QScintilla widget and add it to the layout. + qDebug() << "Trying to load QScintilla library. If anything fails during loading, it might be possible that" + << " the debug and release version of QScintilla are mixed or the library cannot be found at all."; + // Try and catch doesn't seem to catch the runtime error when starting UiGUI release with QScintilla debug lib and the other way around. + try { + _qSciSourceCodeEditor = new QsciScintilla(this); + } + catch (...) { + QMessageBox::critical(this, "Error creating QScintilla text editor component!", + "During trying to create the text editor component, that is based on QScintilla, an error occurred. Please make sure that you have installed QScintilla and not mixed release and debug versions." ); + exit(1); + } + _mainWindowForm->hboxLayout1->addWidget(_qSciSourceCodeEditor); + + // Make some _settings for the QScintilla widget. + _qSciSourceCodeEditor->setUtf8(true); + _qSciSourceCodeEditor->setMarginLineNumbers(1, true); + _qSciSourceCodeEditor->setMarginWidth(1, QString("10000") ); + _qSciSourceCodeEditor->setBraceMatching(_qSciSourceCodeEditor->SloppyBraceMatch); + _qSciSourceCodeEditor->setMatchedBraceForegroundColor( QColor("red") ); + _qSciSourceCodeEditor->setFolding(QsciScintilla::BoxedTreeFoldStyle); + _qSciSourceCodeEditor->setAutoCompletionSource(QsciScintilla::AcsAll); + _qSciSourceCodeEditor->setAutoCompletionThreshold(3); + + // Handle if white space is set to be visible + bool whiteSpaceIsVisible = _settings->getValueByName("whiteSpaceIsVisible").toBool(); + setWhiteSpaceVisibility( whiteSpaceIsVisible ); + + // Handle the width of tabs in spaces + int tabWidth = _settings->getValueByName("tabWidth").toInt(); + _qSciSourceCodeEditor->setTabWidth(tabWidth); + + // Remember a pointer to the scrollbar of the QScintilla widget used to keep + // on the same line as before when turning preview on/off. + _textEditVScrollBar = _qSciSourceCodeEditor->verticalScrollBar(); + + // Add a column row indicator to the status bar. + _textEditLineColumnInfoLabel = new QLabel( tr("Line %1, Column %2").arg(1).arg(1) ); + _mainWindowForm->statusbar->addPermanentWidget(_textEditLineColumnInfoLabel); + connect( _qSciSourceCodeEditor, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(setStatusBarCursorPosInfo(int, int)) ); + + // Connect the text editor to dependent functions. + connect( _qSciSourceCodeEditor, SIGNAL(textChanged()), this, SLOT(sourceCodeChangedHelperSlot()) ); + connect( _qSciSourceCodeEditor, SIGNAL(linesChanged()), this, SLOT(numberOfLinesChanged()) ); + //connect( _settings, SIGNAL(tabWidth(int)), _qSciSourceCodeEditor, SLOT(setTabWidth(int)) ); + _settings->registerObjectSlot(_qSciSourceCodeEditor, "setTabWidth(int)", "tabWidth"); + _qSciSourceCodeEditor->setTabWidth( _settings->getValueByName("tabWidth").toInt() ); +} + + +/*! + \brief Create and init the syntax _highlighter and set it to use the QScintilla edit component. + */ +void MainWindow::initSyntaxHighlighter() { + // Create the _highlighter. + _highlighter = new UiGuiHighlighter(_qSciSourceCodeEditor); + + // Connect the syntax highlighting setting in the menu to the turnHighlightOnOff function. + connect( _mainWindowForm->enableSyntaxHighlightingAction, SIGNAL(toggled(bool)), this, SLOT(turnHighlightOnOff(bool)) ); + + // Register the syntax highlighting setting in the menu to the _settings object. + _settings->registerObjectProperty(_mainWindowForm->enableSyntaxHighlightingAction, "checked", "SyntaxHighlightingEnabled"); +} + + +/*! + \brief Initializes the language of UniversalIndentGUI. + + If the program language is defined in the _settings, the corresponding language + file will be loaded and set for the application. If not set there, the system + default language will be set, if a translation file for that language exists. + Returns true, if the translation file could be loaded. Otherwise it returns + false and uses the default language, which is English. + */ +bool MainWindow::initApplicationLanguage() { + QString languageShort; + + // Get the language _settings from the _settings object. + int languageIndex = _settings->getValueByName("language").toInt(); + + // If no language was set, indicated by a negative index, use the system language. + if ( languageIndex < 0 ) { + languageShort = QLocale::system().name(); + + // Chinese and Japanese language consist of country and language code. + // For all others the language code will be cut off. + if ( languageShort.left(2) != "zh" && languageShort.left(2) != "ja" ) { + languageShort = languageShort.left(2); + } + + // If no translation file for the systems local language exist, fall back to English. + if ( _settings->getAvailableTranslations().indexOf(languageShort) < 0 ) { + languageShort = "en"; + } + + // Set the language setting to the new language. + _settings->setValueByName("language", _settings->getAvailableTranslations().indexOf(languageShort) ); + } + // If a language was defined in the _settings, get this language mnemonic. + else { + languageShort = _settings->getAvailableTranslations().at(languageIndex); + } + + // Load the Qt own translation file and set it for the application. + _qTTranslator = new QTranslator(); + bool translationFileLoaded; + translationFileLoaded = _qTTranslator->load( SettingsPaths::getGlobalFilesPath() + "/translations/qt_" + languageShort ); + if ( translationFileLoaded ) { + qApp->installTranslator(_qTTranslator); + } + + // Load the uigui translation file and set it for the application. + _uiGuiTranslator = new QTranslator(); + translationFileLoaded = _uiGuiTranslator->load( SettingsPaths::getGlobalFilesPath() + "/translations/universalindent_" + languageShort ); + if ( translationFileLoaded ) { + qApp->installTranslator(_uiGuiTranslator); + } + + //connect( _settings, SIGNAL(language(int)), this, SLOT(languageChanged(int)) ); + _settings->registerObjectSlot(this, "languageChanged(int)", "language"); + + return translationFileLoaded; +} + + +/*! + \brief Creates and initializes the indenter. + */ +void MainWindow::initIndenter() { + // Get Id of last selected indenter. + _currentIndenterID = _settings->getValueByName("selectedIndenter").toInt(); + + // Create the indenter widget with the ID and add it to the layout. + _indentHandler = new IndentHandler(_currentIndenterID, this, _mainWindowForm->centralwidget); + _mainWindowForm->vboxLayout->addWidget(_indentHandler); + + // If _settings for the indenter have changed, let the main window know aboud it. + connect(_indentHandler, SIGNAL(indenterSettingsChanged()), this, SLOT(indentSettingsChangedSlot())); + + // Set this true, so the indenter is called at first program start + _indentSettingsChanged = true; + _previewToggled = true; + + // Handle if indenter parameter tool tips are enabled + _settings->registerObjectProperty(_mainWindowForm->indenterParameterTooltipsEnabledAction, "checked", "indenterParameterTooltipsEnabled"); + + // Add the indenters context menu to the mainwindows menu. + _mainWindowForm->menuIndenter->addActions( _indentHandler->getIndenterMenuActions() ); +} + + +/*! + \brief Tries to load the by \a filePath defined file and returns its content as QString. + + If the file could not be loaded a error dialog will be shown. + */ +QString MainWindow::loadFile(QString filePath) { + QFile inSrcFile(filePath); + QString fileContent = ""; + + if ( !inSrcFile.open(QFile::ReadOnly | QFile::Text) ) { + QMessageBox::warning(NULL, tr("Error opening file"), tr("Cannot read the file ")+"\""+filePath+"\"." ); + } + else { + QTextStream inSrcStrm(&inSrcFile); + QApplication::setOverrideCursor(Qt::WaitCursor); + inSrcStrm.setCodec( QTextCodec::codecForName(_currentEncoding.toAscii()) ); + fileContent = inSrcStrm.readAll(); + QApplication::restoreOverrideCursor(); + inSrcFile.close(); + + QFileInfo fileInfo(filePath); + _currentSourceFileExtension = fileInfo.suffix(); + int indexOfHighlighter = _highlighter->setLexerForExtension( _currentSourceFileExtension ); + _highlighterActionGroup->actions().at(indexOfHighlighter)->setChecked(true); + } + return fileContent; +} + + +/*! + \brief Calls the source file open dialog to load a source file for the formatting preview. + + If the file was successfully loaded the indenter will be called to generate the formatted source code. + */ +void MainWindow::openSourceFileDialog(QString fileName) { + // If the source code file is changed and the shown dialog for saving the file + // is canceled, also stop opening another source file. + if ( !maybeSave() ) { + return; + } + QString openedSourceFileContent = ""; + QString fileExtensions = tr("Supported by indenter")+" ("+_indentHandler->getPossibleIndenterFileExtensions()+ + ");;"+tr("All files")+" (*.*)"; + + //QString openedSourceFileContent = openFileDialog( tr("Choose source code file"), "./", fileExtensions ); + if ( fileName.isEmpty() ) { + fileName = QFileDialog::getOpenFileName( this, tr("Choose source code file"), _currentSourceFile, fileExtensions); + } + + if (fileName != "") { + _currentSourceFile = fileName; + QFileInfo fileInfo(fileName); + _currentSourceFileExtension = fileInfo.suffix(); + + openedSourceFileContent = loadFile(fileName); + _sourceFileContent = openedSourceFileContent; + if ( _toolBarWidget->cbLivePreview->isChecked() ) { + callIndenter(); + } + _sourceCodeChanged = true; + _previewToggled = true; + updateSourceView(); + updateWindowTitle(); + updateRecentlyOpenedList(); + _textEditLastScrollPos = 0; + _textEditVScrollBar->setValue( _textEditLastScrollPos ); + + _savedSourceContent = openedSourceFileContent; + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + } +} + + +/*! + \brief Calls the source file save as dialog to save a source file under a chosen name. + + If the file already exists and it should be overwritten, a warning is shown before. + */ +bool MainWindow::saveasSourceFileDialog(QAction *chosenEncodingAction) { + QString encoding; + QString fileExtensions = tr("Supported by indenter")+" ("+_indentHandler->getPossibleIndenterFileExtensions()+ + ");;"+tr("All files")+" (*.*)"; + + //QString openedSourceFileContent = openFileDialog( tr("Choose source code file"), "./", fileExtensions ); + QString fileName = QFileDialog::getSaveFileName( this, tr("Save source code file"), _currentSourceFile, fileExtensions); + + // Saving has been canceled if the filename is empty + if ( fileName.isEmpty() ) { + return false; + } + + _savedSourceContent = _qSciSourceCodeEditor->text(); + + _currentSourceFile = fileName; + QFile::remove(fileName); + QFile outSrcFile(fileName); + outSrcFile.open( QFile::ReadWrite | QFile::Text ); + + // Get current encoding. + if ( chosenEncodingAction != NULL ) { + encoding = chosenEncodingAction->text(); + } + else { + encoding = _encodingActionGroup->checkedAction()->text(); + } + QTextStream outSrcStrm(&outSrcFile); + outSrcStrm.setCodec( QTextCodec::codecForName(encoding.toAscii()) ); + outSrcStrm << _savedSourceContent; + outSrcFile.close(); + + QFileInfo fileInfo(fileName); + _currentSourceFileExtension = fileInfo.suffix(); + + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + + updateWindowTitle(); + return true; +} + + +/*! + \brief Saves the currently shown source code to the last save or opened source file. + + If no source file has been opened, because only the static example has been loaded, + the save as file dialog will be shown. + */ +bool MainWindow::saveSourceFile() { + if ( _currentSourceFile.isEmpty() ) { + return saveasSourceFileDialog(); + } + else { + QFile::remove(_currentSourceFile); + QFile outSrcFile(_currentSourceFile); + _savedSourceContent = _qSciSourceCodeEditor->text(); + outSrcFile.open( QFile::ReadWrite | QFile::Text ); + + // Get current encoding. + QString _currentEncoding = _encodingActionGroup->checkedAction()->text(); + QTextStream outSrcStrm(&outSrcFile); + outSrcStrm.setCodec( QTextCodec::codecForName(_currentEncoding.toAscii()) ); + outSrcStrm << _savedSourceContent; + outSrcFile.close(); + + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + } + return true; +} + + +/*! + \brief Shows a file open dialog. + + Shows a file open dialog with the title \a dialogHeaderStr starting in the directory \a startPath + and with a file mask defined by \a fileMaskStr. Returns the contents of the file as QString. + */ +QString MainWindow::openFileDialog(QString dialogHeaderStr, QString startPath, QString fileMaskStr) { + QString fileContent = ""; + + QString fileName = QFileDialog::getOpenFileName( NULL, dialogHeaderStr, startPath, fileMaskStr); + + if (fileName != "") { + fileContent = loadFile(fileName); + } + + return fileContent; +} + + +/*! + \brief Updates the displaying of the source code. + + Updates the text edit field, which is showing the loaded, and if preview is enabled formatted, source code. + Reassigns the line numbers and in case of switch between preview and none preview keeps the text field + at the same line number. + */ +void MainWindow::updateSourceView() { + _textEditLastScrollPos = _textEditVScrollBar->value(); + + if ( _toolBarWidget->cbLivePreview->isChecked() ) { + _sourceViewContent = _sourceFormattedContent; + } + else { + _sourceViewContent = _sourceFileContent; + } + + if (_previewToggled) { + disconnect( _qSciSourceCodeEditor, SIGNAL(textChanged ()), this, SLOT(sourceCodeChangedHelperSlot()) ); + bool textIsModified = isWindowModified(); + _qSciSourceCodeEditor->setText(_sourceViewContent); + setWindowModified(textIsModified); + _previewToggled = false; + connect( _qSciSourceCodeEditor, SIGNAL(textChanged ()), this, SLOT(sourceCodeChangedHelperSlot()) ); + } + + _textEditVScrollBar->setValue( _textEditLastScrollPos ); +} + + +/*! + \brief Calls the selected indenter with the currently loaded source code to retrieve the formatted source code. + + The original loaded source code file will not be changed. + */ +void MainWindow::callIndenter() { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + _sourceFormattedContent = _indentHandler->callIndenter(_sourceFileContent, _currentSourceFileExtension); + //updateSourceView(); + QApplication::restoreOverrideCursor(); +} + + +/*! + \brief Switches the syntax highlighting corresponding to the value \a turnOn either on or off. + */ +void MainWindow::turnHighlightOnOff(bool turnOn) { + if ( turnOn ) { + _highlighter->turnHighlightOn(); + } + else { + _highlighter->turnHighlightOff(); + } + _previewToggled = true; + updateSourceView(); +} + + +/*! + \brief Added this slot to avoid multiple calls because of changed text. + */ +void MainWindow::sourceCodeChangedHelperSlot() { + QTimer::singleShot(0, this, SLOT(sourceCodeChangedSlot())); +} + + +/*! + \brief Is emitted whenever the text inside the source view window changes. Calls the indenter + to format the changed source code. + */ +void MainWindow::sourceCodeChangedSlot() { + QChar enteredCharacter; + int cursorPos, cursorPosAbsolut, cursorLine; + QString text; + + _sourceCodeChanged = true; + if ( _scrollPositionChanged ) { + _scrollPositionChanged = false; + } + + // Get the content text of the text editor. + _sourceFileContent = _qSciSourceCodeEditor->text(); + + // Get the position of the cursor in the unindented text. + if ( _sourceFileContent.isEmpty() ) { + // Add this line feed, because AStyle has problems with a totally emtpy file. + _sourceFileContent += "\n"; + cursorPosAbsolut = 0; + cursorPos = 0; + cursorLine = 0; + enteredCharacter = _sourceFileContent.at(cursorPosAbsolut); + } + else { + _qSciSourceCodeEditor->getCursorPosition(&cursorLine, &cursorPos); + cursorPosAbsolut = _qSciSourceCodeEditor->SendScintilla(QsciScintillaBase::SCI_GETCURRENTPOS); + text = _qSciSourceCodeEditor->text(cursorLine); + if ( cursorPosAbsolut > 0 ) { + cursorPosAbsolut--; + } + if ( cursorPos > 0 ) { + cursorPos--; + } + enteredCharacter = _sourceFileContent.at(cursorPosAbsolut); + } + + // Call the indenter to reformat the text. + if ( _toolBarWidget->cbLivePreview->isChecked() ) { + callIndenter(); + _previewToggled = true; + } + + // Update the text editor. + updateSourceView(); + + if ( _toolBarWidget->cbLivePreview->isChecked() && !enteredCharacter.isNull() && enteredCharacter != 10 ) { + //const char ch = enteredCharacter.toAscii(); + + int saveCursorLine = cursorLine; + int saveCursorPos = cursorPos; + + bool charFound = false; + + // Search forward + for ( cursorLine = saveCursorLine; cursorLine-saveCursorLine < 6 && cursorLine < _qSciSourceCodeEditor->lines(); cursorLine++ ) { + text = _qSciSourceCodeEditor->text(cursorLine); + while ( cursorPos < text.count() && enteredCharacter != text.at(cursorPos)) { + cursorPos++; + } + if ( cursorPos >= text.count() ) { + cursorPos = 0; + } + else { + charFound = true; + break; + } + } + + // If foward search did not find the character, search backward + if ( !charFound ) { + text = _qSciSourceCodeEditor->text(saveCursorLine); + cursorPos = saveCursorPos; + if ( cursorPos >= text.count() ) { + cursorPos = text.count() - 1; + } + + for ( cursorLine = saveCursorLine; saveCursorLine-cursorLine < 6 && cursorLine >= 0; cursorLine-- ) { + text = _qSciSourceCodeEditor->text(cursorLine); + while ( cursorPos >= 0 && enteredCharacter != text.at(cursorPos)) { + cursorPos--; + } + if ( cursorPos < 0 ) { + cursorPos = _qSciSourceCodeEditor->lineLength(cursorLine-1) - 1; + } + else { + charFound = true; + break; + } + } + } + + // If the character was found set its new cursor position... + if ( charFound ) { + _qSciSourceCodeEditor->setCursorPosition( cursorLine, cursorPos+1 ); + } + // ...if it was not found, set the previous cursor position. + else { + _qSciSourceCodeEditor->setCursorPosition( saveCursorLine, saveCursorPos+1 ); + } + } + // set the previous cursor position. + else if ( enteredCharacter == 10 ) { + _qSciSourceCodeEditor->setCursorPosition( cursorLine, cursorPos ); + } + + + if ( _toolBarWidget->cbLivePreview->isChecked() ) { + _sourceCodeChanged = false; + } + + if ( _savedSourceContent == _qSciSourceCodeEditor->text() ) { + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + } + else { + _qSciSourceCodeEditor->setModified( true ); // Has no effect according to QScintilla docs. + setWindowModified( true ); + } + + // Could set cursor this way and use normal linear search in text instead of columns and rows. + //_qSciSourceCodeEditor->SendScintilla(QsciScintillaBase::SCI_SETCURRENTPOS, 50); + //_qSciSourceCodeEditor->SendScintilla(QsciScintillaBase::SCI_SETANCHOR, 50); +} + + +/*! + \brief This slot is called whenever one of the indenter _settings are changed. + + It calls the selected indenter if the preview is turned on. If preview + is not active a flag is set, that the _settings have changed. + */ +void MainWindow::indentSettingsChangedSlot() { + _indentSettingsChanged = true; + + int cursorLine, cursorPos; + _qSciSourceCodeEditor->getCursorPosition(&cursorLine, &cursorPos); + + if ( _toolBarWidget->cbLivePreview->isChecked() ) { + callIndenter(); + _previewToggled = true; + + updateSourceView(); + if (_sourceCodeChanged) { +/* savedCursor = _qSciSourceCodeEditor->textCursor(); + if ( cursorPos >= _qSciSourceCodeEditor->text().count() ) { + cursorPos = _qSciSourceCodeEditor->text().count() - 1; + } + savedCursor.setPosition( cursorPos ); + _qSciSourceCodeEditor->setTextCursor( savedCursor ); +*/ + _sourceCodeChanged = false; + } + _indentSettingsChanged = false; + } + else { + updateSourceView(); + } + + if ( _savedSourceContent == _qSciSourceCodeEditor->text() ) { + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + } + else { + _qSciSourceCodeEditor->setModified( true ); // Has no effect according to QScintilla docs. + setWindowModified( true ); + } +} + + +/*! + \brief This slot is called whenever the preview button is turned on or off. + + It calls the selected indenter to format the current source code if + the code has been changed since the last indenter call. + */ +void MainWindow::previewTurnedOnOff(bool turnOn) { + _previewToggled = true; + + int cursorLine, cursorPos; + _qSciSourceCodeEditor->getCursorPosition(&cursorLine, &cursorPos); + + if ( turnOn && (_indentSettingsChanged || _sourceCodeChanged) ) { + callIndenter(); + } + updateSourceView(); + if (_sourceCodeChanged) { +/* savedCursor = _qSciSourceCodeEditor->textCursor(); + if ( cursorPos >= _qSciSourceCodeEditor->text().count() ) { + cursorPos = _qSciSourceCodeEditor->text().count() - 1; + } + savedCursor.setPosition( cursorPos ); + _qSciSourceCodeEditor->setTextCursor( savedCursor ); +*/ + _sourceCodeChanged = false; + } + _indentSettingsChanged = false; + + if ( _savedSourceContent == _qSciSourceCodeEditor->text() ) { + _qSciSourceCodeEditor->setModified( false ); + setWindowModified( false ); + } + else { + _qSciSourceCodeEditor->setModified( true ); + setWindowModified( true ); + } +} + + +/*! + \brief This slot updates the main window title to show the currently opened + source code filename. + */ +void MainWindow::updateWindowTitle() { + this->setWindowTitle( "UniversalIndentGUI " + QString(PROGRAM_VERSION_STRING) + " [*]" + _currentSourceFile ); +} + + +/*! + \brief Opens a dialog to save the current source code as a PDF document. + */ +void MainWindow::exportToPDF() { + QString fileExtensions = tr("PDF Document")+" (*.pdf)"; + + QString fileName = _currentSourceFile; + QFileInfo fileInfo(fileName); + QString fileExtension = fileInfo.suffix(); + + fileName.replace( fileName.length()-fileExtension.length(), fileExtension.length(), "pdf" ); + fileName = QFileDialog::getSaveFileName( this, tr("Export source code file"), fileName, fileExtensions); + + if ( !fileName.isEmpty() ) { + QsciPrinter printer(QPrinter::HighResolution); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(fileName); + printer.printRange(_qSciSourceCodeEditor); + } +} + + +/*! + \brief Opens a dialog to save the current source code as a HTML document. + */ +void MainWindow::exportToHTML() { + QString fileExtensions = tr("HTML Document")+" (*.html)"; + + QString fileName = _currentSourceFile; + QFileInfo fileInfo(fileName); + QString fileExtension = fileInfo.suffix(); + + fileName.replace( fileName.length()-fileExtension.length(), fileExtension.length(), "html" ); + fileName = QFileDialog::getSaveFileName( this, tr("Export source code file"), fileName, fileExtensions); + + if ( !fileName.isEmpty() ) { + // Create a document from which HTML code can be generated. + QTextDocument sourceCodeDocument( _qSciSourceCodeEditor->text() ); + sourceCodeDocument.setDefaultFont( QFont("Courier", 12, QFont::Normal) ); + QString sourceCodeAsHTML = sourceCodeDocument.toHtml(); + // To ensure that empty lines are kept in the HTML code make this replacement. + sourceCodeAsHTML.replace("\"></p>", "\"><br /></p>"); + + // Write the HTML file. + QFile::remove(fileName); + QFile outSrcFile(fileName); + outSrcFile.open( QFile::ReadWrite | QFile::Text ); + outSrcFile.write( sourceCodeAsHTML.toAscii() ); + outSrcFile.close(); + } +} + + +/*! + \brief Loads the last opened file if this option is enabled in the _settings. + + If the file does not exist, the default example file is tried to be loaded. If even that + fails a very small code example is shown. + If the setting for opening the last file is disabled, the editor is empty on startup. +*/ +void MainWindow::loadLastOpenedFile() { + // Get setting for last opened source code file. + _loadLastSourceCodeFileOnStartup = _settings->getValueByName("loadLastSourceCodeFileOnStartup").toBool(); + + // Only load last source code file if set to do so + if ( _loadLastSourceCodeFileOnStartup ) { + // From the list of last opened files get the first one. + _currentSourceFile = _settings->getValueByName("lastSourceCodeFile").toString().split("|").first(); + + // If source file exist load it. + if ( QFile::exists(_currentSourceFile) ) { + QFileInfo fileInfo(_currentSourceFile); + _currentSourceFile = fileInfo.absoluteFilePath(); + _sourceFileContent = loadFile(_currentSourceFile); + } + // If the last opened source code file does not exist, try to load the default example.cpp file. + else if ( QFile::exists( SettingsPaths::getIndenterPath() + "/example.cpp" ) ) { + QFileInfo fileInfo( SettingsPaths::getIndenterPath() + "/example.cpp" ); + _currentSourceFile = fileInfo.absoluteFilePath(); + _sourceFileContent = loadFile(_currentSourceFile); + } + // If neither the example source code file exists show some small code example. + else { + _currentSourceFile = "untitled.cpp"; + _currentSourceFileExtension = "cpp"; + _sourceFileContent = "if(x==\"y\"){x=z;}"; + } + } + // if last opened source file should not be loaded make some default _settings. + else { + _currentSourceFile = "untitled.cpp"; + _currentSourceFileExtension = "cpp"; + _sourceFileContent = ""; + } + _savedSourceContent = _sourceFileContent; + + // Update the mainwindow title to show the name of the loaded source code file. + updateWindowTitle(); +} + + +/*! + \brief Saves the _settings for the main application to the file "UniversalIndentGUI.ini". + + Settings are for example last selected indenter, last loaded config file and so on. +*/ +void MainWindow::saveSettings() { + _settings->setValueByName( "encoding", _currentEncoding ); + _settings->setValueByName( "version", PROGRAM_VERSION_STRING ); + _settings->setValueByName( "maximized", isMaximized() ); + if ( !isMaximized() ) { + _settings->setValueByName( "position", pos() ); + _settings->setValueByName( "size", size() ); + } + _settings->setValueByName( "MainWindowState", saveState() ); + + // Also save the syntax highlight style for all lexers. + _highlighter->writeCurrentSettings(""); +} + + +/*! + \brief Is always called when the program is quit. Calls the saveSettings function before really quits. +*/ +void MainWindow::closeEvent( QCloseEvent *event ) { + if ( maybeSave() ) { + saveSettings(); + event->accept(); + } + else { + event->ignore(); + } +} + + +/*! + \brief This function is setup to capture tooltip events. + + All widgets that are created by the _indentHandler object and are responsible + for indenter parameters are connected with this event filter. + So depending on the _settings the tooltips can be enabled and disabled for these widgets. + */ +bool MainWindow::eventFilter(QObject *obj, QEvent *event) { + if ( event->type() == QEvent::ToolTip) { + if ( _mainWindowForm->indenterParameterTooltipsEnabledAction->isChecked() ) { + return QMainWindow::eventFilter(obj, event); + } + else { + //QToolTip::showText( QPoint(100,100) , "Test1"); + return true; + } + } + else { + // pass the event on to the parent class + return QMainWindow::eventFilter(obj, event); + } +} + + +/*! + \brief Is called at application exit and asks whether to save the source code file, if it has been changed. + */ +bool MainWindow::maybeSave() { + if ( isWindowModified() ) { + int ret = QMessageBox::warning(this, tr("Modified code"), + tr("The source code has been modified.\nDo you want to save your changes?"), + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::No, + QMessageBox::Cancel | QMessageBox::Escape); + if (ret == QMessageBox::Yes) { + return saveSourceFile(); + } + else if (ret == QMessageBox::Cancel) { + return false; + } + } + return true; +} + + +/*! + \brief This slot is called whenever a language is selected in the menu. It tries to find the + corresponding action in the languageInfoList and sets the language. + */ +void MainWindow::languageChanged(int languageIndex) { + if ( languageIndex < _settings->getAvailableTranslations().size() ) { + // Get the mnemonic of the new selected language. + QString languageShort = _settings->getAvailableTranslations().at(languageIndex); + + // Remove the old qt translation. + qApp->removeTranslator( _qTTranslator ); + + // Remove the old uigui translation. + qApp->removeTranslator( _uiGuiTranslator ); + + // Load the Qt own translation file and set it for the application. + bool translationFileLoaded; + translationFileLoaded = _qTTranslator->load( SettingsPaths::getGlobalFilesPath() + "/translations/qt_" + languageShort ); + if ( translationFileLoaded ) { + qApp->installTranslator(_qTTranslator); + } + + // Load the uigui translation file and set it for the application. + translationFileLoaded = _uiGuiTranslator->load( SettingsPaths::getGlobalFilesPath() + "/translations/universalindent_" + languageShort ); + if ( translationFileLoaded ) { + qApp->installTranslator(_uiGuiTranslator); + } + } +} + + +/*! + \brief Creates a menu entries in the file menu for opening and saving a file with different encodings. +*/ +void MainWindow::createEncodingMenu() { + QAction *encodingAction; + QString encodingName; + + _encodingsList = QStringList() << "UTF-8" << "UTF-16" << "UTF-16BE" << "UTF-16LE" + << "Apple Roman" << "Big5" << "Big5-HKSCS" << "EUC-JP" << "EUC-KR" << "GB18030-0" + << "IBM 850" << "IBM 866" << "IBM 874" << "ISO 2022-JP" << "ISO 8859-1" << "ISO 8859-13" + << "Iscii-Bng" << "JIS X 0201" << "JIS X 0208" << "KOI8-R" << "KOI8-U" << "MuleLao-1" + << "ROMAN8" << "Shift-JIS" << "TIS-620" << "TSCII" << "Windows-1250" << "WINSAMI2"; + + _encodingActionGroup = new QActionGroup(this); + _saveEncodedActionGroup = new QActionGroup(this); + + // Loop for each available encoding + foreach ( encodingName, _encodingsList ) { + // Create actions for the "reopen" menu + encodingAction = new QAction(encodingName, _encodingActionGroup); + encodingAction->setStatusTip( tr("Reopen the currently opened source code file by using the text encoding scheme ") + encodingName ); + encodingAction->setCheckable(true); + if ( encodingName == _currentEncoding ) { + encodingAction->setChecked(true); + } + + // Create actions for the "save as encoded" menu + encodingAction = new QAction(encodingName, _saveEncodedActionGroup); + encodingAction->setStatusTip( tr("Save the currently opened source code file by using the text encoding scheme ") + encodingName ); + } + + _mainWindowForm->encodingMenu->addActions( _encodingActionGroup->actions() ); + connect( _encodingActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(encodingChanged(QAction*)) ); + + _mainWindowForm->saveEncodedMenu->addActions( _saveEncodedActionGroup->actions() ); + connect( _saveEncodedActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(saveAsOtherEncoding(QAction*)) ); +} + + +/*! + \brief This slot calls the save dialog to save the current source file with another encoding. + + If the saving is successful and not aborted, the currently used encoding, visible in the + "reopen" menu, is also changed to the new encoding. +*/ +void MainWindow::saveAsOtherEncoding(QAction *chosenEncodingAction) { + bool fileWasSaved = saveasSourceFileDialog(chosenEncodingAction); + + // If the file was save with another encoding, change the selected encoding in the reopen menu. + if ( fileWasSaved ) { + foreach ( QAction *action, _encodingActionGroup->actions() ) { + if ( action->text() == chosenEncodingAction->text() ) { + action->setChecked(true); + return; + } + } + } +} + + +/*! + \brief This slot is called whenever an encoding is selected in the settings menu. +*/ +void MainWindow::encodingChanged(QAction* encodingAction) { + if ( maybeSave() ) { + QFile inSrcFile(_currentSourceFile); + QString fileContent = ""; + + if ( !inSrcFile.open(QFile::ReadOnly | QFile::Text) ) { + QMessageBox::warning(NULL, tr("Error opening file"), tr("Cannot read the file ")+"\""+_currentSourceFile+"\"." ); + } + else { + QTextStream inSrcStrm(&inSrcFile); + QApplication::setOverrideCursor(Qt::WaitCursor); + QString encodingName = encodingAction->text(); + _currentEncoding = encodingName; + inSrcStrm.setCodec( QTextCodec::codecForName(encodingName.toAscii()) ); + fileContent = inSrcStrm.readAll(); + QApplication::restoreOverrideCursor(); + inSrcFile.close(); + _qSciSourceCodeEditor->setText( fileContent ); + _qSciSourceCodeEditor->setModified(false); + } + } +} + + +/*! + \brief Creates a menu entry under the settings menu for all available text encodings. +*/ +void MainWindow::createHighlighterMenu() { + QAction *highlighterAction; + QString highlighterName; + + _highlighterActionGroup = new QActionGroup(this); + + // Loop for each known highlighter + foreach ( highlighterName, _highlighter->getAvailableHighlighters() ) { + highlighterAction = new QAction(highlighterName, _highlighterActionGroup); + highlighterAction->setStatusTip( tr("Set the syntax highlightning to ") + highlighterName ); + highlighterAction->setCheckable(true); + } + _mainWindowForm->highlighterMenu->addActions( _highlighterActionGroup->actions() ); + _mainWindowForm->menuSettings->insertMenu(_mainWindowForm->indenterParameterTooltipsEnabledAction, _mainWindowForm->highlighterMenu ); + + connect( _highlighterActionGroup, SIGNAL(triggered(QAction*)), _highlighter, SLOT(setHighlighterByAction(QAction*)) ); +} + + +/*! + \brief Is called whenever the white space visibility is being changed in the menu. + */ +void MainWindow::setWhiteSpaceVisibility(bool visible) { + if ( _qSciSourceCodeEditor != NULL ) { + if ( visible ) { + _qSciSourceCodeEditor->setWhitespaceVisibility(QsciScintilla::WsVisible); + } + else { + _qSciSourceCodeEditor->setWhitespaceVisibility(QsciScintilla::WsInvisible); + } + } +} + +/*! + \brief This slot is called whenever the number of lines in the editor changes + and adapts the margin for the displayed line numbers. +*/ +void MainWindow::numberOfLinesChanged() { + QString lineNumbers; + lineNumbers.setNum( _qSciSourceCodeEditor->lines()*10 ); + _qSciSourceCodeEditor->setMarginWidth(1, lineNumbers); +} + + +/*! + \brief Catches language change events and retranslates all needed widgets. + */ +void MainWindow::changeEvent(QEvent *event) { + int i = 0; + + if (event->type() == QEvent::LanguageChange) { + QString languageName; + + // Translate the main window. + _mainWindowForm->retranslateUi(this); + updateWindowTitle(); + + // Translate the toolbar. + _toolBarWidget->retranslateUi(_mainWindowForm->toolBar); + + // Translate the indent handler widget. + _indentHandler->retranslateUi(); + + // Translate the load encoding menu. + QList<QAction *> encodingActionList = _encodingActionGroup->actions(); + for ( i = 0; i < encodingActionList.size(); i++ ) { + encodingActionList.at(i)->setStatusTip( tr("Reopen the currently opened source code file by using the text encoding scheme ") + _encodingsList.at(i) ); + } + + // Translate the save encoding menu. + encodingActionList = _saveEncodedActionGroup->actions(); + for ( i = 0; i < encodingActionList.size(); i++ ) { + encodingActionList.at(i)->setStatusTip( tr("Save the currently opened source code file by using the text encoding scheme ") + _encodingsList.at(i) ); + } + + // Translate the _highlighter menu. + QList<QAction *> actionList = _mainWindowForm->highlighterMenu->actions(); + i = 0; + foreach ( QString highlighterName, _highlighter->getAvailableHighlighters() ) { + QAction *highlighterAction = actionList.at(i); + highlighterAction->setStatusTip( tr("Set the syntax highlightning to ") + highlighterName ); + i++; + } + + // Translate the line and column indicators in the statusbar. + int line, column; + _qSciSourceCodeEditor->getCursorPosition( &line, &column ); + setStatusBarCursorPosInfo( line, column ); + } + else { + QWidget::changeEvent(event); + } +} + + + +/*! + \brief Updates the list of recently opened files. + + Therefore the currently open file is set at the lists first position + regarding the in the _settings set maximum list length. Overheads of the + list will be cut off. The new list will be updated to the _settings and + the recently opened menu will be updated too. + */ +void MainWindow::updateRecentlyOpenedList() { + QString fileName; + QString filePath; + QStringList recentlyOpenedList = _settings->getValueByName("lastSourceCodeFile").toString().split("|"); + QList<QAction*> recentlyOpenedActionList = _mainWindowForm->menuRecently_Opened_Files->actions(); + + // Check if the currently open file is in the list of recently opened. + int indexOfCurrentFile = recentlyOpenedList.indexOf( _currentSourceFile ); + + // If it is in the list of recently opened files and not at the first position, move it to the first pos. + if ( indexOfCurrentFile > 0 ) { + recentlyOpenedList.move(indexOfCurrentFile, 0); + recentlyOpenedActionList.move(indexOfCurrentFile, 0); + } + // Put the current file at the first position if it not already is and is not empty. + else if ( indexOfCurrentFile == -1 && !_currentSourceFile.isEmpty() ) { + recentlyOpenedList.insert(0, _currentSourceFile); + QAction *recentlyOpenedAction = new QAction(QFileInfo(_currentSourceFile).fileName(), _mainWindowForm->menuRecently_Opened_Files); + recentlyOpenedAction->setStatusTip(_currentSourceFile); + recentlyOpenedActionList.insert(0, recentlyOpenedAction ); + } + + // Get the maximum recently opened list size. + int recentlyOpenedListMaxSize = _settings->getValueByName("recentlyOpenedListSize").toInt(); + + // Loop for each filepath in the recently opened list, remove non existing files and + // loop only as long as maximum allowed list entries are set. + for ( int i = 0; i < recentlyOpenedList.size() && i < recentlyOpenedListMaxSize; ) { + filePath = recentlyOpenedList.at(i); + QFileInfo fileInfo(filePath); + + // If the file does no longer exist, remove it from the list. + if ( !fileInfo.exists() ) { + recentlyOpenedList.takeAt(i); + if ( i < recentlyOpenedActionList.size()-2 ) { + QAction* action = recentlyOpenedActionList.takeAt(i); + delete action; + } + } + // else if its not already in the menu, add it to the menu. + else { + if ( i >= recentlyOpenedActionList.size()-2 ) { + QAction *recentlyOpenedAction = new QAction(fileInfo.fileName(), _mainWindowForm->menuRecently_Opened_Files); + recentlyOpenedAction->setStatusTip(filePath); + recentlyOpenedActionList.insert( recentlyOpenedActionList.size()-2, recentlyOpenedAction ); + } + i++; + } + } + + // Trim the list to its in the _settings allowed maximum size. + while ( recentlyOpenedList.size() > recentlyOpenedListMaxSize ) { + recentlyOpenedList.takeLast(); + QAction* action = recentlyOpenedActionList.takeAt( recentlyOpenedActionList.size()-3 ); + delete action; + } + + // Add all actions to the menu. + _mainWindowForm->menuRecently_Opened_Files->addActions(recentlyOpenedActionList); + _mainWindowForm->menuRecently_Opened_Files->addActions(recentlyOpenedActionList); + + // Write the new recently opened list to the _settings. + _settings->setValueByName( "lastSourceCodeFile", recentlyOpenedList.join("|") ); + + // Enable or disable "actionClear_Recently_Opened_List" if list is [not] emtpy + if ( recentlyOpenedList.isEmpty() ) { + _mainWindowForm->actionClear_Recently_Opened_List->setEnabled(false); + } + else { + _mainWindowForm->actionClear_Recently_Opened_List->setEnabled(true); + } +} + + +/*! + \brief This slot empties the list of recently opened files. + */ +void MainWindow::clearRecentlyOpenedList() { + QStringList recentlyOpenedList = _settings->getValueByName("lastSourceCodeFile").toString().split("|"); + QList<QAction*> recentlyOpenedActionList = _mainWindowForm->menuRecently_Opened_Files->actions(); + + while ( recentlyOpenedList.size() > 0 ) { + recentlyOpenedList.takeLast(); + QAction* action = recentlyOpenedActionList.takeAt( recentlyOpenedActionList.size()-3 ); + delete action; + } + + // Write the new recently opened list to the _settings. + _settings->setValueByName( "lastSourceCodeFile", recentlyOpenedList.join("|") ); + + // Disable "actionClear_Recently_Opened_List" + _mainWindowForm->actionClear_Recently_Opened_List->setEnabled(false); +} + + +/*! + \brief This slot is called if an entry from the list of recently opened files is + being selected. + */ +void MainWindow::openFileFromRecentlyOpenedList(QAction* recentlyOpenedAction) { + // If the selected action from the recently opened list menu is the clear action + // call the slot to clear the list and then leave. + if ( recentlyOpenedAction == _mainWindowForm->actionClear_Recently_Opened_List ) { + clearRecentlyOpenedList(); + return; + } + + QString fileName = recentlyOpenedAction->text(); + int indexOfSelectedFile = _mainWindowForm->menuRecently_Opened_Files->actions().indexOf( recentlyOpenedAction ); + QStringList recentlyOpenedList = _settings->getValueByName("lastSourceCodeFile").toString().split("|"); + QString filePath = recentlyOpenedList.at(indexOfSelectedFile); + QFileInfo fileInfo(filePath); + + // If the file exists, open it. + if ( fileInfo.exists() ) { + openSourceFileDialog(filePath); + } + // If it does not exist, show a warning message and update the list of recently opened files. + else { + QMessageBox::warning(NULL, tr("File no longer exists"), tr("The file %1 in the list of recently opened files does no longer exist.") ); + // The function updateRecentlyOpenedList() has to be called via a singleShot so it is executed after this + // function (openFileFromRecentlyOpenedList) has already been left. This has to be done because + // a Qt3Support function tries to emit a signal based on the existing actions and deleting + // any of these actions in updateRecentlyOpenedList() causes an error. + QTimer::singleShot(0, this, SLOT(updateRecentlyOpenedList()) ); + } +} + + +/*! + \brief If the dragged in object contains urls/paths to a file, accept the drag. + */ +void MainWindow::dragEnterEvent(QDragEnterEvent *event) { + if ( event->mimeData()->hasUrls() ) { + event->acceptProposedAction(); + } +} + + +/*! + \brief If the dropped in object contains urls/paths to a file, open that file. + */ +void MainWindow::dropEvent(QDropEvent *event) { + if ( event->mimeData()->hasUrls() ) { + QString filePathName = event->mimeData()->urls().first().toLocalFile(); + openSourceFileDialog(filePathName); + } + + event->acceptProposedAction(); +} + + +/*! + \brief If the dropped in object contains urls/paths to a file, open that file. +*/ +void MainWindow::showAboutDialog() { + //QPixmap originalPixmap = QPixmap::grabWindow(QApplication::desktop()->screen()->winId()); + //qDebug("in main pixmap width %d, numScreens = %d", originalPixmap.size().width(), QApplication::desktop()->availableGeometry().width()); + //_aboutDialogGraphicsView->setScreenshotPixmap( originalPixmap ); + _aboutDialogGraphicsView->show(); +} + + +/*! + \brief Sets the label in the status bar to show the \a line and \a column number. +*/ +void MainWindow::setStatusBarCursorPosInfo( int line, int column ) { + _textEditLineColumnInfoLabel->setText( tr("Line %1, Column %2").arg(line+1).arg(column+1) ); +} diff --git a/src/MainWindow.h b/src/MainWindow.h new file mode 100755 index 0000000..1205a46 --- /dev/null +++ b/src/MainWindow.h @@ -0,0 +1,143 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +#include "UiGuiSettings.h" + +class UiGuiSettingsDialog; +class AboutDialog; +class AboutDialogGraphicsView; +class UiGuiHighlighter; +class IndentHandler; +class UpdateCheckDialog; +namespace Ui { + class ToolBarWidget; + class MainWindowUi; +} + +class QLabel; +class QScrollBar; +class QActionGroup; +class QTranslator; + +class QsciScintilla; + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + //! Constructor + MainWindow(QString file2OpenOnStart = "", QWidget *parent = NULL); + ~MainWindow() { + _settings.clear(); + } + +protected: + void closeEvent( QCloseEvent *event ); + bool eventFilter(QObject *obj, QEvent *event); + +private slots: + void openSourceFileDialog(QString fileName = ""); + bool saveasSourceFileDialog(QAction *chosenEncodingAction = NULL); + void saveAsOtherEncoding(QAction *chosenEncodingAction); + bool saveSourceFile(); + void callIndenter(); + void updateSourceView(); + void turnHighlightOnOff(bool turnOn); + void setWhiteSpaceVisibility(bool visible); + void sourceCodeChangedHelperSlot(); + void sourceCodeChangedSlot(); + void indentSettingsChangedSlot(); + void previewTurnedOnOff(bool turnOn); + void exportToPDF(); + void exportToHTML(); + void languageChanged(int languageIndex); + void encodingChanged(QAction *encodingAction); + void numberOfLinesChanged(); + void updateRecentlyOpenedList(); + void openFileFromRecentlyOpenedList(QAction* recentlyOpenedAction); + void clearRecentlyOpenedList(); + void showAboutDialog(); + void setStatusBarCursorPosInfo(int line, int column); + +private: + Ui::MainWindowUi *_mainWindowForm; + + QString loadFile(QString filePath); + QString openFileDialog(QString dialogHeaderStr, QString startPath, QString fileMaskStr); + void updateWindowTitle(); + void loadLastOpenedFile(); + void saveSettings(); + bool maybeSave(); + void createEncodingMenu(); + void createHighlighterMenu(); + bool initApplicationLanguage(); + void initMainWindow(); + void initToolBar(); + void initTextEditor(); + void initSyntaxHighlighter(); + void initIndenter(); + void changeEvent(QEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + + QsciScintilla *_qSciSourceCodeEditor; + QSharedPointer<UiGuiSettings> _settings; + + QString _currentEncoding; + QString _sourceFileContent; + QString _sourceFormattedContent; + QString _sourceViewContent; + UiGuiHighlighter *_highlighter; + QScrollBar *_textEditVScrollBar; + AboutDialog *_aboutDialog; + AboutDialogGraphicsView *_aboutDialogGraphicsView; + UiGuiSettingsDialog *_settingsDialog; + int _textEditLastScrollPos; + int _currentIndenterID; + bool _loadLastSourceCodeFileOnStartup; + QString _currentSourceFile; + QString _currentSourceFileExtension; + QString _savedSourceContent; + QActionGroup *_encodingActionGroup; + QActionGroup *_saveEncodedActionGroup; + QActionGroup *_highlighterActionGroup; + QTranslator *_uiGuiTranslator; + QTranslator *_qTTranslator; + bool _isFirstRunOfThisVersion; + + bool _sourceCodeChanged; + bool _scrollPositionChanged; + bool _indentSettingsChanged; + bool _previewToggled; + QStringList _encodingsList; + + Ui::ToolBarWidget *_toolBarWidget; + IndentHandler *_indentHandler; + UpdateCheckDialog *_updateCheckDialog; + QLabel *_textEditLineColumnInfoLabel; +}; + +#endif // MAINWINDOW_H diff --git a/src/MainWindow.ui b/src/MainWindow.ui new file mode 100755 index 0000000..1a3cacd --- /dev/null +++ b/src/MainWindow.ui @@ -0,0 +1,488 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <author>Thomas_-_S</author> + <class>MainWindowUi</class> + <widget class="QMainWindow" name="MainWindowUi"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>949</width> + <height>633</height> + </rect> + </property> + <property name="windowTitle"> + <string>UniversalIndentGUI</string> + </property> + <property name="windowIcon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/universalIndentGUI.svg</normaloff>:/mainWindow/universalIndentGUI.svg</iconset> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>2</number> + </property> + </layout> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <widget class="QMenuBar" name="menuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>949</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menuIndenter"> + <property name="title"> + <string>Indenter</string> + </property> + </widget> + <widget class="QMenu" name="menuFile"> + <property name="title"> + <string>File</string> + </property> + <widget class="QMenu" name="menuExport"> + <property name="title"> + <string>Export</string> + </property> + <addaction name="actionExportPDF"/> + <addaction name="actionExportHTML"/> + </widget> + <widget class="QMenu" name="menuRecently_Opened_Files"> + <property name="title"> + <string>Recently Opened Files</string> + </property> + <addaction name="separator"/> + <addaction name="actionClear_Recently_Opened_List"/> + </widget> + <widget class="QMenu" name="encodingMenu"> + <property name="title"> + <string>Reopen File with other Encoding</string> + </property> + </widget> + <widget class="QMenu" name="saveEncodedMenu"> + <property name="title"> + <string>Save Source File As with other Encoding</string> + </property> + </widget> + <addaction name="actionOpen_Source_File"/> + <addaction name="menuRecently_Opened_Files"/> + <addaction name="encodingMenu"/> + <addaction name="separator"/> + <addaction name="actionSave_Source_File"/> + <addaction name="actionSave_Source_File_As"/> + <addaction name="saveEncodedMenu"/> + <addaction name="separator"/> + <addaction name="menuExport"/> + <addaction name="actionExit"/> + </widget> + <widget class="QMenu" name="menuSettings"> + <property name="title"> + <string>Settings</string> + </property> + <widget class="QMenu" name="highlighterMenu"> + <property name="title"> + <string>Set Syntax Highlighter</string> + </property> + </widget> + <addaction name="actionLive_Indent_Preview"/> + <addaction name="enableSyntaxHighlightingAction"/> + <addaction name="whiteSpaceIsVisibleAction"/> + <addaction name="highlighterMenu"/> + <addaction name="indenterParameterTooltipsEnabledAction"/> + <addaction name="loadLastOpenedFileOnStartupAction"/> + <addaction name="actionShowSettings"/> + </widget> + <widget class="QMenu" name="menuHelp"> + <property name="title"> + <string>Help</string> + </property> + <addaction name="actionCheck_for_update"/> + <addaction name="actionShowLog"/> + <addaction name="separator"/> + <addaction name="actionAbout_UniversalIndentGUI"/> + </widget> + <addaction name="menuFile"/> + <addaction name="menuIndenter"/> + <addaction name="menuSettings"/> + <addaction name="menuHelp"/> + </widget> + <widget class="QDockWidget" name="dockWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="features"> + <set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set> + </property> + <property name="allowedAreas"> + <set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set> + </property> + <property name="windowTitle"> + <string>Indenter Settings</string> + </property> + <attribute name="dockWidgetArea"> + <number>1</number> + </attribute> + <widget class="QWidget" name="dockWidgetContents"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>0</number> + </property> + </layout> + </item> + </layout> + </widget> + </widget> + <widget class="QToolBar" name="toolBar"> + <property name="contextMenuPolicy"> + <enum>Qt::PreventContextMenu</enum> + </property> + <property name="windowTitle"> + <string>Main Toolbar</string> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="iconSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + </widget> + <action name="actionOpen_Source_File"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-open.png</normaloff>:/mainWindow/document-open.png</iconset> + </property> + <property name="text"> + <string>Open Source File</string> + </property> + <property name="statusTip"> + <string>Opens a dialog for selecting a source code file.</string> + </property> + <property name="shortcut"> + <string>Ctrl+O</string> + </property> + </action> + <action name="actionSave_Source_File"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-save.png</normaloff>:/mainWindow/document-save.png</iconset> + </property> + <property name="text"> + <string>Save Source File</string> + </property> + <property name="statusTip"> + <string>Saves the currently shown source code to the last opened or saved source file.</string> + </property> + <property name="shortcut"> + <string>Ctrl+S</string> + </property> + </action> + <action name="actionSave_Source_File_As"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-save-as.png</normaloff>:/mainWindow/document-save-as.png</iconset> + </property> + <property name="text"> + <string>Save Source File As...</string> + </property> + <property name="iconText"> + <string>Save Source File As...</string> + </property> + <property name="toolTip"> + <string>Save Source File As...</string> + </property> + <property name="statusTip"> + <string>Opens a file dialog to save the currently shown source code.</string> + </property> + <property name="shortcut"> + <string>Ctrl+Shift+S</string> + </property> + </action> + <action name="actionAbout_UniversalIndentGUI"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/info.png</normaloff>:/mainWindow/info.png</iconset> + </property> + <property name="text"> + <string>About UniversalIndentGUI</string> + </property> + <property name="statusTip"> + <string>Shows info about UniversalIndentGUI.</string> + </property> + </action> + <action name="actionExit"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/system-log-out.png</normaloff>:/mainWindow/system-log-out.png</iconset> + </property> + <property name="text"> + <string>Exit</string> + </property> + <property name="statusTip"> + <string>Quits the UniversalIndentGUI.</string> + </property> + <property name="shortcut"> + <string>Ctrl+Q</string> + </property> + </action> + <action name="actionExportPDF"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/exportpdf.png</normaloff>:/mainWindow/exportpdf.png</iconset> + </property> + <property name="text"> + <string>PDF</string> + </property> + <property name="statusTip"> + <string>Export the currently visible source code as PDF document</string> + </property> + </action> + <action name="actionExportHTML"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/exporthtml.png</normaloff>:/mainWindow/exporthtml.png</iconset> + </property> + <property name="text"> + <string>HTML</string> + </property> + <property name="statusTip"> + <string>Export the currently visible source code as HTML document</string> + </property> + </action> + <action name="indenterParameterTooltipsEnabledAction"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/tooltip.png</normaloff>:/mainWindow/tooltip.png</iconset> + </property> + <property name="text"> + <string>Parameter Tooltips</string> + </property> + <property name="statusTip"> + <string>If checked, tool tips will show up if the mouse cursor remains over an indenter parameter for a while.</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string>DONOTTRANSLATE:indenterParameterTooltipsEnabled</string> + </property> + </action> + <action name="actionLive_Indent_Preview"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/live-preview.png</normaloff>:/mainWindow/live-preview.png</iconset> + </property> + <property name="text"> + <string>Live Indent Preview</string> + </property> + <property name="shortcut"> + <string>Ctrl+L</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + </action> + <action name="enableSyntaxHighlightingAction"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/syntax-highlight.png</normaloff>:/mainWindow/syntax-highlight.png</iconset> + </property> + <property name="text"> + <string>Syntax Highlighting</string> + </property> + <property name="iconText"> + <string>Syntax Highlighting</string> + </property> + <property name="toolTip"> + <string>Enables or disables syntax highlighting for the source code.</string> + </property> + <property name="statusTip"> + <string>By enabling special key words of the source code are highlighted.</string> + </property> + <property name="shortcut"> + <string>Ctrl+H</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string>DONOTTRANSLATE:SyntaxHighlightingEnabled</string> + </property> + </action> + <action name="whiteSpaceIsVisibleAction"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>White Space Visible</string> + </property> + <property name="iconText"> + <string>White Space Visible</string> + </property> + <property name="toolTip"> + <string>Set white space visible</string> + </property> + <property name="statusTip"> + <string>Enables or disables diplaying of white space characters in the editor.</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + <property name="connectedSettingName" stdset="0"> + <string>DONOTTRANSLATE:whiteSpaceIsVisible</string> + </property> + </action> + <action name="loadLastOpenedFileOnStartupAction"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Auto Open Last File</string> + </property> + <property name="toolTip"> + <string>Auto open last source file on startup</string> + </property> + <property name="statusTip"> + <string>If selected opens last source code file on startup</string> + </property> + <property name="visible"> + <bool>false</bool> + </property> + <property name="connectedSettingName" stdset="0"> + <string>DONOTTRANSLATE:loadLastSourceCodeFileOnStartup</string> + </property> + </action> + <action name="actionShowSettings"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/preferences-system.png</normaloff>:/mainWindow/preferences-system.png</iconset> + </property> + <property name="text"> + <string>Settings</string> + </property> + <property name="iconText"> + <string>Settings</string> + </property> + <property name="toolTip"> + <string>Opens the settings dialog</string> + </property> + <property name="statusTip"> + <string>Opens the settings dialog, to set language etc.</string> + </property> + </action> + <action name="actionCheck_for_update"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/system-software-update.png</normaloff>:/mainWindow/system-software-update.png</iconset> + </property> + <property name="text"> + <string>Check for update</string> + </property> + <property name="toolTip"> + <string>Checks online whether a new version of UniversalIndentGUI is available.</string> + </property> + <property name="statusTip"> + <string>Checks online whether a new version of UniversalIndentGUI is available.</string> + </property> + </action> + <action name="actionClear_Recently_Opened_List"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/edit-clear.png</normaloff>:/mainWindow/edit-clear.png</iconset> + </property> + <property name="text"> + <string>Clear Recently Opened List</string> + </property> + </action> + <action name="actionShowLog"> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-properties.png</normaloff>:/mainWindow/document-properties.png</iconset> + </property> + <property name="text"> + <string>Show Log</string> + </property> + <property name="toolTip"> + <string>Displays logging information.</string> + </property> + <property name="statusTip"> + <string>Displays logging info about the currently running UiGUI application.</string> + </property> + </action> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections> + <connection> + <sender>actionExit</sender> + <signal>triggered()</signal> + <receiver>MainWindowUi</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>399</x> + <y>299</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/SettingsPaths.cpp b/src/SettingsPaths.cpp new file mode 100755 index 0000000..f556491 --- /dev/null +++ b/src/SettingsPaths.cpp @@ -0,0 +1,275 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "SettingsPaths.h"
+
+#include <QCoreApplication>
+#include <QFile>
+#include <QDir>
+#include <QDirIterator>
+#include <QStack>
+#include <QtDebug>
+
+#include <stdlib.h>
+
+//! \defgroup grp_Settings All concerning applications settings.
+
+/*!
+ \class SettingsPaths
+ \ingroup grp_Settings
+ \brief SettingsPaths is a pure static functions class from which info about the
+ paths needed for settings can be retrieved.
+*/
+
+bool SettingsPaths::_alreadyInitialized = false;
+QString SettingsPaths::_applicationBinaryPath = "";
+QString SettingsPaths::_settingsPath = "";
+QString SettingsPaths::_globalFilesPath = "";
+QString SettingsPaths::_indenterPath = "";
+QString SettingsPaths::_tempPath = "";
+bool SettingsPaths::_portableMode = false;
+
+
+/*!
+ \brief Initializes all available information about the paths.
+
+ Mainly during this init it is detected whether to start in portable mode or not. This is
+ done by testing whether the directory "config" is in the same directory as this
+ applications executable file.
+ In portable mode all data is ONLY written to subdirectories of the applications executable file.
+ Means also that the directory "indenters" has to be there.
+ In not portable mode (multiuser mode) only users home directory is used for writing config data.
+ */
+void SettingsPaths::init() {
+ _alreadyInitialized = true;
+
+ qDebug() << __LINE__ << " " << __FUNCTION__ << ": Initializing application paths.";
+
+ // Get the applications binary path, with respect to MacOSXs use of the .app folder.
+ _applicationBinaryPath = QCoreApplication::applicationDirPath();
+ // Remove any trailing slashes
+ while ( _applicationBinaryPath.right(1) == "/" ) {
+ _applicationBinaryPath.chop(1);
+ }
+
+#ifdef UNIVERSALINDENTGUI_NPP_EXPORTS
+ _applicationBinaryPath += "/plugins/uigui";
+#endif
+
+#ifdef Q_OS_MAC
+ // Because on Mac universal binaries are used, the binary path is not equal
+ // to the applications (.app) path. So get the .apps path here.
+ int indexOfDotApp = _applicationBinaryPath.indexOf(".app");
+ if ( indexOfDotApp != -1 ) {
+ // Cut off after the dot of ".app".
+ _applicationBinaryPath = _applicationBinaryPath.left( indexOfDotApp-1 );
+ // Cut off after the first slash that was in front of ".app" (normally this is the word "UniversalIndentGUI")
+ _applicationBinaryPath = _applicationBinaryPath.left( _applicationBinaryPath.lastIndexOf("/") );
+ }
+#endif
+
+ // If the "config" directory is a subdir of the applications binary path, use this one (portable mode)
+ _settingsPath = _applicationBinaryPath + "/config";
+ if ( QFile::exists( _settingsPath ) ) {
+ _portableMode = true;
+ QDir dirCreator;
+ _globalFilesPath = _applicationBinaryPath;
+ _indenterPath = _applicationBinaryPath + "/indenters";
+ dirCreator.mkpath( _settingsPath );
+ _tempPath = _applicationBinaryPath + "/temp";
+ //TODO: If the portable drive has write protection, use local temp path and clean it up on exit.
+ dirCreator.mkpath( _tempPath );
+ }
+ // ... otherwise use the system specific global application data path.
+ else {
+ _portableMode = false;
+ QDir dirCreator;
+#ifdef Q_OS_WIN
+ // Get the local users application settings directory.
+ // Remove any trailing slashes.
+ _settingsPath = QDir::fromNativeSeparators( qgetenv("APPDATA") );
+ while ( _settingsPath.right(1) == "/" ) {
+ _settingsPath.chop(1);
+ }
+ _settingsPath = _settingsPath + "/UniversalIndentGUI";
+
+ // On windows systems the directories "indenters", "translations" are subdirs of the _applicationBinaryPath.
+ _globalFilesPath = _applicationBinaryPath;
+#else
+ // Remove any trailing slashes.
+ _settingsPath = QDir::homePath();
+ while ( _settingsPath.right(1) == "/" ) {
+ _settingsPath.chop(1);
+ }
+ _settingsPath = _settingsPath + "/.universalindentgui";
+ _globalFilesPath = "/usr/share/universalindentgui";
+#endif
+ dirCreator.mkpath( _settingsPath );
+ // If a highlighter config file does not exist in the users home config dir
+ // copy the default config file over there.
+ if ( !QFile::exists(_settingsPath+"/UiGuiSyntaxHighlightConfig.ini") ) {
+ QFile::copy( _globalFilesPath+"/config/UiGuiSyntaxHighlightConfig.ini", _settingsPath+"/UiGuiSyntaxHighlightConfig.ini" );
+ }
+ _indenterPath = _globalFilesPath + "/indenters";
+
+ // On different systems it may be that "QDir::tempPath()" ends with a "/" or not. So check this.
+ // Remove any trailing slashes.
+ _tempPath = QDir::tempPath();
+ while ( _tempPath.right(1) == "/" ) {
+ _tempPath.chop(1);
+ }
+ _tempPath = _tempPath + "/UniversalIndentGUI";
+
+#if defined(Q_OS_WIN32)
+ dirCreator.mkpath( _tempPath );
+#else
+ // On Unix based systems create a random temporary directory for security
+ // reasons. Otherwise an evil human being could create a symbolic link
+ // to an important existing file which gets overwritten when UiGUI writes
+ // into this normally temporary but linked file.
+ char *pathTemplate = new char[_tempPath.length()+8];
+ QByteArray pathTemplateQBA = QString(_tempPath + "-XXXXXX").toAscii();
+ delete [] pathTemplate;
+ pathTemplate = pathTemplateQBA.data();
+ pathTemplate = mkdtemp( pathTemplate );
+ _tempPath = pathTemplate;
+#endif
+ }
+
+ qDebug() << __LINE__ << " " << __FUNCTION__ << ": Paths are:" \
+ "<ul><li>_applicationBinaryPath=" << _applicationBinaryPath \
+ << "</li><li>_settingsPath=" << _settingsPath \
+ << "</li><li>_globalFilesPath=" << _globalFilesPath \
+ << "</li><li>_indenterPath=" << _indenterPath \
+ << "</li><li>_tempPath=" << _tempPath \
+ << "</li><li>Running in portable mode=" << _portableMode << "</li></ul>";
+}
+
+
+/*!
+ \brief Returns the path of the applications executable.
+ */
+const QString SettingsPaths::getApplicationBinaryPath() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _applicationBinaryPath;
+}
+
+
+/*!
+ \brief Returns the path where all settings are being/should be written to.
+ */
+const QString SettingsPaths::getSettingsPath() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _settingsPath;
+}
+
+
+/*!
+ \brief Returns the path where the files concerning all users reside. For example translations.
+ */
+const QString SettingsPaths::getGlobalFilesPath() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _globalFilesPath;
+}
+
+
+/*!
+ \brief Returns the path where the indenter executables reside.
+ */
+const QString SettingsPaths::getIndenterPath() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _indenterPath;
+}
+
+
+/*!
+ \brief Returns the path where the where all temporary data should be written to.
+ */
+const QString SettingsPaths::getTempPath() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _tempPath;
+}
+
+
+/*!
+ \brief Returns true if portable mode shall be used.
+ */
+bool SettingsPaths::getPortableMode() {
+ if ( !_alreadyInitialized ) {
+ SettingsPaths::init();
+ }
+ return _portableMode;
+}
+
+
+/*!
+ \brief Completely deletes the created temporary directory with all of its content.
+ */
+void SettingsPaths::cleanAndRemoveTempDir() {
+ QDirIterator dirIterator(_tempPath, QDirIterator::Subdirectories);
+ QStack<QString> directoryStack;
+ bool noErrorsOccurred = true;
+
+ while ( dirIterator.hasNext() ) {
+ QString currentDirOrFile = dirIterator.next();
+ // If this dummy call isn't done here, calling "dirIterator.fileInfo().isDir()" later somehow fails.
+ dirIterator.fileInfo();
+
+ if ( !currentDirOrFile.isEmpty() && dirIterator.fileName() != "." && dirIterator.fileName() != ".." ) {
+ // There is a path on the stack but the current path doesn't start with that path.
+ // So we changed into another parent directory and the one on the stack can be deleted
+ // since it must be empty.
+ if ( !directoryStack.isEmpty() && !currentDirOrFile.startsWith(directoryStack.top()) ) {
+ QString dirToBeRemoved = directoryStack.pop();
+ bool couldRemoveDir = QDir(dirToBeRemoved).rmdir(dirToBeRemoved);
+ noErrorsOccurred &= couldRemoveDir;
+ if ( couldRemoveDir == false )
+ qWarning() << __LINE__ << " " << __FUNCTION__ << "Could not remove the directory: " << dirToBeRemoved;
+ //qDebug() << "Removing Dir " << directoryStack.pop();
+ }
+
+ // If the iterator currently points to a directory push it onto the stack.
+ if ( dirIterator.fileInfo().isDir() ) {
+ directoryStack.push( currentDirOrFile );
+ //qDebug() << "Pushing onto Stack " << currentDirOrFile;
+ }
+ // otherwise it must be a file, so delete it.
+ else {
+ bool couldRemoveFile = QFile::remove( currentDirOrFile );
+ noErrorsOccurred &= couldRemoveFile;
+ if ( couldRemoveFile == false )
+ qWarning() << __LINE__ << " " << __FUNCTION__ << "Could not remove the file: " << currentDirOrFile;
+ //qDebug() << "Removing File " << currentDirOrFile;
+ }
+ }
+ }
+ noErrorsOccurred &= QDir(_tempPath).rmdir(_tempPath);
+ if ( noErrorsOccurred == false )
+ qWarning() << __LINE__ << " " << __FUNCTION__ << "While cleaning up the temp dir an error occurred.";
+}
diff --git a/src/SettingsPaths.h b/src/SettingsPaths.h new file mode 100755 index 0000000..71f17e3 --- /dev/null +++ b/src/SettingsPaths.h @@ -0,0 +1,50 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef SETTINGSPATHS_H
+#define SETTINGSPATHS_H
+
+class QString;
+
+
+class SettingsPaths
+{
+public:
+ static void init();
+ static const QString getApplicationBinaryPath();
+ static const QString getSettingsPath();
+ static const QString getGlobalFilesPath();
+ static const QString getIndenterPath();
+ static const QString getTempPath();
+ static bool getPortableMode();
+ static void cleanAndRemoveTempDir();
+
+private:
+ SettingsPaths();
+
+ static bool _alreadyInitialized;
+ static QString _applicationBinaryPath;
+ static QString _settingsPath;
+ static QString _globalFilesPath;
+ static QString _indenterPath;
+ static QString _tempPath;
+ static bool _portableMode;
+};
+
+#endif // SETTINGSPATHS_H
diff --git a/src/TemplateBatchScript.cpp b/src/TemplateBatchScript.cpp new file mode 100755 index 0000000..00c96ce --- /dev/null +++ b/src/TemplateBatchScript.cpp @@ -0,0 +1,171 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "TemplateBatchScript.h" + +// Need to include QObject here so that platform specific defines like Q_OS_WIN32 are set. +#include <QObject> + +/*! + \brief The only and static function of this class returns a batch or shell script + as string that can be used to call an indenter with the current settings from + the command line. + + The returned string contains some placeholders where the indenter name needs to + be filled in. The placeholders are "__INDENTERCALLSTRING1__" that should be replaced + by the indenter call string that indents a complete directory. + "__INDENTERCALLSTRING2__" the call string for indenting only one file. + And "__INDENTERCALLSTRINGSCRIPTNAME__" which is only the shown name of the indenter. + */ +const char* TemplateBatchScript::getTemplateBatchScript() { + static const char* templateBatchScript = +#if defined(Q_OS_WIN32) + "@echo off\n" + "\n" + "IF (%1)==() GOTO error\n" + "dir /b /ad %1 >nul 2>nul && GOTO indentDir\n" + "IF NOT EXIST %1 GOTO error\n" + "goto indentFile\n" + "\n" + ":indentDir\n" + "set searchdir=%1\n" + "\n" + "IF (%2)==() GOTO assignDefaultSuffix\n" + "set filesuffix=%2\n" + "\n" + "GOTO run\n" + "\n" + ":assignDefaultSuffix\n" + "::echo !!!!DEFAULT SUFFIX!!!\n" + "set filesuffix=*\n" + "\n" + ":run\n" + "FOR /F \"tokens=*\" %%G IN ('DIR /B /S %searchdir%\\*.%filesuffix%') DO (\n" + "echo Indenting file \"%%G\"\n" + "__INDENTERCALLSTRING1__\n" + ")\n" + "GOTO ende\n" + "\n" + ":indentFile\n" + "echo Indenting one file %1\n" + "__INDENTERCALLSTRING2__\n" + "\n" + "GOTO ende\n" + "\n" + ":error\n" + "echo .\n" + "echo ERROR: As parameter given directory or file does not exist!\n" + "echo Syntax is: __INDENTERCALLSTRINGSCRIPTNAME__ dirname filesuffix\n" + "echo Syntax is: __INDENTERCALLSTRINGSCRIPTNAME__ filename\n" + "echo Example: __INDENTERCALLSTRINGSCRIPTNAME__ temp cpp\n" + "echo .\n" + "\n" + ":ende\n"; + +#else + + "#!/bin/sh \n" + "\n" + "if [ ! -n \"$1\" ]; then\n" + "echo \"Syntax is: recurse.sh dirname filesuffix\"\n" + "echo \"Syntax is: recurse.sh filename\"\n" + "echo \"Example: recurse.sh temp cpp\"\n" + "exit 1\n" + "fi\n" + "\n" + "if [ -d \"$1\" ]; then\n" + "#echo \"Dir ${1} exists\"\n" + "if [ -n \"$2\" ]; then\n" + "filesuffix=$2\n" + "else\n" + "filesuffix=\"*\"\n" + "fi\n" + "\n" + "#echo \"Filtering files using suffix ${filesuffix}\"\n" + "\n" + "file_list=`find ${1} -name \"*.${filesuffix}\" -type f`\n" + "for file2indent in $file_list\n" + "do \n" + "echo \"Indenting file $file2indent\"\n" + "__INDENTERCALLSTRING1__\n" + "done\n" + "else\n" + "if [ -f \"$1\" ]; then\n" + "echo \"Indenting one file $1\"\n" + "__INDENTERCALLSTRING2__\n" + "else\n" + "echo \"ERROR: As parameter given directory or file does not exist!\"\n" + "echo \"Syntax is: __INDENTERCALLSTRINGSCRIPTNAME__ dirname filesuffix\"\n" + "echo \"Syntax is: __INDENTERCALLSTRINGSCRIPTNAME__ filename\"\n" + "echo \"Example: __INDENTERCALLSTRINGSCRIPTNAME__ temp cpp\"\n" + "exit 1\n" + "fi\n" + "fi\n"; +#endif // #if defined(Q_OS_WIN32) + return templateBatchScript; +} + + +/* Here comes the original batch script without the c++ markup +@echo off + +IF (%1)==() GOTO error +dir /b /ad %1 >nul 2>nul && GOTO indentDir +IF NOT EXIST %1 GOTO error +goto indentFile + +:indentDir +set searchdir=%1 + +IF (%2)==() GOTO assignDefaultSuffix +set filesuffix=%2 + +GOTO run + +:assignDefaultSuffix +::echo !!!!DEFAULT SUFFIX!!! +set filesuffix=* + +:run +FOR /F "tokens=*" %%G IN ('DIR /B /S %searchdir%\*.%filesuffix%') DO ( + echo Indenting file "%%G" + ::call call_CSSTidy.bat "%%G" + "C:/Dokumente und Einstellungen/ts/Eigene Dateien/Visual Studio 2005/Projects/UiGuixy/indenters/csstidy.exe" "%%G" --timestamp=true --allow_html_in_templates=false --compress_colors=true --compress_font=true --lowercase_s=false --preserve_css=false --remove_last_;=false --remove_bslash=true --sort_properties=false --sort_selectors=false indentoutput.css + move /Y indentoutput.css "%%G" +) +GOTO ende + +:indentFile +echo Indenting one file %1 +"C:/Dokumente und Einstellungen/ts/Eigene Dateien/Visual Studio 2005/Projects/UiGuixy/indenters/csstidy.exe" %1 --timestamp=true --allow_html_in_templates=false --compress_colors=true --compress_font=true --lowercase_s=false --preserve_css=false --remove_last_;=false --remove_bslash=true --sort_properties=false --sort_selectors=false indentoutput.css +move /Y indentoutput.css %1 + +GOTO ende + +:error +echo . +echo ERROR: As parameter given directory or file does not exist! +echo Syntax is: recurse.bat dirname filesuffix +echo Syntax is: recurse.bat filename +echo Example: recurse.bat temp cpp +echo . + +:ende + +*/ diff --git a/src/TemplateBatchScript.h b/src/TemplateBatchScript.h new file mode 100755 index 0000000..ff14ade --- /dev/null +++ b/src/TemplateBatchScript.h @@ -0,0 +1,31 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef TEMPLATEBATCHSCRIPT_H
+#define TEMPLATEBATCHSCRIPT_H
+
+class TemplateBatchScript
+{
+private:
+ TemplateBatchScript();
+public:
+ static const char* getTemplateBatchScript();
+};
+
+#endif // TEMPLATEBATCHSCRIPT_H
diff --git a/src/ToolBarWidget.ui b/src/ToolBarWidget.ui new file mode 100755 index 0000000..900c60a --- /dev/null +++ b/src/ToolBarWidget.ui @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ToolBarWidget</class> + <widget class="QWidget" name="ToolBarWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>773</width> + <height>34</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="pbOpen_Source_File"> + <property name="toolTip"> + <string><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;"><span style=" font-size:8pt;">Opens a dialog for selecting a source code file.</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;">This file will be used to show what the indent tool changes.</p></body></html></string> + </property> + <property name="text"> + <string>Open Source File </string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-open.png</normaloff>:/mainWindow/document-open.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="cbLivePreview"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; 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; font-family:MS Shell Dlg; font-size:8pt;">Turns the preview of the reformatted source code on and off.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:MS Shell Dlg; font-size:8pt;">In other words it switches between formatted and nonformatted code. (Ctrl+L)</p></body></html></string> + </property> + <property name="text"> + <string>Live Indent Preview</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/live-preview.png</normaloff>:/mainWindow/live-preview.png</iconset> + </property> + <property name="shortcut"> + <string>Ctrl+L</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="enableSyntaxHighlightningCheckBox"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg 2; 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; font-family:MS Shell Dlg; font-size:8pt;">Enables and disables the highlightning of the source</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:MS Shell Dlg; font-size:8pt;">code shown below. (Still needs some performance improvements) (Ctrl+H)</p></body></html></string> + </property> + <property name="text"> + <string>Syntax Highlight</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/syntax-highlight.png</normaloff>:/mainWindow/syntax-highlight.png</iconset> + </property> + <property name="shortcut"> + <string>Ctrl+H</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="connectedSettingName" stdset="0"> + <string>DONOTTRANSLATE:SyntaxHighlightingEnabled</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pbAbout"> + <property name="toolTip"> + <string><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 info about UniversalIndentGUI</p></body></html></string> + </property> + <property name="text"> + <string>About</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/info.png</normaloff>:/mainWindow/info.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pbExit"> + <property name="toolTip"> + <string><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;">Quits the UniversalIndentGUI</p></body></html></string> + </property> + <property name="text"> + <string>Exit</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/system-log-out.png</normaloff>:/mainWindow/system-log-out.png</iconset> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/UiGuiErrorMessage.cpp b/src/UiGuiErrorMessage.cpp new file mode 100755 index 0000000..424a709 --- /dev/null +++ b/src/UiGuiErrorMessage.cpp @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "UiGuiErrorMessage.h" + +#include <QCheckBox> + +/*! + \class UiGuiErrorMessage + \ingroup grp_Dialogs + \brief UiGuiErrorMessage is a child of QErrorMessage. But QErrorMessages + "Do not show again" didn't work with my strings, so this is my own, working + implementation of it. +*/ + + +/*! + \brief Initializes the dialog. + + Retrieves the object pointer to the \a _showAgainCheckBox check box, sets the dialogs + modality and for a working translation sets the check box text. + */ +UiGuiErrorMessage::UiGuiErrorMessage(QWidget *parent) : QErrorMessage(parent) { + _showAgainCheckBox = findChild<QCheckBox *>(); + setWindowModality( Qt::ApplicationModal ); + _showAgainCheckBox->setText( tr("Show this message again") ); +} + + +/*! + \brief Just a lazy nothin doin destructive destructor. + */ +UiGuiErrorMessage::~UiGuiErrorMessage(void) { +} + + +/*! + \brief Shows an error \a message in a dialog box with \a title. + + The shown \a message is added to a list, if not already in there. If it is + already in that list and "Show this message again" is not checked, that + message will not be shown. + */ +void UiGuiErrorMessage::showMessage( const QString &title, const QString &message ) { + bool showAgain = true; + + if ( _showAgainCheckBox != 0 ) { + showAgain = _showAgainCheckBox->isChecked(); + } + + setWindowTitle(title); + + if ( !_errorMessageList.contains(message) ) { + _errorMessageList << message; + if ( _showAgainCheckBox != 0 ) { + _showAgainCheckBox->setChecked(true); + } + QErrorMessage::showMessage( message ); + } + else if ( showAgain ) { + QErrorMessage::showMessage( message ); + } +} + + +/*! + \brief For convinience, for showing a dialog box with the default title "UniversalIndentGUI". + */ +void UiGuiErrorMessage::showMessage( const QString &message ) { + showMessage( "UniversalIndentGUI", message ); +} diff --git a/src/UiGuiErrorMessage.h b/src/UiGuiErrorMessage.h new file mode 100755 index 0000000..f520795 --- /dev/null +++ b/src/UiGuiErrorMessage.h @@ -0,0 +1,43 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UIGUIERRORMESSAGE_H
+#define UIGUIERRORMESSAGE_H
+
+#include <QErrorMessage>
+
+class QCheckBox;
+
+
+class UiGuiErrorMessage : public QErrorMessage
+{
+ Q_OBJECT
+
+public:
+ UiGuiErrorMessage(QWidget *parent = 0);
+ ~UiGuiErrorMessage(void);
+ void showMessage( const QString &message );
+ void showMessage( const QString &title, const QString &message );
+
+private:
+ QCheckBox *_showAgainCheckBox;
+ QStringList _errorMessageList;
+};
+
+#endif // UIGUIERRORMESSAGE_H
diff --git a/src/UiGuiHighlighter.cpp b/src/UiGuiHighlighter.cpp new file mode 100755 index 0000000..ac74909 --- /dev/null +++ b/src/UiGuiHighlighter.cpp @@ -0,0 +1,528 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "UiGuiHighlighter.h" + +#include "SettingsPaths.h" + +#include <QSettings> +#include <QMenu> +#include <QScrollBar> +#include <QCoreApplication> + +#include <Qsci/qsciscintilla.h> +#include <Qsci/qscilexer.h> +#include <Qsci/qscilexerbash.h> +#include <Qsci/qscilexerbatch.h> +#include <Qsci/qscilexercmake.h> +#include <Qsci/qscilexercpp.h> +#include <Qsci/qscilexercsharp.h> +#include <Qsci/qscilexercss.h> +#include <Qsci/qscilexerd.h> +#include <Qsci/qscilexerdiff.h> +#if ( QSCINTILLA_VERSION >= 0x020300 ) +#include <Qsci/qscilexerfortran.h> +#include <Qsci/qscilexerfortran77.h> +#endif +#include <Qsci/qscilexerhtml.h> +#include <Qsci/qscilexeridl.h> +#include <Qsci/qscilexerjava.h> +#include <Qsci/qscilexerjavascript.h> +#include <Qsci/qscilexerlua.h> +#include <Qsci/qscilexermakefile.h> +#if ( QSCINTILLA_VERSION >= 0x020300 ) +#include <Qsci/qscilexerpascal.h> +#endif +#include <Qsci/qscilexerperl.h> +#if ( QSCINTILLA_VERSION >= 0x020300 ) +#include <Qsci/qscilexerpostscript.h> +#endif +#include <Qsci/qscilexerpov.h> +#include <Qsci/qscilexerproperties.h> +#include <Qsci/qscilexerpython.h> +#include <Qsci/qscilexerruby.h> +#if ( QSCINTILLA_VERSION >= 0x020400 ) +#include <Qsci/qscilexerspice.h> +#endif +#include <Qsci/qscilexersql.h> +#if ( QSCINTILLA_VERSION >= 0x020300 ) +#include <Qsci/qscilexertcl.h> +#endif +#include <Qsci/qscilexertex.h> +#if ( QSCINTILLA_VERSION >= 0x020400 ) +#include <Qsci/qscilexerverilog.h> +#endif +#include <Qsci/qscilexervhdl.h> +#if ( QSCINTILLA_VERSION >= 0x020300 ) +#include <Qsci/qscilexerxml.h> +#include <Qsci/qscilexeryaml.h> +#endif + +//! \defgroup grp_EditorComponent All concerning editor widget. + +/*! + \class UiGuiHighlighter + \ingroup grp_EditorComponent + \brief UiGuiHighlighter used for selecting the syntax highlighter/lexer for the QsciScintilla component. +*/ + +/*! + \brief The constructor initializes some regular expressions and keywords to identify cpp tokens + */ +UiGuiHighlighter::UiGuiHighlighter(QsciScintilla *parent) : QObject(parent) { + _qsciEditorParent = parent; + + // Create the highlighter _settings object from the UiGuiSyntaxHighlightConfig.ini file. + _settings = new QSettings(SettingsPaths::getSettingsPath() + "/UiGuiSyntaxHighlightConfig.ini", QSettings::IniFormat, this); + + _highlightningIsOn = true; + + _mapHighlighternameToExtension["Bash"] = QStringList() << "sh"; + _mapHighlighternameToExtension["Batch"] = QStringList() << "bat"; + _mapHighlighternameToExtension["CMake"] = QStringList() << "cmake"; + _mapHighlighternameToExtension["C++"] = QStringList() << "c" << "h" << "cpp" << "hpp" << "cxx" << "hxx"; + _mapHighlighternameToExtension["C#"] = QStringList() << "cs"; + _mapHighlighternameToExtension["CSS"] = QStringList() << "css"; + _mapHighlighternameToExtension["D"] = QStringList() << "d"; + _mapHighlighternameToExtension["Diff"] = QStringList() << "diff"; +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _mapHighlighternameToExtension["Fortran"] = QStringList() << "f" << "for" << "f90"; + _mapHighlighternameToExtension["Fortran77"] = QStringList() << "f77"; +#endif + _mapHighlighternameToExtension["HTML"] = QStringList() << "html" << "htm"; + _mapHighlighternameToExtension["IDL"] = QStringList() << "idl"; + _mapHighlighternameToExtension["Java"] = QStringList() << "java"; + _mapHighlighternameToExtension["JavaScript"] = QStringList() << "js"; + _mapHighlighternameToExtension["LUA"] = QStringList() << "lua"; + _mapHighlighternameToExtension["Makefile"] = QStringList() << "makefile"; +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _mapHighlighternameToExtension["Pascal"] = QStringList() << "pas"; +#endif + _mapHighlighternameToExtension["Perl"] = QStringList() << "perl" << "pl" << "pm"; + _mapHighlighternameToExtension["PHP"] = QStringList() << "php"; +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _mapHighlighternameToExtension["PostScript"] = QStringList() << "ps" << "eps" << "pdf" << "ai" << "fh"; +#endif + _mapHighlighternameToExtension["POV"] = QStringList() << "pov"; + _mapHighlighternameToExtension["Ini"] = QStringList() << "ini"; + _mapHighlighternameToExtension["Python"] = QStringList() << "py"; + _mapHighlighternameToExtension["Ruby"] = QStringList() << "rub" << "rb"; +#if ( QSCINTILLA_VERSION >= 0x020400 ) + _mapHighlighternameToExtension["Spice"] = QStringList() << "cir"; +#endif + _mapHighlighternameToExtension["SQL"] = QStringList() << "sql"; +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _mapHighlighternameToExtension["TCL"] = QStringList() << "tcl"; +#endif + _mapHighlighternameToExtension["TeX"] = QStringList() << "tex"; +#if ( QSCINTILLA_VERSION >= 0x020400 ) + _mapHighlighternameToExtension["Verilog"] = QStringList() << "v" << "vh"; +#endif + _mapHighlighternameToExtension["VHDL"] = QStringList() << "vhdl"; + _mapHighlighternameToExtension["XML"] = QStringList() << "xml"; +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _mapHighlighternameToExtension["YAML"] = QStringList() << "yaml"; +#endif + + _lexer = NULL; + + // This code is only for testing. + /* + foreach(QStringList extensionList, _mapHighlighternameToExtension.values() ) { + setLexerForExtension( extensionList.at(0) ); + } + */ + + // Set default highlighter to C++ highlighter. + setLexerForExtension( "cpp" ); +} + + +/*! + \brief Returns the available highlighters as QStringList. + */ +QStringList UiGuiHighlighter::getAvailableHighlighters() { + return _mapHighlighternameToExtension.keys(); +} + + +/*! + \brief This slot handles signals coming from selecting another syntax highlighter. + */ +void UiGuiHighlighter::setHighlighterByAction(QAction* highlighterAction) { + QString highlighterName = highlighterAction->text(); + setLexerForExtension( _mapHighlighternameToExtension[highlighterName].first() ); + //TODO: This is really no nice way. How do it better? + // Need to do this "text update" to update the syntax highlighting. Otherwise highlighting is wrong. + int scrollPos = _qsciEditorParent->verticalScrollBar()->value(); + _qsciEditorParent->setText( _qsciEditorParent->text() ); + _qsciEditorParent->verticalScrollBar()->setValue(scrollPos); +} + + +/*! + \brief Turns the syntax parser on. +*/ +void UiGuiHighlighter::turnHighlightOn() { + _highlightningIsOn = true; + _qsciEditorParent->setLexer(_lexer); + readCurrentSettings(""); +} + +/*! + \brief Turns the syntax parser off. +*/ +void UiGuiHighlighter::turnHighlightOff() { + _highlightningIsOn = false; + _qsciEditorParent->setLexer(); +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) + _qsciEditorParent->setFont( QFont("Courier", 10, QFont::Normal) ); + _qsciEditorParent->setMarginsFont( QFont("Courier", 10, QFont::Normal) ); +#else + _qsciEditorParent->setFont( QFont("Monospace", 10, QFont::Normal) ); + _qsciEditorParent->setMarginsFont( QFont("Monospace", 10, QFont::Normal) ); +#endif +} + + +/*! + \brief Read the settings for the current lexer from the settings file. + */ +//TODO: Refactor this function so that the coding style and variable names suit better. +bool UiGuiHighlighter::readCurrentSettings( const char *prefix ) { + bool ok, flag, rc = true; + int num; + QString key; + + // Reset lists containing fonts and colors for each style + _fontForStyles.clear(); + _colorForStyles.clear(); + + // Read the styles. + for (int i = 0; i < 128; ++i) { + // Ignore invalid styles. + if ( _lexer->description(i).isEmpty() ) + continue; + + key.sprintf( "%s/%s/style%d/", prefix, _lexer->language(), i ); + key.replace("+", "p"); + + // Read the foreground color. + ok = _settings->contains(key + "color"); + num = _settings->value(key + "color", 0).toInt(); + + if (ok) + setColor( QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff), i ); + else + rc = false; + + // Read the end-of-line fill. + ok = _settings->contains(key + "eolfill"); + flag = _settings->value(key + "eolfill", false).toBool(); + + if (ok) + _lexer->setEolFill( flag, i ); + else + rc = false; + + // Read the font + QStringList fdesc; + + ok = _settings->contains(key + "font"); + fdesc = _settings->value(key + "font").toStringList(); + + if (ok && fdesc.count() == 5) { + QFont f; + +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) + f.setFamily(fdesc[0]); +#else + if ( fdesc[0].contains("courier", Qt::CaseInsensitive) ) + f.setFamily("Monospace"); + else + f.setFamily(fdesc[0]); +#endif + f.setPointSize(fdesc[1].toInt()); + f.setBold(fdesc[2].toInt()); + f.setItalic(fdesc[3].toInt()); + f.setUnderline(fdesc[4].toInt()); + + setFont(f, i); + } + else + rc = false; + + // Read the background color. + ok = _settings->contains(key + "paper"); + num = _settings->value(key + "paper", 0).toInt(); + + if (ok) + _lexer->setPaper( QColor((num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff), i ); + else + rc = false; + } + + // Read the properties. + key.sprintf( "%s/%s/properties/", prefix, _lexer->language() ); + + _lexer->refreshProperties(); + + return rc; +} + + +/*! + \brief Write the settings for the current lexer to the settings file. + */ +void UiGuiHighlighter::writeCurrentSettings( const char *prefix ) { + QString key; + + // Write the styles. + for (int i = 0; i < 128; ++i) { + // Ignore invalid styles. + if ( _lexer->description(i).isEmpty() ) + continue; + + int num; + QColor c; + + key.sprintf( "%s/%s/style%d/", prefix, _lexer->language(), i ); + key.replace("+", "p"); + + // Write style name + _settings->setValue( key + "", _lexer->description(i) ); + + // Write the foreground color. + if ( _colorForStyles.contains(i) ) { + c = _colorForStyles[i]; + } + else { + c = _lexer->color(i); + } + num = (c.red() << 16) | (c.green() << 8) | c.blue(); + + _settings->setValue(key + "color", num); + + // Write the end-of-line fill. + _settings->setValue( key + "eolfill", _lexer->eolFill(i) ); + + // Write the font + QStringList fdesc; + QString fmt("%1"); + QFont f; + + if ( _fontForStyles.contains(i) ) { + f = _fontForStyles[i]; + } + else { + f = _lexer->font(i); + } + + fdesc += f.family(); + fdesc += fmt.arg( f.pointSize() ); + + // The casts are for Borland. + fdesc += fmt.arg( (int)f.bold() ); + fdesc += fmt.arg( (int)f.italic() ); + fdesc += fmt.arg( (int)f.underline() ); + + _settings->setValue(key + "font", fdesc); + + // Write the background color. + c = _lexer->paper(i); + num = (c.red() << 16) | (c.green() << 8) | c.blue(); + + _settings->setValue(key + "paper", num); + } +} + + +/*! + \brief Sets the \a color for the given \a style. + */ +void UiGuiHighlighter::setColor(const QColor &color, int style) { + _colorForStyles[style] = color; + _lexer->setColor( color, style ); +} + + +/*! + \brief Sets the \a font for the given \a style. + */ +void UiGuiHighlighter::setFont(const QFont &font, int style) { + _fontForStyles[style] = font; + _lexer->setFont( font, style ); +} + + +/*! + \brief Sets the to be used lexer by giving his name. + */ +void UiGuiHighlighter::setLexerByName( QString lexerName ) { + setLexerForExtension( _mapHighlighternameToExtension[lexerName].first() ); +} + + +/*! + \brief Sets the proper highlighter / lexer for the given file \a extension. Returns the index of the used lexer in the list. + */ +int UiGuiHighlighter::setLexerForExtension( QString extension ) { + int indexOfHighlighter = 0; + extension = extension.toLower(); + + if ( _lexer != NULL ) { + writeCurrentSettings(""); + delete _lexer; + } + + if ( extension == "cpp" || extension == "hpp" || extension == "c" || extension == "h" || extension == "cxx" || extension == "hxx" ) { + _lexer = new QsciLexerCPP(); + } + else if ( extension == "sh" ) { + _lexer = new QsciLexerBash(); + } + else if ( extension == "bat" ) { + _lexer = new QsciLexerBatch(); + } + else if ( extension == "cmake" ) { + _lexer = new QsciLexerCMake(); + } + else if ( extension == "cs" ) { + _lexer = new QsciLexerCSharp(); + } + else if ( extension == "css" ) { + _lexer = new QsciLexerCSS(); + } + else if ( extension == "d" ) { + _lexer = new QsciLexerD(); + } + else if ( extension == "diff" ) { + _lexer = new QsciLexerDiff(); + } +#if ( QSCINTILLA_VERSION >= 0x020300 ) + else if ( extension == "f" || extension == "for" || extension == "f90" ) { + _lexer = new QsciLexerFortran(); + } + else if ( extension == "f77" ) { + _lexer = new QsciLexerFortran77(); + } +#endif + else if ( extension == "html" || extension == "htm" ) { + _lexer = new QsciLexerHTML(); + } + else if ( extension == "idl" ) { + _lexer = new QsciLexerIDL(); + } + else if ( extension == "java" ) { + _lexer = new QsciLexerJava(); + } + else if ( extension == "js" ) { + _lexer = new QsciLexerJavaScript(); + } + else if ( extension == "lua" ) { + _lexer = new QsciLexerLua(); + } + else if ( extension == "makefile" ) { + _lexer = new QsciLexerMakefile(); + } +#if ( QSCINTILLA_VERSION >= 0x020300 ) + else if ( extension == "pas" ) { + _lexer = new QsciLexerPascal(); + } +#endif + else if ( extension == "perl" || extension == "pl" || extension == "pm" ) { + _lexer = new QsciLexerPerl(); + } + else if ( extension == "php" ) { + _lexer = new QsciLexerHTML(); + } +#if ( QSCINTILLA_VERSION >= 0x020300 ) + else if ( extension == "ps" || extension == "eps" || extension == "pdf" || extension == "ai" || extension == "fh") { + _lexer = new QsciLexerPostScript(); + } +#endif + else if ( extension == "pov" ) { + _lexer = new QsciLexerPOV(); + } + else if ( extension == "ini" ) { + _lexer = new QsciLexerProperties(); + } + else if ( extension == "py" ) { + _lexer = new QsciLexerPython(); + } + else if ( extension == "rub" || extension == "rb" ) { + _lexer = new QsciLexerRuby(); + } +#if ( QSCINTILLA_VERSION >= 0x020400 ) + else if ( extension == "spice?" ) { + _lexer = new QsciLexerSpice(); + } +#endif + else if ( extension == "sql" ) { + _lexer = new QsciLexerSQL(); + } +#if ( QSCINTILLA_VERSION >= 0x020300 ) + else if ( extension == "tcl" ) { + _lexer = new QsciLexerTCL(); + } +#endif + else if ( extension == "tex" ) { + _lexer = new QsciLexerTeX(); + } +#if ( QSCINTILLA_VERSION >= 0x020400 ) + else if ( extension == "vlog?" ) { + _lexer = new QsciLexerVerilog(); + } +#endif + else if ( extension == "vhdl" ) { + _lexer = new QsciLexerVHDL(); + } + else if ( extension == "xml" ) { +#if ( QSCINTILLA_VERSION >= 0x020300 ) + _lexer = new QsciLexerXML(); +#else + _lexer = new QsciLexerHTML(); +#endif + } +#if ( QSCINTILLA_VERSION >= 0x020300 ) + else if ( extension == "yaml" ) { + _lexer = new QsciLexerYAML(); + } +#endif + else { + _lexer = new QsciLexerCPP(); + extension = "cpp"; + } + + // Find the index of the selected _lexer. + indexOfHighlighter = 0; + while ( !_mapHighlighternameToExtension.values().at(indexOfHighlighter).contains(extension) ) { + indexOfHighlighter++; + } + + // Set the _lexer for the QScintilla widget. + if ( _highlightningIsOn ) { + _qsciEditorParent->setLexer(_lexer); + } + + // Read the _settings for the _lexer properties from file. + readCurrentSettings(""); + + return indexOfHighlighter; +} diff --git a/src/UiGuiHighlighter.h b/src/UiGuiHighlighter.h new file mode 100755 index 0000000..d0d60d4 --- /dev/null +++ b/src/UiGuiHighlighter.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef UIGUIHIGHLIGHTER_H +#define UIGUIHIGHLIGHTER_H + +#include <QObject> +#include <QMap> +#include <QFont> +#include <QColor> + +class QAction; +class QSettings; + +class QsciScintilla; +class QsciLexer; + + +class UiGuiHighlighter : public QObject +{ + Q_OBJECT + +public: + UiGuiHighlighter(QsciScintilla *parent); + void turnHighlightOff(); + void turnHighlightOn(); + + bool readCurrentSettings(const char *prefix); + void writeCurrentSettings(const char *prefix); + QStringList getAvailableHighlighters(); + +public slots: + //! The foreground color for style number \a style is set to \a color. If + //! \a style is -1 then the color is set for all styles. + void setColor(const QColor &color, int style = -1); + + //! The font for style number \a style is set to \a font. If \a style is + //! -1 then the font is set for all styles. + void setFont(const QFont &font, int style = -1); + + //! Sets the lexer that is responsible for the given \a extension. + int setLexerForExtension( QString extension ); + + void setLexerByName( QString lexerName ); + + void setHighlighterByAction(QAction* highlighterAction); + +private: + bool _highlightningIsOn; + QsciScintilla *_qsciEditorParent; + QMap<int, QFont> _fontForStyles; + QMap<int, QColor> _colorForStyles; + QsciLexer* _lexer; + QSettings *_settings; + QMap<QString, QStringList> _mapHighlighternameToExtension; +}; + +#endif // UIGUIHIGHLIGHTER_H diff --git a/src/UiGuiIndentServer.cpp b/src/UiGuiIndentServer.cpp new file mode 100755 index 0000000..0dfc93f --- /dev/null +++ b/src/UiGuiIndentServer.cpp @@ -0,0 +1,156 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "UiGuiIndentServer.h" + +#include <QTcpServer> +#include <QTcpSocket> +#include <QMessageBox> +#include <QtDebug> + +//! \defgroup grp_Server All concerning the server component. + +/*! + \class UiGuiIndentServer + \ingroup grp_Server + \brief UiGuiIndentServer is in such an early state, that even the communication + protocol isn't completely planned. So this class lacks documentation until + I really know where all this will lead to. + + The plan however is to have a server that receives commands for selecting an + indenter and perhaps load some by the user predefined indenter config file. Then + the client can send a text to it and will receive it formatted. + The idea behind that is to make UiGUIs use as plugin or whatever more flexible. + So the plugin is developed for Eclipse for example and it takes the client role, + making it possible to use UiGUI from within Eclipse. Choosing a network protocol + makes everything platform and programming language independent, so it doesn't + matter for which application the plugin/client is developed. +*/ + +UiGuiIndentServer::UiGuiIndentServer(void) : QObject() { + _tcpServer = NULL; + _currentClientConnection = NULL; + _readyForHandleRequest = false; +} + + +UiGuiIndentServer::~UiGuiIndentServer(void) { +} + + +void UiGuiIndentServer::startServer() { + if ( _tcpServer == NULL ) { + _tcpServer = new QTcpServer(this); + } + + if ( !_tcpServer->isListening() ) { + if ( !_tcpServer->listen(QHostAddress::Any, quint16(84484)) ) { + QMessageBox::critical( NULL, tr("UiGUI Server"), tr("Unable to start the server: %1.").arg(_tcpServer->errorString()) ); + return; + } + } + + connect( _tcpServer, SIGNAL(newConnection()), this, SLOT(handleNewConnection()) ); + _readyForHandleRequest = true; + _blockSize = 0; +} + + +void UiGuiIndentServer::stopServer() { + if ( _tcpServer != NULL ) { + _tcpServer->close(); + delete _tcpServer; + _tcpServer = NULL; + } + _currentClientConnection = NULL; + _readyForHandleRequest = false; +} + + +void UiGuiIndentServer::handleNewConnection() { + QTcpSocket *clientConnection = _tcpServer->nextPendingConnection(); + connect( clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()) ); + + connect( clientConnection, SIGNAL(readyRead()), this, SLOT(handleReceivedData()) ); +} + + +void UiGuiIndentServer::handleReceivedData() { + if ( !_readyForHandleRequest ) { + return; + } + + _currentClientConnection = qobject_cast<QTcpSocket*>( sender() ); + QString receivedData = ""; + + if ( _currentClientConnection != NULL ) { + QDataStream in(_currentClientConnection); + in.setVersion(QDataStream::Qt_4_0); + + if ( _blockSize == 0 ) { + if ( _currentClientConnection->bytesAvailable() < (int)sizeof(quint32) ) + return; + + in >> _blockSize; + } + + if ( _currentClientConnection->bytesAvailable() < _blockSize ) + return; + + QString receivedMessage; + in >> receivedMessage; + + _blockSize = 0; + + qDebug() << "receivedMessage: " << receivedMessage; + + if ( receivedMessage == "ts" ) { + sendMessage("Toll"); + } + else { + sendMessage("irgendwas"); + } + } +} + + +void UiGuiIndentServer::sendMessage( const QString &message ) { + _readyForHandleRequest = false; + + _dataToSend = ""; + QDataStream out(&_dataToSend, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_0); + out << (quint32)0; + out << message; + out.device()->seek(0); + out << (quint32)(_dataToSend.size() - sizeof(quint32)); + + connect(_currentClientConnection, SIGNAL(bytesWritten(qint64)), this, SLOT(checkIfReadyForHandleRequest())); + _currentClientConnection->write(_dataToSend); +} + + +void UiGuiIndentServer::checkIfReadyForHandleRequest() { + if ( _currentClientConnection->bytesToWrite() == 0 ) { + QString dataToSendStr = _dataToSend.right( _dataToSend.size() - sizeof(quint32) ); + qDebug() << "checkIfReadyForHandleRequest _dataToSend was: " << dataToSendStr; + disconnect(_currentClientConnection, SIGNAL(bytesWritten(qint64)), this, SLOT(checkIfReadyForHandleRequest())); + _readyForHandleRequest = true; + } +} diff --git a/src/UiGuiIndentServer.h b/src/UiGuiIndentServer.h new file mode 100755 index 0000000..837693a --- /dev/null +++ b/src/UiGuiIndentServer.h @@ -0,0 +1,55 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UIGUIINDENTSERVER_H
+#define UIGUIINDENTSERVER_H
+
+#include <QObject>
+
+class QTcpServer;
+class QTcpSocket;
+
+
+class UiGuiIndentServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ UiGuiIndentServer(void);
+ ~UiGuiIndentServer(void);
+
+public slots:
+ void startServer();
+ void stopServer();
+
+private slots:
+ void handleNewConnection();
+ void handleReceivedData();
+ void sendMessage(const QString &message);
+ void checkIfReadyForHandleRequest();
+
+private:
+ QTcpServer *_tcpServer;
+ QByteArray _dataToSend;
+ bool _readyForHandleRequest;
+ QTcpSocket *_currentClientConnection;
+ quint32 _blockSize;
+};
+
+#endif // UIGUIINDENTSERVER_H
diff --git a/src/UiGuiIniFileParser.cpp b/src/UiGuiIniFileParser.cpp new file mode 100755 index 0000000..84542e0 --- /dev/null +++ b/src/UiGuiIniFileParser.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "UiGuiIniFileParser.h" + +#include <QFile> +#include <QStringList> +#include <QVariant> +#include <QTextStream> + +//! \defgroup grp_Settings All concerning applications settings. + +/*! + \class UiGuiIniFileParser + \ingroup grp_Settings + \brief UiGuiIniFileParser is a simple ini file format parser. + + These ini files need to have key-value pairs in the style + "keyname=keyvalue". Groups can be defined by writing the groupname + in the style [groupname] before some key-value pairs. + + The reason why I use my own class instead of QSettings is mainly, that + QSettings always internally sorts the groups alphabetically and also + rewrites a settings file sorted. Very annoying for me. +*/ + +/*! + \brief Init and empty all needed lists and strings. + */ +UiGuiIniFileParser::UiGuiIniFileParser(void) { + init(); +} + + +/*! + \brief Directly loads and parses the file with name \a iniFileName. + */ +UiGuiIniFileParser::UiGuiIniFileParser(const QString &iniFileName) { + init(); + _iniFileName = iniFileName; + parseIniFile(); +} + + +void UiGuiIniFileParser::init() { + _sections.clear(); + _keyValueMap.clear(); + _iniFileName = ""; +} + + +UiGuiIniFileParser::~UiGuiIniFileParser(void) { +} + + +/*! + \brief Returns the group/section names in the same order as they occurr in the ini file as QStringList. + */ +QStringList UiGuiIniFileParser::childGroups() { + QStringList sectionsStringList; + + for( unsigned int i = 0; i < _sections.size(); i++ ) { + sectionsStringList << _sections[i]; + } + + return sectionsStringList; +} + + +/*! + \brief Returns the value of the defined \a keyName as QVariant. + + The \a keyName is assembled by a section name, a slash and the key name itself. + For example if you wish to access the value of the following setting: + <code>[NiceSection]</br>niceKeyName=2</code> you would have to call + value("NiceSection/niceKeyName"). + */ +QVariant UiGuiIniFileParser::value(const QString &keyName, const QString &defaultValue) { + return _keyValueMap.value( keyName, defaultValue ); +} + + +/*! + \brief Parses the ini file and stores the key value pairs in the internal vectors \a keys and \a values. + */ +void UiGuiIniFileParser::parseIniFile() { + QFile iniFile(_iniFileName); + + if ( iniFile.open(QFile::ReadOnly) ) { + // Clear the vectors holding the keys and values. + _sections.clear(); + _keyValueMap.clear(); + + QTextStream iniFileStream( &iniFile ); + QString line; + QString currentSectionName = ""; + QString keyName = ""; + QString valueAsString = ""; + + while ( !iniFileStream.atEnd() ) { + line = iniFileStream.readLine().trimmed(); + + // Test if the read line is a section name and if so remeber it. + if ( line.startsWith("[") && line.endsWith("]") ) { + currentSectionName = line.remove(0, 1); + currentSectionName.chop(1); + + // Store the section name. + _sections.push_back( currentSectionName ); + } + // Otherwise test whether the line has a assign char + else if ( line.contains("=") ) { + int indexOfFirstAssign = line.indexOf("="); + keyName = line.left(indexOfFirstAssign); + + if ( !keyName.isEmpty() ) { + valueAsString = line.remove(0, indexOfFirstAssign+1); + // Remove any existing double quotes from the value. + if ( valueAsString.startsWith("\"") && valueAsString.endsWith("\"") ) { + valueAsString = valueAsString.remove(0, 1); + valueAsString.chop(1); + } + + // Prepend an eventually section name to the key name. + if ( !currentSectionName.isEmpty() ) { + keyName = currentSectionName + "/" + keyName; + } + + // Store the key and value in the map. + _keyValueMap.insert(keyName, valueAsString ); + } + } + } + } +} diff --git a/src/UiGuiIniFileParser.h b/src/UiGuiIniFileParser.h new file mode 100755 index 0000000..cbbc3c9 --- /dev/null +++ b/src/UiGuiIniFileParser.h @@ -0,0 +1,52 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UIGUIINIFILEPARSER_H
+#define UIGUIINIFILEPARSER_H
+
+#include <QMap>
+#include <QString>
+
+#include <vector>
+
+class QStringList;
+class QVariant;
+
+
+class UiGuiIniFileParser
+{
+public:
+ UiGuiIniFileParser(void);
+ UiGuiIniFileParser(const QString &iniFileName);
+ ~UiGuiIniFileParser(void);
+ QVariant value(const QString &keyName, const QString &defaultValue = "");
+ QStringList childGroups();
+
+protected:
+ void init();
+
+private:
+ void parseIniFile();
+
+ QString _iniFileName;
+ std::vector<QString> _sections;
+ QMap<QString, QVariant> _keyValueMap;
+};
+
+#endif // UIGUIINIFILEPARSER_H
diff --git a/src/UiGuiSettings.cpp b/src/UiGuiSettings.cpp new file mode 100755 index 0000000..f997ec3 --- /dev/null +++ b/src/UiGuiSettings.cpp @@ -0,0 +1,688 @@ +/***************************************************************************
+* Copyright (C) 2006-2012 by Thomas Schweitzer *
+* thomas-schweitzer(at)arcor.de *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License version 2.0 as *
+* published by the Free Software Foundation. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program in the file LICENSE.GPL; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#include "UiGuiSettings.h"
+
+#include "SettingsPaths.h"
+
+#include <QSettings>
+#include <QPoint>
+#include <QSize>
+#include <QDir>
+#include <QDate>
+#include <QStringList>
+#include <QCoreApplication>
+#include <QMetaMethod>
+#include <QMetaProperty>
+#include <QWidget>
+
+//! \defgroup grp_Settings All concerning the settings.
+
+/*!
+ \class UiGuiSettings
+ \ingroup grp_Settings
+ \brief Handles the settings of the program. Reads them on startup and saves them on exit.
+ Is a singleton class and can only be accessed via getInstance().
+*/
+
+// Inits the single class instance pointer.
+QWeakPointer<UiGuiSettings> UiGuiSettings::_instance;
+
+
+/*!
+ \brief The constructor for the settings.
+*/
+UiGuiSettings::UiGuiSettings() : QObject() {
+ // Create the main application settings object from the UniversalIndentGUI.ini file.
+ _qsettings = new QSettings(SettingsPaths::getSettingsPath() + "/UniversalIndentGUI.ini", QSettings::IniFormat, this);
+
+ _indenterDirctoryStr = SettingsPaths::getGlobalFilesPath() + "/indenters";
+ readAvailableTranslations();
+ initSettings();
+}
+
+
+/*!
+ \brief Returns the instance of the settings class. If no instance exists, ONE will be created.
+ */
+QSharedPointer<UiGuiSettings> UiGuiSettings::getInstance() {
+ QSharedPointer<UiGuiSettings> sharedInstance = _instance.toStrongRef();
+ if ( sharedInstance.isNull() ) {
+ // Create the settings object, which loads all UiGui settings from a file.
+ sharedInstance = QSharedPointer<UiGuiSettings>(new UiGuiSettings());
+ _instance = sharedInstance.toWeakRef();
+ }
+
+ return sharedInstance;
+}
+
+
+/*!
+ \brief The destructor saves the settings to a file.
+ */
+UiGuiSettings::~UiGuiSettings() {
+ // Convert the language setting from an integer index to a string.
+ int index = _qsettings->value("UniversalIndentGUI/language", 0).toInt();
+ if ( index < 0 || index >= _availableTranslations.size() )
+ index = 0;
+
+ _qsettings->setValue( "UniversalIndentGUI/language", _availableTranslations.at(index) );
+}
+
+
+/*!
+ \brief Scans the translations directory for available translation files and
+ stores them in the QList \a _availableTranslations.
+ */
+void UiGuiSettings::readAvailableTranslations() {
+ QString languageShort;
+ QStringList languageFileList;
+
+ // English is the default language. A translation file does not exist but to have a menu entry, added here.
+ languageFileList << "universalindent_en.qm";
+
+ // Find all translation files in the "translations" directory.
+ QDir translationDirectory = QDir( SettingsPaths::getGlobalFilesPath() + "/translations" );
+ languageFileList << translationDirectory.entryList( QStringList("universalindent_*.qm") );
+
+ // Loop for each found translation file
+ foreach ( languageShort, languageFileList ) {
+ // Remove the leading string "universalindent_" from the filename.
+ languageShort.remove(0,16);
+ // Remove trailing file extension ".qm".
+ languageShort.chop(3);
+
+ _availableTranslations.append(languageShort);
+ }
+}
+
+
+/*!
+ \brief Returns a list of the mnemonics of the available translations.
+ */
+QStringList UiGuiSettings::getAvailableTranslations() {
+ return _availableTranslations;
+}
+
+
+/*!
+ \brief Returns the value of the by \a settingsName defined setting as QVariant.
+
+ If the named setting does not exist, 0 is being returned.
+*/
+QVariant UiGuiSettings::getValueByName(QString settingName) {
+ return _qsettings->value("UniversalIndentGUI/" + settingName);
+}
+
+
+/*!
+ \brief Loads the settings for the main application.
+
+ Settings are for example last selected indenter, last loaded source code file and so on.
+*/
+bool UiGuiSettings::initSettings()
+{
+ // Read the version string saved in the settings file.
+ _qsettings->setValue( "UniversalIndentGUI/version", _qsettings->value("UniversalIndentGUI/version", "") );
+
+ // Read windows last size and position from the settings file.
+ _qsettings->setValue( "UniversalIndentGUI/maximized", _qsettings->value("UniversalIndentGUI/maximized", false) );
+ _qsettings->setValue( "UniversalIndentGUI/position", _qsettings->value("UniversalIndentGUI/position", QPoint(50, 50)) );
+ _qsettings->setValue( "UniversalIndentGUI/size", _qsettings->value("UniversalIndentGUI/size", QSize(800, 600)) );
+
+ // Read last selected encoding for the opened source code file.
+ _qsettings->setValue( "UniversalIndentGUI/encoding", _qsettings->value("UniversalIndentGUI/encoding", "UTF-8") );
+
+ // Read maximum length of list for recently opened files.
+ _qsettings->setValue( "UniversalIndentGUI/recentlyOpenedListSize", _qsettings->value("UniversalIndentGUI/recentlyOpenedListSize", 5) );
+
+ // Read if last opened source code file should be loaded on startup.
+ _qsettings->setValue( "UniversalIndentGUI/loadLastSourceCodeFileOnStartup", _qsettings->value("UniversalIndentGUI/loadLastSourceCodeFileOnStartup", true) );
+
+ // Read last opened source code file from the settings file.
+ _qsettings->setValue( "UniversalIndentGUI/lastSourceCodeFile", _qsettings->value("UniversalIndentGUI/lastSourceCodeFile", _indenterDirctoryStr+"/example.cpp") );
+
+ // Read last selected indenter from the settings file.
+ int selectedIndenter = _qsettings->value("UniversalIndentGUI/selectedIndenter", 0).toInt();
+ if ( selectedIndenter < 0 ) {
+ selectedIndenter = 0;
+ }
+ _qsettings->setValue( "UniversalIndentGUI/selectedIndenter", selectedIndenter );
+
+ // Read if syntax highlighting is enabled.
+ _qsettings->setValue( "UniversalIndentGUI/SyntaxHighlightingEnabled", _qsettings->value("UniversalIndentGUI/SyntaxHighlightingEnabled", true) );
+
+ // Read if white space characters should be displayed.
+ _qsettings->setValue( "UniversalIndentGUI/whiteSpaceIsVisible", _qsettings->value("UniversalIndentGUI/whiteSpaceIsVisible", false) );
+
+ // Read if indenter parameter tool tips are enabled.
+ _qsettings->setValue( "UniversalIndentGUI/indenterParameterTooltipsEnabled", _qsettings->value("UniversalIndentGUI/indenterParameterTooltipsEnabled", true) );
+
+ // Read the tab width from the settings file.
+ _qsettings->setValue( "UniversalIndentGUI/tabWidth", _qsettings->value("UniversalIndentGUI/tabWidth", 4) );
+
+ // Read the last selected language and stores the index it has in the list of available translations.
+ _qsettings->setValue( "UniversalIndentGUI/language", _availableTranslations.indexOf( _qsettings->value("UniversalIndentGUI/language", "").toString() ) );
+
+ // Read the update check settings from the settings file.
+ _qsettings->setValue( "UniversalIndentGUI/CheckForUpdate", _qsettings->value("UniversalIndentGUI/CheckForUpdate", false) );
+ _qsettings->setValue( "UniversalIndentGUI/LastUpdateCheck", _qsettings->value("UniversalIndentGUI/LastUpdateCheck", QDate(1900,1,1)) );
+
+ // Read the main window state.
+ _qsettings->setValue( "UniversalIndentGUI/MainWindowState", _qsettings->value("UniversalIndentGUI/MainWindowState", QByteArray()) );
+
+ return true;
+}
+
+
+/*!
+ \brief Register the by \a propertyName defined property of \a obj to be connected to the setting defined by \a settingName.
+
+ The \a propertyName must be one of those that are listed in the Qt "Properties" documentation section of a Qt Object.
+ All further needed info is retrieved via the \a obj's MetaObject, like the to the property bound signal.
+ */
+bool UiGuiSettings::registerObjectProperty( QObject *obj, const QString &propertyName, const QString &settingName )
+{
+ const QMetaObject *metaObject = obj->metaObject();
+ bool connectSuccess = false;
+
+ // Connect to the objects destroyed signal, so that it will be correctly unregistered.
+ connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*)));
+
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( connectSuccess && indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+
+ // Connect to the property's value changed signal.
+ if ( mProp.hasNotifySignal() ) {
+ QMetaMethod signal = mProp.notifySignal();
+ //QString teststr = qPrintable(SIGNAL() + QString(signal.signature()));
+ // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL.
+ connectSuccess = connect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange()));
+ }
+
+ if ( connectSuccess ) {
+ _registeredObjectProperties[obj] = QStringList() << propertyName << settingName;
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*)));
+ return false;
+ }
+
+ // If setting already exists, set the objects property to the setting value.
+ if ( _qsettings->contains("UniversalIndentGUI/" + settingName) ) {
+ mProp.write(obj, _qsettings->value("UniversalIndentGUI/" + settingName));
+ }
+ // Otherwise add the setting and set it to the value of the objects property.
+ else {
+ _qsettings->setValue("UniversalIndentGUI/" + settingName, mProp.read(obj));
+ }
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectProperty(QObject*)));
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ \brief Searches the child QObjects of \a obj for a property name and setting name definition within
+ their custom properties and registers this property name to that setting name if both were found.
+
+ The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName",
+ where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and
+ "connectedSettingName" is the name of a setting here within UiGuiSettings. If the mentioned setting
+ name doesn't exist, it will be created.
+
+ Returns true, if all found property and setting definitions could be successfully registered.
+ Returns false, if any of those registrations fails.
+ */
+bool UiGuiSettings::registerObjectPropertyRecursive(QObject *obj) {
+ return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::registerObjectProperty);
+}
+
+
+/*!
+ \brief Assigns the by \a settingName defined setting value to the by \a propertyName defined property of \a obj.
+
+ Returns true, if the value could be assigned, otherwise returns false, which is the case if settingName doesn't exist
+ within the settings or if the mentioned propertyName wasn't found for the \a obj.
+ */
+bool UiGuiSettings::setObjectPropertyToSettingValue( QObject *obj, const QString &propertyName, const QString &settingName )
+{
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+
+ // If setting already exists, set the objects property to the setting value.
+ if ( _qsettings->contains("UniversalIndentGUI/" + settingName) ) {
+ mProp.write(obj, _qsettings->value("UniversalIndentGUI/" + settingName));
+ }
+ // The setting didn't exist so return that setting the objects property failed.
+ else {
+ //TODO: Write a debug warning to the log.
+ return false;
+ }
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ \brief Searches the child QObjects of \a obj for a property name and setting name definition within
+ their custom properties and sets each property to settings value.
+
+ The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName",
+ where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and
+ "connectedSettingName" is the name of a setting here within UiGuiSettings.
+
+ Returns true, if all found property and setting definitions could be successfully registered.
+ Returns false, if any of those registrations fails.
+ */
+bool UiGuiSettings::setObjectPropertyToSettingValueRecursive(QObject *obj) {
+ return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::setObjectPropertyToSettingValue);
+}
+
+
+/*!
+ \brief Assigns the by \a propertyName defined property's value of \a obj to the by \a settingName defined setting.
+
+ If the \a settingName didn't exist yet, it will be created.
+
+ Returns true, if the value could be assigned, otherwise returns false, which is the case if the mentioned
+ propertyName wasn't found for the \a obj.
+ */
+bool UiGuiSettings::setSettingToObjectPropertyValue( QObject *obj, const QString &propertyName, const QString &settingName )
+{
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+
+ setValueByName(settingName, mProp.read(obj));
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ \brief Searches the child QObjects of \a obj for a property name and setting name definition within
+ their custom properties and sets each setting to the property value.
+
+ The custom properties, for which are searched, are "connectedPropertyName" and "connectedSettingName",
+ where "connectedPropertyName" is the name of a QObject property as it is documented in the QtDocs, and
+ "connectedSettingName" is the name of a setting here within UiGuiSettings. If the settingName
+ didn't exist yet, it will be created.
+
+ Returns true, if all found property and setting definitions could be successfully registered.
+ Returns false, if any of those registrations fails.
+ */
+bool UiGuiSettings::setSettingToObjectPropertyValueRecursive(QObject *obj) {
+ return checkCustomPropertiesAndCallFunction(obj, &UiGuiSettings::setSettingToObjectPropertyValue);
+}
+
+
+/*!
+ \brief Iterates over all \a objs child QObjects and checks whether they have the custom properties
+ "connectedPropertyName" and "connectedSettingName" set. If both are set, it invokes the \a callBackFunc
+ with both.
+ */
+bool UiGuiSettings::checkCustomPropertiesAndCallFunction(QObject *obj, bool (UiGuiSettings::*callBackFunc)(QObject *obj, const QString &propertyName, const QString &settingName)) {
+ bool success = true;
+
+ // Find all widgets that have PropertyName and SettingName defined in their style sheet.
+ QList<QObject *> allObjects = obj->findChildren<QObject *>();
+ foreach (QObject *object, allObjects) {
+ QString propertyName = object->property("connectedPropertyName").toString();
+ QString settingName = object->property("connectedSettingName").toString();
+
+ // If property and setting name were found, register that widget with the settings.
+ if ( !propertyName.isEmpty() && !settingName.isEmpty() ) {
+ success &= (this->*callBackFunc)( object, propertyName, settingName );
+ }
+ }
+
+ return success;
+}
+
+
+/*!
+ \brief The with a certain property registered \a obj gets unregistered.
+ */
+void UiGuiSettings::unregisterObjectProperty(QObject *obj) {
+ if ( _registeredObjectProperties.contains(obj) ) {
+ const QMetaObject *metaObject = obj->metaObject();
+ QString propertyName = _registeredObjectProperties[obj].first();
+ QString settingName = _registeredObjectProperties[obj].last();
+
+ bool connectSuccess = false;
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+
+ // Disconnect to the property's value changed signal.
+ if ( mProp.hasNotifySignal() ) {
+ QMetaMethod signal = mProp.notifySignal();
+ // The command "SIGNAL() + QString(signal.signature())" assembles the signal methods signature to a valid Qt SIGNAL.
+ connectSuccess = disconnect(obj, qPrintable(SIGNAL() + QString(signal.signature())), this, SLOT(handleObjectPropertyChange()));
+ }
+ }
+ _registeredObjectProperties.remove(obj);
+ }
+}
+
+
+/*!
+ \brief Registers a slot form the \a obj by its \a slotName to be invoked, if the by \a settingName defined
+ setting changes.
+
+ The registered slot may have no parameters or exactly one. If it accepts one parameter, whenever the setting
+ \a settingName changes the slot gets tried to be invoked with the settings value as parameter. This only works,
+ if the slot parameter is of the same type as the setting.
+ */
+bool UiGuiSettings::registerObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) {
+
+ const QMetaObject *metaObject = obj->metaObject();
+
+ bool connectSuccess = false;
+ // Connect to the objects destroyed signal, so that it will be correctly unregistered.
+ connectSuccess = connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*)));
+
+ QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) );
+ int indexOfMethod = metaObject->indexOfMethod( qPrintable(normalizedSlotName) );
+ if ( connectSuccess && indexOfMethod > -1 ) {
+ QMetaMethod mMethod = metaObject->method(indexOfMethod);
+ //QMetaMethod::Access access = mMethod.access();
+ //QMetaMethod::MethodType methType = mMethod.methodType();
+
+ // Since the method can at maximum be invoked with the setting value as argument,
+ // only methods taking max one argument are allowed.
+ if ( mMethod.parameterTypes().size() <= 1 ) {
+ _registeredObjectSlots.insert(obj, QStringList() << normalizedSlotName << settingName);
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*)));
+ return false;
+ }
+ }
+ else {
+ //TODO: Write a debug warning to the log.
+ disconnect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(unregisterObjectSlot(QObject*)));
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ \brief If \a obj, \a slotName and \a settingName are given, that certain connection is unregistered.
+ If only \a obj is given, all to this object registered slot-setting connections are unregistered.
+ */
+void UiGuiSettings::unregisterObjectSlot(QObject *obj, const QString &slotName, const QString &settingName) {
+ //const QMetaObject *metaObject = obj->metaObject();
+ QString normalizedSlotName = QMetaObject::normalizedSignature( qPrintable(slotName) );
+ QMutableMapIterator<QObject*, QStringList> it(_registeredObjectSlots);
+ while (it.hasNext()) {
+ it.next();
+ if (it.key() == obj && slotName.isEmpty() && settingName.isEmpty())
+ it.remove();
+ else if (it.key() == obj && it.value().first() == slotName && it.value().last() == settingName)
+ it.remove();
+ }
+}
+
+
+/*!
+ \brief This private slot gets invoked whenever a registered objects property changes
+ and distributes the new value to all other to the same settingName registered objects.
+ */
+void UiGuiSettings::handleObjectPropertyChange() {
+ QObject *obj = QObject::sender();
+ QString className = obj->metaObject()->className();
+ const QMetaObject *metaObject = obj->metaObject();
+ QString propertyName = _registeredObjectProperties[obj].first();
+ QString settingName = _registeredObjectProperties[obj].last();
+
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+ setValueByName(settingName, mProp.read(obj));
+ }
+}
+
+
+/*!
+ \brief Sets the setting defined by \a settingName to \a value.
+
+ When setting a changed value, all to this settingName registered objects get
+ the changed value set too.
+ If the \a settingName didn't exist yet, it will be created.
+ */
+void UiGuiSettings::setValueByName(const QString &settingName, const QVariant &value) {
+ // Do the updating only, if the setting was really changed.
+ if ( _qsettings->value("UniversalIndentGUI/" + settingName) != value ) {
+ _qsettings->setValue("UniversalIndentGUI/" + settingName, value);
+
+ // Set the new value for all registered object properties for settingName.
+ for ( QMap<QObject*, QStringList>::ConstIterator it = _registeredObjectProperties.begin(); it != _registeredObjectProperties.end(); ++it ) {
+ if ( it.value().last() == settingName ) {
+ QObject *obj = it.key();
+ const QMetaObject *metaObject = obj->metaObject();
+ QString propertyName = it.value().first();
+
+ int indexOfProp = metaObject->indexOfProperty( qPrintable(propertyName) );
+ if ( indexOfProp > -1 ) {
+ QMetaProperty mProp = metaObject->property(indexOfProp);
+ mProp.write(obj, value);
+ }
+ }
+ }
+
+ // Invoke all registered object methods for settingName.
+ for ( QMap<QObject*, QStringList>::ConstIterator it = _registeredObjectSlots.begin(); it != _registeredObjectSlots.end(); ++it ) {
+ if ( it.value().last() == settingName ) {
+ QObject *obj = it.key();
+ const QMetaObject *metaObject = obj->metaObject();
+ QString slotName = it.value().first();
+
+ int indexOfMethod = metaObject->indexOfMethod( qPrintable(slotName) );
+ if ( indexOfMethod > -1 ) {
+ QMetaMethod mMethod = metaObject->method(indexOfMethod);
+ //QMetaMethod::Access access = mMethod.access();
+ //QMetaMethod::MethodType methType = mMethod.methodType();
+
+ bool success = false;
+
+ // Handle registered slots taking one parameter.
+ if ( mMethod.parameterTypes().size() == 1 ) {
+ if ( mMethod.parameterTypes().first() == value.typeName() ) {
+ success = invokeMethodWithValue(obj, mMethod, value);
+ }
+ }
+ // Handle registered slots taking zero parameters.
+ else {
+ success = mMethod.invoke( obj, Qt::DirectConnection );
+ }
+
+ if ( success == false ) {
+ // TODO: Write a warning to the log if no success.
+ }
+ }
+ }
+ }
+ }
+}
+
+
+#include <QBitArray>
+#include <QBitmap>
+#include <QBrush>
+#include <QCursor>
+#include <QDateTime>
+#include <QFont>
+#include <QIcon>
+#include <QKeySequence>
+#include <QLocale>
+#include <QPalette>
+#include <QPen>
+#include <QSizePolicy>
+#include <QTextFormat>
+#include <QTextLength>
+#include <QUrl>
+#if QT_VERSION >= 0x040600
+#include <QMatrix4x4>
+#include <QVector2D>
+#endif
+
+bool UiGuiSettings::invokeMethodWithValue( QObject *obj, QMetaMethod mMethod, QVariant value )
+{
+ switch (value.type()) {
+ case QVariant::BitArray :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitArray, value.toBitArray()) );
+ case QVariant::Bitmap :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBitmap, value.value<QBitmap>()) );
+ case QVariant::Bool :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(bool, value.toBool()) );
+ case QVariant::Brush :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QBrush, value.value<QBrush>()) );
+ case QVariant::ByteArray :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QByteArray, value.toByteArray()) );
+ case QVariant::Char :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QChar, value.toChar()) );
+ case QVariant::Color :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QColor, value.value<QColor>()) );
+ case QVariant::Cursor :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QCursor, value.value<QCursor>()) );
+ case QVariant::Date :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDate, value.toDate()) );
+ case QVariant::DateTime :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QDateTime, value.toDateTime()) );
+ case QVariant::Double :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(double, value.toDouble()) );
+ case QVariant::Font :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QFont, value.value<QFont>()) );
+ case QVariant::Hash :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantHash, value.toHash()) );
+ case QVariant::Icon :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QIcon, value.value<QIcon>()) );
+ case QVariant::Image :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QImage, value.value<QImage>()) );
+ case QVariant::Int :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(int, value.toInt()) );
+ case QVariant::KeySequence :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QKeySequence, value.value<QKeySequence>()) );
+ case QVariant::Line :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLine, value.toLine()) );
+ case QVariant::LineF :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLineF, value.toLineF()) );
+ case QVariant::List :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantList, value.toList()) );
+ case QVariant::Locale :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QLocale, value.toLocale()) );
+ case QVariant::LongLong :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qlonglong, value.toLongLong()) );
+ case QVariant::Map :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVariantMap, value.toMap()) );
+ case QVariant::Matrix :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix, value.value<QMatrix>()) );
+ case QVariant::Transform :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTransform, value.value<QTransform>()) );
+#if QT_VERSION >= 0x040600
+ case QVariant::Matrix4x4 :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QMatrix4x4, value.value<QMatrix4x4>()) );
+#endif
+ case QVariant::Palette :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPalette, value.value<QPalette>()) );
+ case QVariant::Pen :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPen, value.value<QPen>()) );
+ case QVariant::Pixmap :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPixmap, value.value<QPixmap>()) );
+ case QVariant::Point :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPoint, value.toPoint()) );
+ // case QVariant::PointArray :
+ // return Q_ARG(QPointArray, value.value<QPointArray>()) );
+ case QVariant::PointF :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPointF, value.toPointF()) );
+ case QVariant::Polygon :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QPolygon, value.value<QPolygon>()) );
+#if QT_VERSION >= 0x040600
+ case QVariant::Quaternion :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QQuaternion, value.value<QQuaternion>()) );
+#endif
+ case QVariant::Rect :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRect, value.toRect()) );
+ case QVariant::RectF :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRectF, value.toRectF()) );
+ case QVariant::RegExp :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegExp, value.toRegExp()) );
+ case QVariant::Region :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QRegion, value.value<QRegion>()) );
+ case QVariant::Size :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSize, value.toSize()) );
+ case QVariant::SizeF :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizeF, value.toSizeF()) );
+ case QVariant::SizePolicy :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QSizePolicy, value.value<QSizePolicy>()) );
+ case QVariant::String :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QString, value.toString()) );
+ case QVariant::StringList :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QStringList, value.toStringList()) );
+ case QVariant::TextFormat :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextFormat, value.value<QTextFormat>()) );
+ case QVariant::TextLength :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTextLength, value.value<QTextLength>()) );
+ case QVariant::Time :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QTime, value.toTime()) );
+ case QVariant::UInt :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(uint, value.toUInt()) );
+ case QVariant::ULongLong :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(qulonglong, value.toULongLong()) );
+ case QVariant::Url :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QUrl, value.toUrl()) );
+#if QT_VERSION >= 0x040600
+ case QVariant::Vector2D :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector2D, value.value<QVector2D>()) );
+ case QVariant::Vector3D :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector3D, value.value<QVector3D>()) );
+ case QVariant::Vector4D :
+ return mMethod.invoke( obj, Qt::DirectConnection, Q_ARG(QVector4D, value.value<QVector4D>()) );
+#endif
+ default:
+ return false;
+ }
+}
diff --git a/src/UiGuiSettings.h b/src/UiGuiSettings.h new file mode 100755 index 0000000..54f4dca --- /dev/null +++ b/src/UiGuiSettings.h @@ -0,0 +1,83 @@ +/***************************************************************************
+* Copyright (C) 2006-2012 by Thomas Schweitzer *
+* thomas-schweitzer(at)arcor.de *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License version 2.0 as *
+* published by the Free Software Foundation. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program in the file LICENSE.GPL; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+
+#ifndef UIGUISETTINGS_H
+#define UIGUISETTINGS_H
+
+#include <QObject>
+#include <QStringList>
+#include <QMultiMap>
+#include <QSharedPointer>
+
+class QSettings;
+
+
+class UiGuiSettings : public QObject
+{
+ Q_OBJECT
+private:
+ UiGuiSettings();
+ static QWeakPointer<UiGuiSettings> _instance;
+
+public:
+ static QSharedPointer<UiGuiSettings> getInstance();
+ ~UiGuiSettings();
+
+ bool registerObjectProperty(QObject *obj, const QString &propertyName, const QString &settingName);
+ bool registerObjectPropertyRecursive(QObject *obj);
+ bool setObjectPropertyToSettingValue(QObject *obj, const QString &propertyName, const QString &settingName);
+ bool setObjectPropertyToSettingValueRecursive(QObject *obj);
+ bool setSettingToObjectPropertyValue(QObject *obj, const QString &propertyName, const QString &settingName);
+ bool setSettingToObjectPropertyValueRecursive(QObject *obj);
+ bool registerObjectSlot(QObject *obj, const QString &slotName, const QString &settingName);
+ QVariant getValueByName(QString settingName);
+ QStringList getAvailableTranslations();
+
+public slots:
+ void setValueByName(const QString &settingName, const QVariant &value);
+ void unregisterObjectProperty(QObject *obj);
+ void unregisterObjectSlot(QObject *obj, const QString &slotName = "", const QString &settingName = "");
+
+protected:
+ bool initSettings();
+ bool invokeMethodWithValue(QObject *obj, QMetaMethod mMethod, QVariant value);
+ bool checkCustomPropertiesAndCallFunction(QObject *obj, bool (UiGuiSettings::*callBackFunc)(QObject *obj, const QString &propertyName, const QString &settingName));
+
+private slots:
+ void handleObjectPropertyChange();
+
+private:
+ void readAvailableTranslations();
+
+ //! Stores the mnemonics of the available translations.
+ QStringList _availableTranslations;
+
+ //! The settings file.
+ QSettings *_qsettings;
+
+ //! Maps an QObject to a string list containing the property name and the associated setting name.
+ QMap<QObject*, QStringList> _registeredObjectProperties;
+
+ //! Maps QObjects to a string list containing the method name and the associated setting name.
+ QMultiMap<QObject*, QStringList> _registeredObjectSlots;
+
+ QString _indenterDirctoryStr;
+};
+
+#endif // UIGUISETTINGS_H
diff --git a/src/UiGuiSettingsDialog.cpp b/src/UiGuiSettingsDialog.cpp new file mode 100755 index 0000000..7c7001f --- /dev/null +++ b/src/UiGuiSettingsDialog.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** +* Copyright (C) 2006-2012 by Thomas Schweitzer * +* thomas-schweitzer(at)arcor.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License version 2.0 as * +* published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program in the file LICENSE.GPL; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "UiGuiSettingsDialog.h" +#include "ui_UiGuiSettingsDialog.h" + +#include "UiGuiSettings.h" + +/*! + \class UiGuiSettingsDialog + \ingroup grp_Settings + \brief Displays a dialog window with settings for UniversalIndentGUI +*/ + +/*! + \brief The constructor calls the setup function for the ui created by uic. +*/ +UiGuiSettingsDialog::UiGuiSettingsDialog(QWidget* parent, QSharedPointer<UiGuiSettings> settings) : QDialog(parent) { + // Remember pointer to the UiGuiSettings object. + _settings = settings; + + // Init the user interface created by the UIC. + _settingsDialogForm = new Ui::SettingsDialog(); + _settingsDialogForm->setupUi(this); + + //TODO: This call has to be removed when the properties for the highlighters can be set + // with the settings dialog. + _settingsDialogForm->groupBoxSyntaxHighlighterProperties->setToolTip( "(Will be implemented soon)" + _settingsDialogForm->groupBoxSyntaxHighlighterProperties->toolTip() ); + + // Connect the accepted signal to own function, to write values back to the UiGuiSettings object. + connect(this, SIGNAL(accepted()), this, SLOT(writeWidgetValuesToSettings()) ); + + // Init the language selection combobox. + initTranslationSelection(); +} + + +/*! + \brief By calling this function the combobox for selecting the application language will + be initialized. + + Also the translation itself will be reinitialized. + */ +void UiGuiSettingsDialog::initTranslationSelection() { + // First empty the combo box. + _settingsDialogForm->languageSelectionComboBox->clear(); + + // Now add an entry into the box for every language short. + foreach (QString languageShort, _settings->getAvailableTranslations() ) { + // Identify the language mnemonic and set the full name. + if ( languageShort == "en" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("English") ); + } + else if ( languageShort == "fr" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("French") ); + } + else if ( languageShort == "de" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("German") ); + } + else if ( languageShort == "zh_TW" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Chinese (Taiwan)") ); + } + else if ( languageShort == "ja" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Japanese") ); + } + else if ( languageShort == "ru" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Russian") ); + } + else if ( languageShort == "uk" ) { + _settingsDialogForm->languageSelectionComboBox->addItem( QIcon(QString(":/language/language-"+languageShort+".png")), tr("Ukrainian") ); + } + + else { + _settingsDialogForm->languageSelectionComboBox->addItem( tr("Unknown language mnemonic ") + languageShort ); + } + } +} + + +/*! + \brief Displays the dialog by calling the dialogs exec function. + + Before it gets all the values needed from the UiGuiSettings object. + */ +int UiGuiSettingsDialog::showDialog() { + // Init all settings dialog objects with values from settings. + _settings->setObjectPropertyToSettingValueRecursive(this); + + // Execute the dialog. + return exec(); +} + + +/*! + \brief This slot is called when the dialog box is closed by pressing the Ok button. + + Writes all settings to the UiGuiSettings object. + */ +void UiGuiSettingsDialog::writeWidgetValuesToSettings() { + // Write settings dialog object values to settings. + _settings->setSettingToObjectPropertyValueRecursive(this); +} + + +/*! + \brief Catches language change events and retranslates all needed widgets. + */ +void UiGuiSettingsDialog::changeEvent(QEvent *event) { + if (event->type() == QEvent::LanguageChange) { + _settingsDialogForm->retranslateUi(this); + // If this is not explicit set here, Qt < 4.3.0 does not translate the buttons. + _settingsDialogForm->buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::NoButton|QDialogButtonBox::Ok); + + //TODO: This has to be removed when the properties for the highlighters can be set. + _settingsDialogForm->groupBoxSyntaxHighlighterProperties->setToolTip( "(Will be implemented soon)" + _settingsDialogForm->groupBoxSyntaxHighlighterProperties->toolTip() ); + + QStringList languageShortList = _settings->getAvailableTranslations(); + + // Now retranslate every entry in the language selection box. + for (int i = 0; i < languageShortList.size(); i++ ) { + QString languageShort = languageShortList.at(i); + + // Identify the language mnemonic and set the full name. + if ( languageShort == "en" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("English") ); + } + else if ( languageShort == "fr" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("French") ); + } + else if ( languageShort == "de" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("German") ); + } + else if ( languageShort == "zh_TW" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("Chinese (Taiwan)") ); + } + else if ( languageShort == "ja" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("Japanese") ); + } + else if ( languageShort == "ru" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("Russian") ); + } + else if ( languageShort == "uk" ) { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("Ukrainian") ); + } + else { + _settingsDialogForm->languageSelectionComboBox->setItemText( i, tr("Unknown language mnemonic ") + languageShort ); + } + } + } + else { + QWidget::changeEvent(event); + } +} diff --git a/src/UiGuiSettingsDialog.h b/src/UiGuiSettingsDialog.h new file mode 100755 index 0000000..582d436 --- /dev/null +++ b/src/UiGuiSettingsDialog.h @@ -0,0 +1,54 @@ +/*************************************************************************** +* Copyright (C) 2006-2012 by Thomas Schweitzer * +* thomas-schweitzer(at)arcor.de * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License version 2.0 as * +* published by the Free Software Foundation. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program in the file LICENSE.GPL; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#ifndef UIGUISETTINGSDIALOG_H +#define UIGUISETTINGSDIALOG_H + +#include <QDialog> + +#include "UiGuiSettings.h" + +namespace Ui { + class SettingsDialog; +} + + +class UiGuiSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + UiGuiSettingsDialog(QWidget* parent, QSharedPointer<UiGuiSettings> settings); + +public slots: + int showDialog(); + +private slots: + void writeWidgetValuesToSettings(); + +private: + Ui::SettingsDialog *_settingsDialogForm; + + void changeEvent(QEvent *event); + void initTranslationSelection(); + + QSharedPointer<UiGuiSettings> _settings; +}; + +#endif // UIGUISETTINGSDIALOG_H diff --git a/src/UiGuiSettingsDialog.ui b/src/UiGuiSettingsDialog.ui new file mode 100755 index 0000000..e3c5f7a --- /dev/null +++ b/src/UiGuiSettingsDialog.ui @@ -0,0 +1,625 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SettingsDialog</class> + <widget class="QDialog" name="SettingsDialog"> + <property name="windowModality"> + <enum>Qt::ApplicationModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>503</width> + <height>336</height> + </rect> + </property> + <property name="windowTitle"> + <string>Settings</string> + </property> + <property name="windowIcon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/preferences-system.png</normaloff>:/mainWindow/preferences-system.png</iconset> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/settingsDialog/applications-system.png</normaloff>:/settingsDialog/applications-system.png</iconset> + </attribute> + <attribute name="title"> + <string>Common</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="toolTip"> + <string>Displays all available translations for UniversalIndentGui and lets you choose one.</string> + </property> + <property name="text"> + <string>Application language</string> + </property> + <property name="buddy"> + <cstring>languageSelectionComboBox</cstring> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="languageSelectionComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Displays all available translations for UniversalIndentGui and lets you choose one.</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">language</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">currentIndex</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="loadLastOpenedFileOnStartupComboBox"> + <property name="toolTip"> + <string>If selected opens the source code file on startup that was opened last time.</string> + </property> + <property name="text"> + <string>Automatically open last file on startup</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">loadLastSourceCodeFileOnStartup</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="enableIndenterParameterTooltipsCheckBox"> + <property name="toolTip"> + <string>If checked, tool tips will show up if the mouse cursor remains over an indenter parameter for a while.</string> + </property> + <property name="text"> + <string>Enable Parameter Tooltips</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">indenterParameterTooltipsEnabled</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="labelRecentlyOpenedListSize"> + <property name="toolTip"> + <string>Sets how many files should be remembered in the list of recently opened files.</string> + </property> + <property name="text"> + <string>Number of files in recently opened list</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="recentlyOpenedListSizeSpinBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Sets how many files should be remembered in the list of recently opened files.</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>30</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">recentlyOpenedListSize</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">value</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/settingsDialog/accessories-text-editor.png</normaloff>:/settingsDialog/accessories-text-editor.png</iconset> + </attribute> + <attribute name="title"> + <string>Editor</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <widget class="QCheckBox" name="whiteSpaceIsVisibleCheckBox"> + <property name="toolTip"> + <string>Enables or disables displaying of white space characters in the editor.</string> + </property> + <property name="text"> + <string>Display white space character (tabs, spaces, etc.)</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">whiteSpaceIsVisible</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="labelTabWidth"> + <property name="toolTip"> + <string>Sets width in single spaces used for tabs</string> + </property> + <property name="statusTip"> + <string>Defines how many spaces should be displayed in the editor for one tab.</string> + </property> + <property name="text"> + <string>Displayed width of tabs</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="tabWidthSpinBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Defines how many spaces should be displayed in the editor for one tab character.</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>99</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">tabWidth</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">value</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_4"> + <attribute name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/system-software-update.png</normaloff>:/mainWindow/system-software-update.png</iconset> + </attribute> + <attribute name="title"> + <string>Network</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="checkForUpdateCheckBox"> + <property name="toolTip"> + <string>Checks whether a new version of UniversalIndentGUI exists on program start, but only once a day.</string> + </property> + <property name="text"> + <string>Check online for update on program start</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">CheckForUpdate</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QCheckBox" name="enableProxyCheckBox"> + <property name="toolTip"> + <string>If checked, the made proxy settings will be applied for all network connections. Type of the used proxy is SOCKS5.</string> + </property> + <property name="text"> + <string>Enable proxy</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">ProxyEnabled</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Host name:</string> + </property> + <property name="buddy"> + <cstring>proxyHostNameLineEdit</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="proxyHostNameLineEdit"> + <property name="toolTip"> + <string>Host name of the to be used proxy. E.g.: proxy.example.com</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">ProxyHostName</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">text</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Port:</string> + </property> + <property name="buddy"> + <cstring>proxyPortSpinBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="proxyPortSpinBox"> + <property name="toolTip"> + <string>Port number to connect to the before named proxy.</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>99999</number> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">ProxyPort</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">text</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>User name:</string> + </property> + <property name="buddy"> + <cstring>proxyUserNameLineEdit</cstring> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="proxyUserNameLineEdit"> + <property name="toolTip"> + <string>If the proxy needs authentification, enter the login name here.</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">ProxyUserName</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">text</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Password:</string> + </property> + <property name="buddy"> + <cstring>proxyPasswordLineEdit</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="proxyPasswordLineEdit"> + <property name="toolTip"> + <string>If the proxy needs authentification, enter the password here.</string> + </property> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">ProxyPassword</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">text</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_3"> + <attribute name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/settingsDialog/syntax-highlight.png</normaloff>:/settingsDialog/syntax-highlight.png</iconset> + </attribute> + <attribute name="title"> + <string>Syntax Highlighting</string> + </attribute> + <layout class="QVBoxLayout"> + <item> + <widget class="QCheckBox" name="enableSyntaxHighlightningCheckBox"> + <property name="toolTip"> + <string>By enabling special key words of the source code are highlighted.</string> + </property> + <property name="text"> + <string>Enable syntax highlighting</string> + </property> + <property name="connectedSettingName" stdset="0"> + <string notr="true">SyntaxHighlightingEnabled</string> + </property> + <property name="connectedPropertyName" stdset="0"> + <string notr="true">checked</string> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBoxSyntaxHighlighterProperties"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Lets you make settings for all properties of the available syntax highlighters, like font and color.</string> + </property> + <property name="title"> + <string>Highlighter settings</string> + </property> + <layout class="QHBoxLayout"> + <item> + <widget class="QListWidget" name="listWidget"> + <property name="currentRow"> + <number>-1</number> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="listWidget_2"> + <property name="currentRow"> + <number>-1</number> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout"> + <item> + <widget class="QPushButton" name="pushButton_2"> + <property name="toolTip"> + <string>Set the font for the current selected highlighter property.</string> + </property> + <property name="text"> + <string>Set Font</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="toolTip"> + <string>Set the color for the current selected highlighter property.</string> + </property> + <property name="text"> + <string>Set Color</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>SettingsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>250</x> + <y>316</y> + </hint> + <hint type="destinationlabel"> + <x>153</x> + <y>236</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>SettingsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>327</x> + <y>316</y> + </hint> + <hint type="destinationlabel"> + <x>282</x> + <y>236</y> + </hint> + </hints> + </connection> + <connection> + <sender>enableProxyCheckBox</sender> + <signal>toggled(bool)</signal> + <receiver>widget</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>73</x> + <y>68</y> + </hint> + <hint type="destinationlabel"> + <x>76</x> + <y>95</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/UiGuiSystemInfo.cpp b/src/UiGuiSystemInfo.cpp new file mode 100755 index 0000000..6763bf8 --- /dev/null +++ b/src/UiGuiSystemInfo.cpp @@ -0,0 +1,227 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "UiGuiSystemInfo.h"
+
+#include <QString>
+#include <QSysInfo>
+#include <QProcess>
+#include <QFile>
+
+UiGuiSystemInfo::UiGuiSystemInfo() {
+}
+
+
+/*!
+ \brief Returns the operating system UiGUI is currently running on as one string.
+
+ The String contains name and version of the os. E.g. Linux Ubuntu 9.04.
+ */
+QString UiGuiSystemInfo::getOperatingSystem() {
+ QString operatingSystemString = "";
+
+#if defined(Q_WS_WIN)
+ switch ( QSysInfo::WindowsVersion ) {
+ case QSysInfo::WV_32s :
+ operatingSystemString = "Windows 3.1 with Win 32s";
+ break;
+ case QSysInfo::WV_95 :
+ operatingSystemString = "Windows 95";
+ break;
+ case QSysInfo::WV_98 :
+ operatingSystemString = "Windows 98";
+ break;
+ case QSysInfo::WV_Me :
+ operatingSystemString = "Windows Me";
+ break;
+ case QSysInfo::WV_NT :
+ operatingSystemString = "Windows NT (operating system version 4.0)";
+ break;
+ case QSysInfo::WV_2000 :
+ operatingSystemString = "Windows 2000 (operating system version 5.0)";
+ break;
+ case QSysInfo::WV_XP :
+ operatingSystemString = "Windows XP (operating system version 5.1)";
+ break;
+ case QSysInfo::WV_2003 :
+ operatingSystemString = "Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition (operating system version 5.2)";
+ break;
+ case QSysInfo::WV_VISTA :
+ operatingSystemString = "Windows Vista, Windows Server 2008 (operating system version 6.0)";
+ break;
+ case QSysInfo::WV_WINDOWS7 :
+ operatingSystemString = "Windows 7 (operating system version 6.1)";
+ break;
+ case QSysInfo::WV_CE :
+ operatingSystemString = "Windows CE";
+ break;
+ case QSysInfo::WV_CENET :
+ operatingSystemString = "Windows CE .NET";
+ break;
+ case QSysInfo::WV_CE_5 :
+ operatingSystemString = "Windows CE 5.x";
+ break;
+ case QSysInfo::WV_CE_6 :
+ operatingSystemString = "Windows CE 6.x";
+ break;
+ default :
+ operatingSystemString = "Unknown Windows operating system.";
+ break;
+ }
+#elif defined(Q_WS_MAC)
+ switch ( QSysInfo::MacintoshVersion ) {
+ case QSysInfo::MV_9 :
+ operatingSystemString = "Mac OS 9 (unsupported)";
+ break;
+ case QSysInfo::MV_10_0 :
+ operatingSystemString = "Mac OS X 10.0 Cheetah (unsupported)";
+ break;
+ case QSysInfo::MV_10_1 :
+ operatingSystemString = "Mac OS X 10.1 Puma (unsupported)";
+ break;
+ case QSysInfo::MV_10_2 :
+ operatingSystemString = "Mac OS X 10.2 Jaguar (unsupported)";
+ break;
+ case QSysInfo::MV_10_3 :
+ operatingSystemString = "Mac OS X 10.3 Panther";
+ break;
+ case QSysInfo::MV_10_4 :
+ operatingSystemString = "Mac OS X 10.4 Tiger";
+ break;
+ case QSysInfo::MV_10_5 :
+ operatingSystemString = "Mac OS X 10.5 Leopard";
+ break;
+ case QSysInfo::MV_10_6 :
+ operatingSystemString = "Mac OS X 10.6 Snow Leopard";
+ break;
+ case QSysInfo::MV_Unknown :
+ operatingSystemString = "An unknown and currently unsupported platform";
+ break;
+ default :
+ operatingSystemString = "Unknown Mac operating system.";
+ break;
+ }
+#else
+ //TODO: Detect Unix, Linux etc. distro as described on http://www.novell.com/coolsolutions/feature/11251.html
+ operatingSystemString = "Linux";
+ QProcess process;
+
+ process.start("uname -s");
+ bool result = process.waitForFinished(1000);
+ QString os = process.readAllStandardOutput().trimmed();
+
+ process.start("uname -r");
+ result = process.waitForFinished(1000);
+ QString rev = process.readAllStandardOutput().trimmed();
+
+ process.start("uname -m");
+ result = process.waitForFinished(1000);
+ QString mach = process.readAllStandardOutput().trimmed();
+
+ if ( os == "SunOS" ) {
+ os = "Solaris";
+
+ process.start("uname -p");
+ result = process.waitForFinished(1000);
+ QString arch = process.readAllStandardOutput().trimmed();
+
+ process.start("uname -v");
+ result = process.waitForFinished(1000);
+ QString timestamp = process.readAllStandardOutput().trimmed();
+
+ operatingSystemString = os + " " + rev + " (" + arch + " " + timestamp + ")";
+ }
+ else if ( os == "AIX" ) {
+ process.start("oslevel -r");
+ result = process.waitForFinished(1000);
+ QString oslevel = process.readAllStandardOutput().trimmed();
+
+ operatingSystemString = os + "oslevel " + oslevel;
+ }
+ else if ( os == "Linux" ) {
+ QString dist;
+ QString pseudoname;
+ QString kernel = rev;
+
+ if ( QFile::exists("/etc/redhat-release") ) {
+ dist = "RedHat";
+
+ process.start("sh -c \"cat /etc/redhat-release | sed s/.*\\(// | sed s/\\)//\"");
+ result = process.waitForFinished(1000);
+ pseudoname = process.readAllStandardOutput().trimmed();
+
+ process.start("sh -c \"cat /etc/redhat-release | sed s/.*release\\ // | sed s/\\ .*//\"");
+ result = process.waitForFinished(1000);
+ rev = process.readAllStandardOutput().trimmed();
+ }
+ else if ( QFile::exists("/etc/SUSE-release") ) {
+ process.start("sh -c \"cat /etc/SUSE-release | tr '\\n' ' '| sed s/VERSION.*//\"");
+ result = process.waitForFinished(1000);
+ dist = process.readAllStandardOutput().trimmed();
+
+ process.start("sh -c \"cat /etc/SUSE-release | tr '\\n' ' ' | sed s/.*=\\ //\"");
+ result = process.waitForFinished(1000);
+ rev = process.readAllStandardOutput().trimmed();
+ }
+ else if ( QFile::exists("/etc/mandrake-release") ) {
+ dist = "Mandrake";
+
+ process.start("sh -c \"cat /etc/mandrake-release | sed s/.*\\(// | sed s/\\)//\"");
+ result = process.waitForFinished(1000);
+ pseudoname = process.readAllStandardOutput().trimmed();
+
+ process.start("sh -c \"cat /etc/mandrake-release | sed s/.*release\\ // | sed s/\\ .*//\"");
+ result = process.waitForFinished(1000);
+ rev = process.readAllStandardOutput().trimmed();
+ }
+ else if ( QFile::exists("/etc/lsb-release") ) {
+ dist = "Ubuntu";
+
+ QString processCall = "sh -c \"cat /etc/lsb-release | tr '\\n' ' ' | sed s/.*DISTRIB_RELEASE=// | sed s/\\ .*//\"";
+ process.start( processCall );
+ result = process.waitForFinished(1000);
+ rev = process.readAllStandardOutput().trimmed();
+ QString errorStr = process.readAllStandardError();
+
+ process.start("sh -c \"cat /etc/lsb-release | tr '\\n' ' ' | sed s/.*DISTRIB_CODENAME=// | sed s/\\ .*//\"");
+ result = process.waitForFinished(1000);
+ pseudoname = process.readAllStandardOutput().trimmed();
+ }
+ else if ( QFile::exists("/etc/debian_version") ) {
+ dist = "Debian";
+
+ process.start("cat /etc/debian_version");
+ result = process.waitForFinished(1000);
+ dist += process.readAllStandardOutput().trimmed();
+
+ rev = "";
+ }
+
+ if ( QFile::exists("/etc/UnitedLinux-release") ) {
+ process.start("sh -c \"cat /etc/UnitedLinux-release | tr '\\n' ' ' | sed s/VERSION.*//\"");
+ result = process.waitForFinished(1000);
+ dist += process.readAllStandardOutput().trimmed();
+ }
+
+ operatingSystemString = os + " " + dist + " " + rev + " (" + pseudoname + " " + kernel + " " + mach + ")";
+ }
+#endif
+
+ return operatingSystemString;
+}
diff --git a/src/UiGuiSystemInfo.h b/src/UiGuiSystemInfo.h new file mode 100755 index 0000000..08dca5b --- /dev/null +++ b/src/UiGuiSystemInfo.h @@ -0,0 +1,35 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UIGUISYSTEMINFO_H
+#define UIGUISYSTEMINFO_H
+
+class QString;
+
+
+class UiGuiSystemInfo
+{
+public:
+ static QString getOperatingSystem();
+
+private:
+ UiGuiSystemInfo();
+};
+
+#endif // UIGUISYSTEMINFO_H
diff --git a/src/UiGuiVersion.cpp b/src/UiGuiVersion.cpp new file mode 100755 index 0000000..375df0e --- /dev/null +++ b/src/UiGuiVersion.cpp @@ -0,0 +1,61 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "UiGuiVersion.h"
+
+#include <QString>
+#include <QStringList>
+#include <QDate>
+
+namespace UiGuiVersion {
+/*!
+ \brief Returns the build date as a localized string, e.g. "9. Februar 2009". If
+ there was some kind of error, the returned string is empty.
+ */
+QString getBuildDate() {
+ QStringList monthNames;
+ QString buildDateString = "";
+
+ monthNames << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun" << "Jul" << "Aug" << "Sep" << "Oct" << "Nov" << "Dez";
+ QStringList buildDateStringList = QString(__DATE__).simplified().split(' '); // __DATE__ returns eg "Feb 4 2009"
+
+ if ( buildDateStringList.count() == 3 ) {
+ QDate buildDate(buildDateStringList.last().toInt(), monthNames.indexOf( buildDateStringList.first() )+1, buildDateStringList.at(1).toInt());
+ buildDateString = buildDate.toString("d. MMMM yyyy");
+ }
+
+ return buildDateString;
+}
+
+
+/*!
+ \brief Returns the revision number, that the current build is based on, as string. If
+ there was some kind of error, the returned string is empty.
+ */
+QString getBuildRevision() {
+ QString buildRevision = "";
+ QStringList buildRevisionStringList = QString(PROGRAM_REVISION).simplified().split(' ');
+
+ if ( buildRevisionStringList.count() == 3 ) {
+ buildRevision = buildRevisionStringList.at(1); // PROGRAM_REVISION is eg "$Revision: 907 $"
+ }
+
+ return buildRevision;
+}
+} // namespace UiGuiVersion
diff --git a/src/UiGuiVersion.h b/src/UiGuiVersion.h new file mode 100755 index 0000000..41aff77 --- /dev/null +++ b/src/UiGuiVersion.h @@ -0,0 +1,39 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UIGUIVERSION_H
+#define UIGUIVERSION_H
+
+class QString;
+
+// Define the version number here. Update this as the last file before a release.
+#define PROGRAM_VERSION 1.2.0
+#define PROGRAM_VERSION_STRING "1.2.0"
+#define RESOURCE_VERSION 1,2,0,0
+#define RESOURCE_VERSION_STRING "1,2,0,0\0"
+#define PROGRAM_REVISION "$Revision: 1070 $"
+
+namespace UiGuiVersion {
+
+ QString getBuildDate();
+ QString getBuildRevision();
+
+}
+
+#endif // UIGUIVERSION_H
diff --git a/src/UniversalIndentGUI.vcproj b/src/UniversalIndentGUI.vcproj new file mode 100755 index 0000000..2fabfe7 --- /dev/null +++ b/src/UniversalIndentGUI.vcproj @@ -0,0 +1,549 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8,00" + Name="UniversalIndentGUI" + ProjectGUID="{CF521500-824E-4DB7-A7FA-F4A8B6BB008A}" + RootNamespace="UniversalIndentGUI" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + <ToolFile + RelativePath="..\VS8QtRules.rules" + /> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\tmp" + ConfigurationType="1" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + CommandLine="" + /> + <Tool + Name="MOC" + /> + <Tool + Name="QRC" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="UIC" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalOptions="/D "QT_LARGEFILE_SUPPORT" /D "QT_DLL" /D "QT_GUI_LIB" /D "QT_CORE_LIB" /D "QT_THREAD_SUPPORT"" + Optimization="0" + AdditionalIncludeDirectories=""$(OutDir)\tmp\uic\";"$(QTDIR)\include\QtNetwork";"$(QTDIR)\include\QtScript"" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;QT_NO_CAST_TO_ASCII" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + TreatWChar_tAsBuiltInType="false" + UsePrecompiledHeader="0" + ObjectFile="$(IntDir)\obj\" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="qtmaind.lib QtGuid4.lib QtCored4.lib QtNetworkd4.lib QtScriptd4.lib qscintilla2.lib" + LinkIncremental="2" + IgnoreAllDefaultLibraries="false" + IgnoreDefaultLibraryNames="LIBCRMTD.lib" + GenerateDebugInformation="true" + SubSystem="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + EmbedManifest="false" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)$(ConfigurationName)" + IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\tmp" + ConfigurationType="1" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + CommandLine="" + /> + <Tool + Name="MOC" + /> + <Tool + Name="QRC" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="UIC" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(OutDir)\tmp\uic\";"$(QTDIR)\include\QtScript"" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" + RuntimeLibrary="2" + TreatWChar_tAsBuiltInType="false" + UsePrecompiledHeader="0" + ObjectFile="$(IntDir)\obj\" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="qtmain.lib QtGui4.lib QtCore4.lib QtNetwork4.lib QtScript4.lib qscintilla2.lib" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + VerboseOutput="true" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\AboutDialog.cpp" + > + </File> + <File + RelativePath=".\AboutDialogGraphicsView.cpp" + > + </File> + <File + RelativePath=".\IndentHandler.cpp" + > + </File> + <File + RelativePath=".\main.cpp" + > + </File> + <File + RelativePath=".\MainWindow.cpp" + > + </File> + <File + RelativePath=".\SettingsPaths.cpp" + > + </File> + <File + RelativePath=".\TemplateBatchScript.cpp" + > + </File> + <File + RelativePath=".\UiGuiErrorMessage.cpp" + > + </File> + <File + RelativePath=".\UiGuiHighlighter.cpp" + > + </File> + <File + RelativePath=".\UiGuiIndentServer.cpp" + > + </File> + <File + RelativePath=".\UiGuiIniFileParser.cpp" + > + </File> + <File + RelativePath=".\UiGuiLogger.cpp" + > + </File> + <File + RelativePath=".\UiGuiSettings.cpp" + > + </File> + <File + RelativePath=".\UiGuiSettingsDialog.cpp" + > + </File> + <File + RelativePath=".\UiGuiSystemInfo.cpp" + > + </File> + <File + RelativePath=".\UiGuiVersion.cpp" + > + </File> + <File + RelativePath=".\UpdateCheckDialog.cpp" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\AboutDialog.h" + > + </File> + <File + RelativePath=".\AboutDialogGraphicsView.h" + > + </File> + <File + RelativePath=".\IndentHandler.h" + > + </File> + <File + RelativePath=".\MainWindow.h" + > + </File> + <File + RelativePath=".\SettingsPaths.h" + > + </File> + <File + RelativePath=".\TemplateBatchScript.h" + > + </File> + <File + RelativePath=".\UiGuiErrorMessage.h" + > + </File> + <File + RelativePath=".\UiGuiHighlighter.h" + > + </File> + <File + RelativePath=".\UiGuiIndentServer.h" + > + </File> + <File + RelativePath=".\UiGuiIniFileParser.h" + > + </File> + <File + RelativePath=".\UiGuiLogger.h" + > + </File> + <File + RelativePath=".\UiGuiSettings.h" + > + </File> + <File + RelativePath=".\UiGuiSettingsDialog.h" + > + </File> + <File + RelativePath=".\UiGuiSystemInfo.h" + > + </File> + <File + RelativePath=".\UiGuiVersion.h" + > + </File> + <File + RelativePath=".\UpdateCheckDialog.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + <File + RelativePath="..\resources\Icons.qrc" + > + </File> + <File + RelativePath="..\resources\programicon.rc" + > + </File> + </Filter> + <Filter + Name="Forms (UI)" + > + <File + RelativePath=".\AboutDialog.ui" + > + </File> + <File + RelativePath=".\MainWindow.ui" + > + </File> + <File + RelativePath=".\ToolBarWidget.ui" + > + </File> + <File + RelativePath=".\UiGuiLoggerDialog.ui" + > + </File> + <File + RelativePath=".\UiGuiSettingsDialog.ui" + > + </File> + <File + RelativePath=".\UpdateCheckDialog.ui" + > + </File> + </Filter> + <Filter + Name="Generated" + > + <File + RelativePath="$(OutDir)\tmp\moc\moc_AboutDialog.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_AboutDialogGraphicsView.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_IndentHandler.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_MainWindow.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiErrorMessage.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiHighlighter.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiIndentServer.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiLogger.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiSettings.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UiGuiSettingsDialog.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\moc\moc_UpdateCheckDialog.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\qrc\qrc_Icons.cpp" + > + </File> + <File + RelativePath="$(OutDir)\tmp\uic\ui_AboutDialog.h" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + </File> + <File + RelativePath="$(OutDir)\tmp\uic\ui_MainWindow.h" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + </File> + <File + RelativePath="$(OutDir)\tmp\uic\ui_ToolBarWidget.h" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + </File> + <File + RelativePath="$(OutDir)\tmp\uic\ui_UiGuiSettingsDialog.h" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + </File> + <File + RelativePath="$(OutDir)\tmp\uic\ui_UpdateCheckDialog.h" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="MOC" + /> + </FileConfiguration> + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/src/UpdateCheckDialog.cpp b/src/UpdateCheckDialog.cpp new file mode 100755 index 0000000..a5a58d8 --- /dev/null +++ b/src/UpdateCheckDialog.cpp @@ -0,0 +1,322 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "UpdateCheckDialog.h" +#include "ui_UpdateCheckDialog.h" + +#include "UiGuiSettings.h" +#include "UiGuiVersion.h" + +#include <QMessageBox> +#include <QDesktopServices> +#include <QNetworkAccessManager> +#include <QTimer> +#include <QDate> +#include <QUrl> +#include <QRegExpValidator> +#include <QNetworkRequest> +#include <QNetworkReply> +#include <QNetworkProxy> + +/*! + \class UpdateCheckDialog + \ingroup grp_MainWindow + \brief UpdateCheckDialog is a dialog widget that contains functions + for online checking for a new version of UniversalIndentGUI. +*/ + +/*! + \brief Initializes member variables and stores the version of UiGui and a pointer to the _settings object. + */ +UpdateCheckDialog::UpdateCheckDialog(QSharedPointer<UiGuiSettings> settings, QWidget *parent) : QDialog(parent), + _manualUpdateRequested(false), + _currentNetworkReply(NULL), + _roleOfClickedButton(QDialogButtonBox::InvalidRole) +{ + _updateCheckDialogForm = new Ui::UpdateCheckDialog(); + _updateCheckDialogForm->setupUi(this); + + // Create object for _networkAccessManager request and connect it with the request return handler. + _networkAccessManager = new QNetworkAccessManager(this); + connect( _networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkResultsOfFetchedPadXMLFile(QNetworkReply*)) ); + + // Create a timer object used for the progress bar. + _updateCheckProgressTimer = new QTimer(this); + _updateCheckProgressTimer->setInterval(5); + connect( _updateCheckProgressTimer, SIGNAL(timeout()), this, SLOT(updateUpdateCheckProgressBar()) ); + _updateCheckProgressCounter = 0; + + // Connect the dialogs buttonbox with a button click handler. + connect( _updateCheckDialogForm->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(handleUpdateCheckDialogButtonClicked(QAbstractButton*)) ); + + settings->registerObjectSlot(this, "initProxySettings()", "ProxyEnabled"); + settings->registerObjectSlot(this, "initProxySettings()", "ProxyHostName"); + settings->registerObjectSlot(this, "initProxySettings()", "ProxyPort"); + settings->registerObjectSlot(this, "initProxySettings()", "ProxyUserName"); + settings->registerObjectSlot(this, "initProxySettings()", "ProxyPassword"); + + _settings = settings; + + initProxySettings(); + + // This dialog is always modal. + setModal(true); +} + + +/*! + \brief On destroy cancels any currently running network request. + */ +UpdateCheckDialog::~UpdateCheckDialog() { + disconnect( _networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(checkResultsOfFetchedPadXMLFile(QNetworkReply*)) ); + if (_currentNetworkReply != NULL) + _currentNetworkReply->abort(); +} + + +/*! + \brief This slot should be called, if an update check is manually invoked. + + In difference to the automatic update check, during manual update check request + a modal progress indicator dialog will be shown. + */ +void UpdateCheckDialog::checkForUpdateAndShowDialog() { + _manualUpdateRequested = true; + getPadXMLFile(); + showCheckingForUpdateDialog(); +} + + +/*! + \brief This slot should be called, if an update check is automatically invoked. + + An automatic invoked update check should run in background, so the user + gets not interrupted by a dialog box. + */ +void UpdateCheckDialog::checkForUpdate() { + _manualUpdateRequested = false; + getPadXMLFile(); +} + + +/*! + \brief This function tries to download the UniversalIndentGui pad file from the SourceForge server. + */ +void UpdateCheckDialog::getPadXMLFile() { + //_networkAccessManager->setHost("universalindent.sourceforge.net"); + //_networkAccessManager->get("/universalindentgui_pad.xml"); + _currentNetworkReply = _networkAccessManager->get(QNetworkRequest(QUrl("http://universalindent.sourceforge.net/universalindentgui_pad.xml"))); +} + + +/*! + \brief This slot is called after the update check has returned, either by successfully + retrieving the pad file, or on any kind of network error. + + Shows a message if check was successful or not. Offers the user to go to the + download page if a newer version exists. In case of an error during update + check, a message box with the error will be displayed. + */ +void UpdateCheckDialog::checkResultsOfFetchedPadXMLFile(QNetworkReply *networkReply) { + Q_ASSERT(_currentNetworkReply == networkReply); + + // Stop the progress bar timer. + _updateCheckProgressTimer->stop(); + + if ( networkReply->error() == QNetworkReply::NoError ) { + // Try to find the version string. + QString returnedString = networkReply->readAll(); + int leftPosition = returnedString.indexOf("<Program_Version>"); + int rightPosition = returnedString.indexOf("</Program_Version>"); + + // If the version string could be found in the returned string, show an update dialog and set last update check date. + if ( leftPosition != -1 && rightPosition != -1 ) { + // Get the pure version string from returned string. + returnedString = returnedString.mid( leftPosition+17, rightPosition-(leftPosition+17) ); + + // Create integer values from the version strings. + int versionOnServerInt = convertVersionStringToNumber( returnedString ); + int currentVersionInt = convertVersionStringToNumber( PROGRAM_VERSION_STRING ); + + // Only show update dialog, if the current version number is lower than the one received from the server. + if ( versionOnServerInt > currentVersionInt && currentVersionInt >= 0 && versionOnServerInt >= 0 ) { + // Show message box whether to download the new version. + showNewVersionAvailableDialog(returnedString); + + // If yes clicked, open the download url in the default browser. + if ( _roleOfClickedButton == QDialogButtonBox::YesRole ) { + QDesktopServices::openUrl( QUrl("_networkAccessManager://sourceforge.net/project/showfiles.php?group_id=167482") ); + } + } + else if ( _manualUpdateRequested ) { + showNoNewVersionAvailableDialog(); + } + // Set last update check date. + _settings->setValueByName("LastUpdateCheck", QDate::currentDate()); + } + // In the returned string, the version string could not be found. + else { + QMessageBox::warning(this, tr("Update check error"), tr("There was an error while trying to check for an update! The retrieved file did not contain expected content.") ); + } + } + // If there was some error while trying to retrieve the update info from server and not cancel was pressed. + else if ( _roleOfClickedButton != QDialogButtonBox::RejectRole ) { + QMessageBox::warning(this, tr("Update check error"), tr("There was an error while trying to check for an update! Error was : %1").arg(networkReply->errorString()) ); + hide(); + } + _manualUpdateRequested = false; + networkReply->deleteLater(); + _currentNetworkReply = NULL; +} + + +/*! + \brief Displays the progress bar during update check. + + For displaying activity during update check, a timer is started to + updated the progress bar. The user can press a cancel button to + stop the update check. + */ +void UpdateCheckDialog::showCheckingForUpdateDialog() { + // Reset the progress bar. + _updateCheckProgressCounter = 0; + _updateCheckDialogForm->progressBar->setValue(_updateCheckProgressCounter); + _updateCheckDialogForm->progressBar->setInvertedAppearance( false ); + + _updateCheckProgressTimer->start(); + _updateCheckDialogForm->progressBar->show(); + setWindowTitle( tr("Checking for update...") ); + _updateCheckDialogForm->label->setText( tr("Checking whether a newer version is available") ); + _updateCheckDialogForm->buttonBox->setStandardButtons(QDialogButtonBox::Cancel); + show(); +} + + +/*! + \brief Displays the dialog with info about the new available version. + */ +void UpdateCheckDialog::showNewVersionAvailableDialog(QString newVersion) { + _updateCheckDialogForm->progressBar->hide(); + setWindowTitle( tr("Update available") ); + _updateCheckDialogForm->label->setText( tr("A newer version of UniversalIndentGUI is available.\nYour version is %1. New version is %2.\nDo you want to go to the download website?").arg(PROGRAM_VERSION_STRING).arg(newVersion) ); + _updateCheckDialogForm->buttonBox->setStandardButtons(QDialogButtonBox::No|QDialogButtonBox::NoButton|QDialogButtonBox::Yes); + exec(); +} + + +/*! + \brief Displays the dialog, that no new version is available. + */ +void UpdateCheckDialog::showNoNewVersionAvailableDialog() { + _updateCheckDialogForm->progressBar->hide(); + setWindowTitle( tr("No new update available") ); + _updateCheckDialogForm->label->setText( tr("You already have the latest version of UniversalIndentGUI.") ); + _updateCheckDialogForm->buttonBox->setStandardButtons(QDialogButtonBox::Ok); + exec(); +} + + +/*! + \brief This slot is called, when a button in the dialog is clicked. + + If the clicked button was the cancel button, the user wants to cancel + the update check. So the _networkAccessManager request is aborted and the timer for the + progress bar animation is stopped. + + In any case if a button is clicked, the dialog box will be closed. + */ +void UpdateCheckDialog::handleUpdateCheckDialogButtonClicked(QAbstractButton *clickedButton) { + _roleOfClickedButton = _updateCheckDialogForm->buttonBox->buttonRole(clickedButton); + + if ( _roleOfClickedButton == QDialogButtonBox::RejectRole ) { + // Abort the _networkAccessManager request. + _currentNetworkReply->abort(); + // Stop the progress bar timer. + _updateCheckProgressTimer->stop(); + } + + accept(); +} + + +/*! + \brief This slot is responsible for the animation of the update check progress bar. + */ +void UpdateCheckDialog::updateUpdateCheckProgressBar() { + // Depending on the progress bar direction, decrease or increase the progressbar value. + if ( _updateCheckDialogForm->progressBar->invertedAppearance() ) { + _updateCheckProgressCounter--; + } + else { + _updateCheckProgressCounter++; + } + + // If the progress bar reaches 0 or 100 as value, swap the animation direction. + if ( _updateCheckProgressCounter == 0 || _updateCheckProgressCounter == 100 ) { + _updateCheckDialogForm->progressBar->setInvertedAppearance( !_updateCheckDialogForm->progressBar->invertedAppearance() ); + } + + // Update the progress bar value. + _updateCheckDialogForm->progressBar->setValue(_updateCheckProgressCounter); +} + + +/*! + \brief Converts the as string given version \a versionString to an integer number. + + The \a versionString must have the format x.x.x where each x represents a number + of a maximum of 999. If the input format is wrong, -1 will be returned.The first + number will be multiplied by 1000000 the second by 1000 and then all three will + be summarized. + + Thus for example 12.5.170 will result in 12005170. + */ +int UpdateCheckDialog::convertVersionStringToNumber(QString versionString) { + int versionInteger = 0; + int pos = 0; + + QRegExp regEx("\\d{1,3}.\\d{1,3}.\\d{1,3}"); + QRegExpValidator validator(regEx, NULL); + + if ( validator.validate(versionString, pos) == QValidator::Acceptable ) { + QStringList versionNumberStringList = versionString.split("."); + versionInteger = versionNumberStringList.at(0).toInt() * 1000000; + versionInteger += versionNumberStringList.at(1).toInt() * 1000; + versionInteger += versionNumberStringList.at(2).toInt(); + } + else { + versionInteger = -1; + } + + return versionInteger; +} + +void UpdateCheckDialog::initProxySettings() +{ + if ( _settings->getValueByName("ProxyEnabled") == true ) { + QString proxyHostName = _settings->getValueByName("ProxyHostName").toString(); + int proxyPort = _settings->getValueByName("ProxyPort").toInt(); + QString proxyUserName = _settings->getValueByName("ProxyUserName").toString(); + QString proxyPassword = _settings->getValueByName("ProxyPassword").toString(); + _networkAccessManager->setProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyHostName, proxyPort, proxyUserName, proxyPassword)); + } + else { + _networkAccessManager->setProxy(QNetworkProxy()); + } +} diff --git a/src/UpdateCheckDialog.h b/src/UpdateCheckDialog.h new file mode 100755 index 0000000..f0dfe81 --- /dev/null +++ b/src/UpdateCheckDialog.h @@ -0,0 +1,73 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef UPDATECHECKDIALOG_H
+#define UPDATECHECKDIALOG_H
+
+#include <QDialog>
+#include <QDialogButtonBox>
+
+class UiGuiSettings;
+namespace Ui {
+ class UpdateCheckDialog;
+}
+
+class QTimer;
+class QDesktopServices;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+
+class UpdateCheckDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ UpdateCheckDialog(QSharedPointer<UiGuiSettings> settings, QWidget *parent = NULL);
+ ~UpdateCheckDialog();
+
+public slots:
+ void checkForUpdateAndShowDialog();
+ void checkForUpdate();
+
+private slots:
+ void checkResultsOfFetchedPadXMLFile(QNetworkReply *networkReply);
+ void handleUpdateCheckDialogButtonClicked(QAbstractButton *clickedButton);
+ void updateUpdateCheckProgressBar();
+ void initProxySettings();
+
+private:
+ Ui::UpdateCheckDialog *_updateCheckDialogForm;
+
+ void getPadXMLFile();
+ void showCheckingForUpdateDialog();
+ void showNewVersionAvailableDialog(QString newVersion);
+ void showNoNewVersionAvailableDialog();
+ int convertVersionStringToNumber(QString versionString);
+
+ QSharedPointer<UiGuiSettings> _settings;
+ bool _manualUpdateRequested;
+ QNetworkAccessManager *_networkAccessManager;
+ QNetworkReply *_currentNetworkReply;
+ QDialogButtonBox::ButtonRole _roleOfClickedButton;
+ QTimer *_updateCheckProgressTimer;
+ int _updateCheckProgressCounter;
+};
+
+#endif // UPDATECHECKDIALOG_H
diff --git a/src/UpdateCheckDialog.ui b/src/UpdateCheckDialog.ui new file mode 100755 index 0000000..bb165eb --- /dev/null +++ b/src/UpdateCheckDialog.ui @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UpdateCheckDialog</class> + <widget class="QDialog" name="UpdateCheckDialog"> + <property name="windowModality"> + <enum>Qt::WindowModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>323</width> + <height>108</height> + </rect> + </property> + <property name="windowTitle"> + <string>Checking for update...</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Checking whether a newer version is available</string> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="value"> + <number>0</number> + </property> + <property name="textVisible"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel</set> + </property> + <property name="centerButtons"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/debugging/.svn/all-wcprops b/src/debugging/.svn/all-wcprops new file mode 100755 index 0000000..3ceca8f --- /dev/null +++ b/src/debugging/.svn/all-wcprops @@ -0,0 +1,7 @@ +END +TSLoggerDialog.ui +K 25 +svn:wc:ra_dav:version-url +V 76 +/svnroot/universalindent/!svn/ver/1031/trunk/src/debugging/TSLoggerDialog.ui +END diff --git a/src/debugging/.svn/entries b/src/debugging/.svn/entries new file mode 100755 index 0000000..3d62022 --- /dev/null +++ b/src/debugging/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +1074 +https://universalindent.svn.sourceforge.net/svnroot/universalindent/trunk/src/debugging +https://universalindent.svn.sourceforge.net/svnroot/universalindent + + + +2012-01-01T15:57:45.041181Z +1072 +thomas_-_s + + + + + + + + + + + + + + +c764a436-2d14-0410-8e4b-8664b97a5d8c + +TSLogger.cpp +file + + + + +2012-01-01T15:53:22.000000Z +bb8f19f90ef34ed27f3746cce9c0d857 +2012-01-01T15:57:45.041181Z +1072 +thomas_-_s + + + + + + + + + + + + + + + + + + + + + +9302 + +TSLogger.h +file + + + + +2012-01-01T15:53:20.000000Z +4f6c6d98220006c54c8530fed4ef69a2 +2012-01-01T15:57:45.041181Z +1072 +thomas_-_s + + + + + + + + + + + + + + + + + + + + + +2317 + +TSLoggerDialog.ui +file + + + + +2011-12-26T15:10:20.000000Z +ca2220682b5c3f228a786bbd43fcc9ed +2010-12-21T23:07:50.799886Z +1031 +thomas_-_s + + + + + + + + + + + + + + + + + + + + + +3660 + diff --git a/src/debugging/.svn/text-base/TSLogger.cpp.svn-base b/src/debugging/.svn/text-base/TSLogger.cpp.svn-base new file mode 100755 index 0000000..e7a912b --- /dev/null +++ b/src/debugging/.svn/text-base/TSLogger.cpp.svn-base @@ -0,0 +1,251 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "TSLogger.h"
+#include "ui_TSLoggerDialog.h"
+
+#include "SettingsPaths.h"
+
+#include <QDateTime>
+#include <QFile>
+#include <QFileInfo>
+#include <QUrl>
+#include <QTextStream>
+#include <QDesktopServices>
+#include <QMessageBox>
+
+#include <ctime>
+
+using namespace tschweitzer;
+using namespace tschweitzer::debugging;
+
+TSLogger* TSLogger::_instance = NULL;
+
+/*!
+ \class TSLogger
+ \brief This class handles any kind of data logging, for debugging and whatever purpose.
+
+ Beneath being able of displaying a dialog window containing all log messages of the
+ current session, a log file in the systems temporary directory is used. Its name
+ is "UiGUI_log.html".
+
+ Setting a verbose level allows to only write messages that have the selected minimum
+ priority to the log.
+ */
+
+/*!
+ \brief Returns the only existing instance of TSLogger. If the instance doesn't exist, it will be created.
+ */
+TSLogger* TSLogger::getInstance(int verboseLevel) {
+ if ( _instance == NULL )
+ _instance = new TSLogger(verboseLevel);
+
+ return _instance;
+}
+
+
+/*!
+ \brief Returns the only existing instance of TSLogger. If the instance doesn't exist, it will be created.
+ */
+TSLogger* TSLogger::getInstance() {
+#ifdef _DEBUG
+ return TSLogger::getInstance(QtDebugMsg);
+#else
+ return TSLogger::getInstance(QtWarningMsg);
+#endif
+}
+
+
+/*!
+ \brief Initializes the dialog and sets the path to the log file in the systems temporary directory.
+ Sets the default verbose level to warning level.
+ */
+TSLogger::TSLogger(int verboseLevel) : QDialog() {
+ _TSLoggerDialogForm = new Ui::TSLoggerDialog();
+ _TSLoggerDialogForm->setupUi(this);
+#ifdef _DEBUG
+ _verboseLevel = QtDebugMsg;
+#else
+ _verboseLevel = QtMsgType(verboseLevel);
+#endif
+
+ _logFileInitState = NOTINITIALZED;
+
+ connect( _TSLoggerDialogForm->openLogFileFolderToolButton, SIGNAL(clicked()), this, SLOT(openLogFileFolder()) );
+
+ // Make the main application not to wait for the logging window to close.
+ setAttribute(Qt::WA_QuitOnClose, false);
+}
+
+
+/*!
+ \brief Logs all incoming messages \a msg to the dialogs text edit and to the log file.
+
+ Only messages whos \a type have a higher priority than the set verbose level are logged.
+ */
+void TSLogger::messageHandler(QtMsgType type, const char *msg) {
+ if ( _instance == NULL )
+ _instance = TSLogger::getInstance();
+
+/*
+ QMessageBox messageBox;
+ QString messageBoxText = QString::fromUtf8( msg );
+ messageBox.setText( messageBoxText );
+ messageBox.setWindowModality( Qt::ApplicationModal );
+ messageBox.exec();
+*/
+
+ // Only log messages that have a higher or equal priority than set with the verbose level.
+ if ( type < _instance->_verboseLevel )
+ return;
+
+ // Init log message with prepended date and time.
+ QString message = QDateTime::currentDateTime().toString();
+
+ // Depending on the QtMsgType prepend a different colored Debug, Warning, Critical or Fatal.
+ switch (type) {
+ case QtDebugMsg :
+ message += " <span style=\"font-weight:bold; color:black;\">Debug:</span> ";
+ break;
+ case QtWarningMsg :
+ message += " <span style=\"font-weight:bold; color:gold;\">Warning:</span> ";
+ break;
+ case QtCriticalMsg :
+ message += "<span style=\"font-weight:bold; color:red;\">Critical:</span> ";
+ break;
+ case QtFatalMsg :
+ message += " <span style=\"font-weight:bold; color:#D60000;\">Fatal:</span> ";
+ // This one is no Qt message type, but can be used to send info messages to the log
+ // by calling TSLogger::messageHandler() directly.
+ case TSLoggerInfoMsg :
+ message += " <span style=\"font-weight:bold; color:darkgray;\">Info:</span> ";
+ break;
+ }
+
+ // Append the to UTF-8 back converted message parameter.
+ message += QString::fromUtf8( msg ) + "<br/>\n";
+
+ // Write the message to the log windows text edit.
+ _instance->_TSLoggerDialogForm->logTextEdit->append( message );
+
+ // Write/append the log message to the log file.
+ _instance->writeToLogFile( message );
+
+ // In case of a fatal error abort the application.
+ if ( type == QtFatalMsg )
+ abort();
+}
+
+
+/*!
+ \brief Calling this the verbose level can be set in a range from 0 to 3
+ which is equal to debug, warning, critical and fatal priority.
+ */
+void TSLogger::setVerboseLevel(int level) {
+ if ( level < 0 )
+ _verboseLevel = QtDebugMsg;
+ if ( level > 3 )
+ _verboseLevel = QtFatalMsg;
+ else
+ _verboseLevel = QtMsgType(level);
+}
+
+
+/*!
+ \brief Deletes the existing _instance of TSLogger.
+ */
+void TSLogger::deleteInstance() {
+ if ( _instance != NULL ) {
+ delete _instance;
+ _instance = NULL;
+ }
+}
+
+
+/*!
+ \brief Opens the folder that contains the created log file with the name "UiGUI_log.html".
+ */
+void TSLogger::openLogFileFolder() {
+ QDesktopServices::openUrl( QFileInfo( _logFile ).absolutePath() );
+}
+
+
+/*!
+ \brief Writes the \a message to the used log file.
+ */
+void TSLogger::writeToLogFile(const QString &message) {
+ // If the file where all logging messages should go to isn't initilized yet, do that now.
+ if ( _logFileInitState == NOTINITIALZED ) {
+ _logFileInitState = INITIALIZING;
+
+ // On different systems it may be that "QDir::tempPath()" ends with a "/" or not. So check this.
+ // Remove any trailing slashes.
+ QString tempPath = QFileInfo( SettingsPaths::getTempPath() ).absolutePath();
+ while ( tempPath.right(1) == "/" ) {
+ tempPath.chop(1);
+ }
+
+ // To make the temporary log file invulnerable against file symbolic link hacks
+ // append the current date and time up to milliseconds to its name and a random character.
+ QString logFileName = "UiGUI_log_" + QDateTime::currentDateTime().toString("yyyyMMdd");
+ logFileName += "-" + QDateTime::currentDateTime().toString("hhmmsszzz");
+ // By random decide whether to append a number or an upper or lower case character.
+ qsrand( time(NULL) );
+ unsigned char randomChar;
+ switch ( qrand() % 3 ) {
+ // Append a number from 0 to 9.
+ case 0 :
+ randomChar = qrand() % 10 + '0';
+ break;
+ // Append a upper case characer between A and Z.
+ case 1 :
+ randomChar = qrand() % 26 + 'A';
+ break;
+ // Append a lower case characer between a and z.
+ default :
+ randomChar = qrand() % 26 + 'a';
+ break;
+ }
+ logFileName += "_" + QString(randomChar) + ".html";
+
+ _logFile.setFileName( tempPath + "/" + logFileName );
+
+ // Set the tooltip of the open log file folder button to show the unique name of the log file.
+ _TSLoggerDialogForm->openLogFileFolderToolButton->setToolTip( _TSLoggerDialogForm->openLogFileFolderToolButton->toolTip() + " (" + logFileName + ")" );
+
+ _logFileInitState = INITIALZED;
+ }
+
+ // Add the message to the message queue.
+ _messageQueue << message;
+
+ // If the logging file is initialzed, write all messages contained in the message queue into the file.
+ if ( _logFileInitState == INITIALZED ) {
+ // Write/append the log message to the log file.
+ if ( _logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append) ) {
+ QTextStream out(&_logFile);
+
+ while ( !_messageQueue.isEmpty() ) {
+ out << _messageQueue.takeFirst() << "\n";
+ }
+
+ _logFile.close();
+ }
+ }
+}
diff --git a/src/debugging/.svn/text-base/TSLogger.h.svn-base b/src/debugging/.svn/text-base/TSLogger.h.svn-base new file mode 100755 index 0000000..c7e7e62 --- /dev/null +++ b/src/debugging/.svn/text-base/TSLogger.h.svn-base @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef TSLogger_H +#define TSLogger_H + +#include <QDialog> +#include <QFile> + +namespace Ui { + class TSLoggerDialog; +} + +namespace tschweitzer { namespace debugging { + +#define TSLoggerInfoMsg QtMsgType(4) + +class TSLogger : public QDialog +{ + Q_OBJECT + +public: + static TSLogger* getInstance(int verboseLevel); + static TSLogger* getInstance(); + static void messageHandler(QtMsgType type, const char *msg); + static void deleteInstance(); + void setVerboseLevel(int level); + +private slots: + void openLogFileFolder(); + +private: + Ui::TSLoggerDialog *_TSLoggerDialogForm; + + enum LogFileInitState { NOTINITIALZED, INITIALIZING, INITIALZED } _logFileInitState; + TSLogger(int verboseLevel); + void writeToLogFile(const QString &message); + + static TSLogger* _instance; + QtMsgType _verboseLevel; + QFile _logFile; + QStringList _messageQueue; +}; + +}} // namespace tschweitzer::debugging + +#endif // TSLogger_H diff --git a/src/debugging/.svn/text-base/TSLoggerDialog.ui.svn-base b/src/debugging/.svn/text-base/TSLoggerDialog.ui.svn-base new file mode 100755 index 0000000..3a83146 --- /dev/null +++ b/src/debugging/.svn/text-base/TSLoggerDialog.ui.svn-base @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TSLoggerDialog</class> + <widget class="QDialog" name="TSLoggerDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1030</width> + <height>263</height> + </rect> + </property> + <property name="windowTitle"> + <string>Log</string> + </property> + <property name="windowIcon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-properties.png</normaloff>:/mainWindow/document-properties.png</iconset> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Logged messages</string> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="logTextEdit"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QToolButton" name="cleanUpToolButton"> + <property name="toolTip"> + <string>Clear log</string> + </property> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/edit-clear.png</normaloff>:/mainWindow/edit-clear.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="openLogFileFolderToolButton"> + <property name="toolTip"> + <string>Open folder containing log file.</string> + </property> + <property name="statusTip"> + <string>Open folder containing log file.</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-open.png</normaloff>:/mainWindow/document-open.png</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections> + <connection> + <sender>TSLoggerDialog</sender> + <signal>finished(int)</signal> + <receiver>TSLoggerDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>2</x> + <y>45</y> + </hint> + <hint type="destinationlabel"> + <x>5</x> + <y>59</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>TSLoggerDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>419</x> + <y>280</y> + </hint> + <hint type="destinationlabel"> + <x>477</x> + <y>263</y> + </hint> + </hints> + </connection> + <connection> + <sender>cleanUpToolButton</sender> + <signal>clicked()</signal> + <receiver>logTextEdit</receiver> + <slot>clear()</slot> + <hints> + <hint type="sourcelabel"> + <x>27</x> + <y>282</y> + </hint> + <hint type="destinationlabel"> + <x>22</x> + <y>231</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/debugging/TSLogger.cpp b/src/debugging/TSLogger.cpp new file mode 100755 index 0000000..e7a912b --- /dev/null +++ b/src/debugging/TSLogger.cpp @@ -0,0 +1,251 @@ +/***************************************************************************
+ * Copyright (C) 2006-2012 by Thomas Schweitzer *
+ * thomas-schweitzer(at)arcor.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2.0 as *
+ * published by the Free Software Foundation. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program in the file LICENSE.GPL; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "TSLogger.h"
+#include "ui_TSLoggerDialog.h"
+
+#include "SettingsPaths.h"
+
+#include <QDateTime>
+#include <QFile>
+#include <QFileInfo>
+#include <QUrl>
+#include <QTextStream>
+#include <QDesktopServices>
+#include <QMessageBox>
+
+#include <ctime>
+
+using namespace tschweitzer;
+using namespace tschweitzer::debugging;
+
+TSLogger* TSLogger::_instance = NULL;
+
+/*!
+ \class TSLogger
+ \brief This class handles any kind of data logging, for debugging and whatever purpose.
+
+ Beneath being able of displaying a dialog window containing all log messages of the
+ current session, a log file in the systems temporary directory is used. Its name
+ is "UiGUI_log.html".
+
+ Setting a verbose level allows to only write messages that have the selected minimum
+ priority to the log.
+ */
+
+/*!
+ \brief Returns the only existing instance of TSLogger. If the instance doesn't exist, it will be created.
+ */
+TSLogger* TSLogger::getInstance(int verboseLevel) {
+ if ( _instance == NULL )
+ _instance = new TSLogger(verboseLevel);
+
+ return _instance;
+}
+
+
+/*!
+ \brief Returns the only existing instance of TSLogger. If the instance doesn't exist, it will be created.
+ */
+TSLogger* TSLogger::getInstance() {
+#ifdef _DEBUG
+ return TSLogger::getInstance(QtDebugMsg);
+#else
+ return TSLogger::getInstance(QtWarningMsg);
+#endif
+}
+
+
+/*!
+ \brief Initializes the dialog and sets the path to the log file in the systems temporary directory.
+ Sets the default verbose level to warning level.
+ */
+TSLogger::TSLogger(int verboseLevel) : QDialog() {
+ _TSLoggerDialogForm = new Ui::TSLoggerDialog();
+ _TSLoggerDialogForm->setupUi(this);
+#ifdef _DEBUG
+ _verboseLevel = QtDebugMsg;
+#else
+ _verboseLevel = QtMsgType(verboseLevel);
+#endif
+
+ _logFileInitState = NOTINITIALZED;
+
+ connect( _TSLoggerDialogForm->openLogFileFolderToolButton, SIGNAL(clicked()), this, SLOT(openLogFileFolder()) );
+
+ // Make the main application not to wait for the logging window to close.
+ setAttribute(Qt::WA_QuitOnClose, false);
+}
+
+
+/*!
+ \brief Logs all incoming messages \a msg to the dialogs text edit and to the log file.
+
+ Only messages whos \a type have a higher priority than the set verbose level are logged.
+ */
+void TSLogger::messageHandler(QtMsgType type, const char *msg) {
+ if ( _instance == NULL )
+ _instance = TSLogger::getInstance();
+
+/*
+ QMessageBox messageBox;
+ QString messageBoxText = QString::fromUtf8( msg );
+ messageBox.setText( messageBoxText );
+ messageBox.setWindowModality( Qt::ApplicationModal );
+ messageBox.exec();
+*/
+
+ // Only log messages that have a higher or equal priority than set with the verbose level.
+ if ( type < _instance->_verboseLevel )
+ return;
+
+ // Init log message with prepended date and time.
+ QString message = QDateTime::currentDateTime().toString();
+
+ // Depending on the QtMsgType prepend a different colored Debug, Warning, Critical or Fatal.
+ switch (type) {
+ case QtDebugMsg :
+ message += " <span style=\"font-weight:bold; color:black;\">Debug:</span> ";
+ break;
+ case QtWarningMsg :
+ message += " <span style=\"font-weight:bold; color:gold;\">Warning:</span> ";
+ break;
+ case QtCriticalMsg :
+ message += "<span style=\"font-weight:bold; color:red;\">Critical:</span> ";
+ break;
+ case QtFatalMsg :
+ message += " <span style=\"font-weight:bold; color:#D60000;\">Fatal:</span> ";
+ // This one is no Qt message type, but can be used to send info messages to the log
+ // by calling TSLogger::messageHandler() directly.
+ case TSLoggerInfoMsg :
+ message += " <span style=\"font-weight:bold; color:darkgray;\">Info:</span> ";
+ break;
+ }
+
+ // Append the to UTF-8 back converted message parameter.
+ message += QString::fromUtf8( msg ) + "<br/>\n";
+
+ // Write the message to the log windows text edit.
+ _instance->_TSLoggerDialogForm->logTextEdit->append( message );
+
+ // Write/append the log message to the log file.
+ _instance->writeToLogFile( message );
+
+ // In case of a fatal error abort the application.
+ if ( type == QtFatalMsg )
+ abort();
+}
+
+
+/*!
+ \brief Calling this the verbose level can be set in a range from 0 to 3
+ which is equal to debug, warning, critical and fatal priority.
+ */
+void TSLogger::setVerboseLevel(int level) {
+ if ( level < 0 )
+ _verboseLevel = QtDebugMsg;
+ if ( level > 3 )
+ _verboseLevel = QtFatalMsg;
+ else
+ _verboseLevel = QtMsgType(level);
+}
+
+
+/*!
+ \brief Deletes the existing _instance of TSLogger.
+ */
+void TSLogger::deleteInstance() {
+ if ( _instance != NULL ) {
+ delete _instance;
+ _instance = NULL;
+ }
+}
+
+
+/*!
+ \brief Opens the folder that contains the created log file with the name "UiGUI_log.html".
+ */
+void TSLogger::openLogFileFolder() {
+ QDesktopServices::openUrl( QFileInfo( _logFile ).absolutePath() );
+}
+
+
+/*!
+ \brief Writes the \a message to the used log file.
+ */
+void TSLogger::writeToLogFile(const QString &message) {
+ // If the file where all logging messages should go to isn't initilized yet, do that now.
+ if ( _logFileInitState == NOTINITIALZED ) {
+ _logFileInitState = INITIALIZING;
+
+ // On different systems it may be that "QDir::tempPath()" ends with a "/" or not. So check this.
+ // Remove any trailing slashes.
+ QString tempPath = QFileInfo( SettingsPaths::getTempPath() ).absolutePath();
+ while ( tempPath.right(1) == "/" ) {
+ tempPath.chop(1);
+ }
+
+ // To make the temporary log file invulnerable against file symbolic link hacks
+ // append the current date and time up to milliseconds to its name and a random character.
+ QString logFileName = "UiGUI_log_" + QDateTime::currentDateTime().toString("yyyyMMdd");
+ logFileName += "-" + QDateTime::currentDateTime().toString("hhmmsszzz");
+ // By random decide whether to append a number or an upper or lower case character.
+ qsrand( time(NULL) );
+ unsigned char randomChar;
+ switch ( qrand() % 3 ) {
+ // Append a number from 0 to 9.
+ case 0 :
+ randomChar = qrand() % 10 + '0';
+ break;
+ // Append a upper case characer between A and Z.
+ case 1 :
+ randomChar = qrand() % 26 + 'A';
+ break;
+ // Append a lower case characer between a and z.
+ default :
+ randomChar = qrand() % 26 + 'a';
+ break;
+ }
+ logFileName += "_" + QString(randomChar) + ".html";
+
+ _logFile.setFileName( tempPath + "/" + logFileName );
+
+ // Set the tooltip of the open log file folder button to show the unique name of the log file.
+ _TSLoggerDialogForm->openLogFileFolderToolButton->setToolTip( _TSLoggerDialogForm->openLogFileFolderToolButton->toolTip() + " (" + logFileName + ")" );
+
+ _logFileInitState = INITIALZED;
+ }
+
+ // Add the message to the message queue.
+ _messageQueue << message;
+
+ // If the logging file is initialzed, write all messages contained in the message queue into the file.
+ if ( _logFileInitState == INITIALZED ) {
+ // Write/append the log message to the log file.
+ if ( _logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append) ) {
+ QTextStream out(&_logFile);
+
+ while ( !_messageQueue.isEmpty() ) {
+ out << _messageQueue.takeFirst() << "\n";
+ }
+
+ _logFile.close();
+ }
+ }
+}
diff --git a/src/debugging/TSLogger.h b/src/debugging/TSLogger.h new file mode 100755 index 0000000..c7e7e62 --- /dev/null +++ b/src/debugging/TSLogger.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef TSLogger_H +#define TSLogger_H + +#include <QDialog> +#include <QFile> + +namespace Ui { + class TSLoggerDialog; +} + +namespace tschweitzer { namespace debugging { + +#define TSLoggerInfoMsg QtMsgType(4) + +class TSLogger : public QDialog +{ + Q_OBJECT + +public: + static TSLogger* getInstance(int verboseLevel); + static TSLogger* getInstance(); + static void messageHandler(QtMsgType type, const char *msg); + static void deleteInstance(); + void setVerboseLevel(int level); + +private slots: + void openLogFileFolder(); + +private: + Ui::TSLoggerDialog *_TSLoggerDialogForm; + + enum LogFileInitState { NOTINITIALZED, INITIALIZING, INITIALZED } _logFileInitState; + TSLogger(int verboseLevel); + void writeToLogFile(const QString &message); + + static TSLogger* _instance; + QtMsgType _verboseLevel; + QFile _logFile; + QStringList _messageQueue; +}; + +}} // namespace tschweitzer::debugging + +#endif // TSLogger_H diff --git a/src/debugging/TSLoggerDialog.ui b/src/debugging/TSLoggerDialog.ui new file mode 100755 index 0000000..3a83146 --- /dev/null +++ b/src/debugging/TSLoggerDialog.ui @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TSLoggerDialog</class> + <widget class="QDialog" name="TSLoggerDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1030</width> + <height>263</height> + </rect> + </property> + <property name="windowTitle"> + <string>Log</string> + </property> + <property name="windowIcon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-properties.png</normaloff>:/mainWindow/document-properties.png</iconset> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Logged messages</string> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="logTextEdit"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QToolButton" name="cleanUpToolButton"> + <property name="toolTip"> + <string>Clear log</string> + </property> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/edit-clear.png</normaloff>:/mainWindow/edit-clear.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="openLogFileFolderToolButton"> + <property name="toolTip"> + <string>Open folder containing log file.</string> + </property> + <property name="statusTip"> + <string>Open folder containing log file.</string> + </property> + <property name="icon"> + <iconset resource="../resources/Icons.qrc"> + <normaloff>:/mainWindow/document-open.png</normaloff>:/mainWindow/document-open.png</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources> + <include location="../resources/Icons.qrc"/> + </resources> + <connections> + <connection> + <sender>TSLoggerDialog</sender> + <signal>finished(int)</signal> + <receiver>TSLoggerDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>2</x> + <y>45</y> + </hint> + <hint type="destinationlabel"> + <x>5</x> + <y>59</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>TSLoggerDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>419</x> + <y>280</y> + </hint> + <hint type="destinationlabel"> + <x>477</x> + <y>263</y> + </hint> + </hints> + </connection> + <connection> + <sender>cleanUpToolButton</sender> + <signal>clicked()</signal> + <receiver>logTextEdit</receiver> + <slot>clear()</slot> + <hints> + <hint type="sourcelabel"> + <x>27</x> + <y>282</y> + </hint> + <hint type="destinationlabel"> + <x>22</x> + <y>231</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 0000000..6e09f3e --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,279 @@ +/*************************************************************************** + * Copyright (C) 2006-2012 by Thomas Schweitzer * + * thomas-schweitzer(at)arcor.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License version 2.0 as * + * published by the Free Software Foundation. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program in the file LICENSE.GPL; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "MainWindow.h" + +#include "UiGuiIndentServer.h" +#include "debugging/TSLogger.h" +#include "UiGuiIniFileParser.h" +#include "UiGuiSettings.h" +#include "UiGuiVersion.h" +#include "UiGuiSystemInfo.h" +#include "IndentHandler.h" +#include "SettingsPaths.h" + +#include <QApplication> +#include <QTextCodec> +#include <QDebug> + +#include <string> +#include <iostream> +#include <algorithm> +#include <tclap/CmdLine.h> + +#ifdef _MSC_VER + +#include <windows.h> +#include <direct.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <io.h> +#include <iostream> +#include <fstream> + +/** + \brief Calling this function tries to attach to the console of the parent process and + redirect all inputs and outputs from and to this console. + + The redirected streams are stdout, stdin, stderr, cout, wcout, cin, wcin, wcerr, cerr, wclog and clog. + + Code based on info from http://dslweb.nwnexus.com/~ast/dload/guicon.htm. + */ +bool attachToConsole(/*enum ATTACH_ONLY|TRY_ATTACH_ELSE_CREATE|CREATE_NEW*/) +{ + int hConHandle; + long lStdHandle; + CONSOLE_SCREEN_BUFFER_INFO coninfo; + FILE *fp; + + // Trying to attach to the console of the parent process. + BOOL successful = AttachConsole(ATTACH_PARENT_PROCESS); + // In case that the parent process has no console return false and do no input/output redirection. + if ( !successful ) + return false; + + // Set the screen buffer to be big enough to let us scroll text + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); + // Set maximum console lines. + coninfo.dwSize.Y = 500; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); + + // Redirect unbuffered STDOUT to the console. + lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if ( hConHandle != -1 ) { + fp = _fdopen( hConHandle, "w" ); + *stdout = *fp; + setvbuf( stdout, NULL, _IONBF, 0 ); + } + + // Redirect unbuffered STDIN to the console. + lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if ( hConHandle != -1 ) { + fp = _fdopen( hConHandle, "r" ); + *stdin = *fp; + setvbuf( stdin, NULL, _IONBF, 0 ); + } + + // Redirect unbuffered STDERR to the console. + lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if ( hConHandle != -1 ) { + fp = _fdopen( hConHandle, "w" ); + *stderr = *fp; + setvbuf( stderr, NULL, _IONBF, 0 ); + } + + // Make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well. + std::ios::sync_with_stdio(); + + return true; +} +#else +bool attachToConsole() +{ + return false; +} + +#endif + +using namespace tschweitzer::debugging; + +/*! + /brief Entry point to UniversalIndentGUI application. + + Evaluates the following parameters: + No parameters starts without server and full gui. + A string without any parameter prefix will be loaded as file on start. + -p --plugin : Run as plugin. Server will be started with a simplified gui. + -s --server : Run as server only without gui. + If -p and -s are set, -p will be used. + -v --verbose needs a following parameter defining the verbose level as a number from 0 to 3. + */ +int main(int argc, char *argv[]) { + QString file2OpenOnStart = ""; + int verboseLevel = 1; + bool startAsPlugin = false; + bool startAsServer = false; + bool tclapExitExceptionThrown = false; + int returnValue = 0; + + bool attachedToConsole = false; + attachedToConsole = attachToConsole(); + +#ifdef __APPLE__ + // Filter out -psn_0_118813 and similar parameters. + std::vector<char*> argList; + for ( int i = 0; i < argc; i++ ) { + QString argString(argv[i]); + + if ( argString.startsWith("-psn_") == false ) { + argList.push_back(argv[i]); + } + else { +// std::cerr << std::endl << "The parameter "<< i << " is an invalid finder parameter. Parameter was " << argv[i] << std::endl; + } + } + for ( size_t i = 0; i < argList.size(); i++ ) { + argv[i] = argList.at(i); + } + argc = argList.size(); +#endif + + // Wrap everything in a try block. Do this every time, + // because exceptions will be thrown for problems. + try { + // Define the command line object. + TCLAP::CmdLine cmd("If -p and -s are set, -p will be used.\nGiving no parameters starts full gui without server.", ' ', "UiGUI version " PROGRAM_VERSION_STRING " " PROGRAM_REVISION); + cmd.setExceptionHandling(false); + + // Define a value argument and add it to the command line. + TCLAP::UnlabeledValueArg<std::string> filenameArg("file", "Opens the by filename defined file on start" , false, "", "filename"); + cmd.add( filenameArg ); + + // Define a switch and add it to the command line. + TCLAP::SwitchArg pluginSwitch("p", "plugin", "Run as plugin. Server will be started with a simplified gui", false); + cmd.add( pluginSwitch ); + + // Define a switch and add it to the command line. + TCLAP::SwitchArg serverSwitch("s", "server", "Run as server only without gui", false); + cmd.add( serverSwitch ); + + // Define a value argument and add it to the command line. + TCLAP::ValueArg<int> verboselevelArg("v", "verbose", "Sets how many info is written to the log. 0 means with debug info, 3 means critical messages only" , false, 1, "int"); + cmd.add( verboselevelArg ); + + // Parse the args. + cmd.parse( argc, argv ); + + // Get the value parsed by each arg. + file2OpenOnStart = filenameArg.getValue().c_str(); + startAsPlugin = pluginSwitch.getValue(); + startAsServer = serverSwitch.getValue(); + verboseLevel = verboselevelArg.getValue(); + } + catch (TCLAP::ArgException &e) { // catch arg exceptions + std::cerr << std::endl << "error: " << e.error() << ". " << e.argId() << std::endl; + returnValue = 1; + } + catch (TCLAP::ExitException &e) { // catch exit exceptions + tclapExitExceptionThrown = true; + returnValue = e.getExitStatus(); + } + catch (...) { // catch any exceptions + std::cerr << std::endl << "There was an error! Maybe faulty command line arguments set. See --help." << std::endl; + returnValue = 1; + } + + if ( returnValue != 0 || tclapExitExceptionThrown ) { +#ifdef _MSC_VER + if ( attachedToConsole ) { + // Workaround for skipped command line prompt: Get the current working directory and print it to console. + char* buffer; + if( (buffer = _getcwd( NULL, 0 )) != NULL ) { + std::cerr << std::endl << buffer << ">"; + free(buffer); + } + // Release the connection to the parents console. + FreeConsole(); + } +#endif + return returnValue; + } + + QApplication app(argc, argv); + UiGuiIndentServer server; + MainWindow *mainWindow = NULL; + IndentHandler *indentHandler = NULL; + + // Init and install the logger function. + // Setting UTF-8 as default 8-Bit encoding to ensure that qDebug does no false string conversion. + QTextCodec::setCodecForCStrings( QTextCodec::codecForName("UTF-8") ); + QTextCodec::setCodecForLocale( QTextCodec::codecForName("UTF-8") ); + // Force creation of an TSLogger instance here, to avoid recursion with SettingsPaths init function. +#ifdef _DEBUG + TSLogger::getInstance(0); +#else + TSLogger::getInstance(verboseLevel); +#endif + qInstallMsgHandler( TSLogger::messageHandler ); + TSLogger::messageHandler( TSLoggerInfoMsg, QString("Starting UiGUI Version %1 %2").arg(PROGRAM_VERSION_STRING).arg(PROGRAM_REVISION).toAscii() ); + TSLogger::messageHandler( TSLoggerInfoMsg, QString("Running on %1").arg(UiGuiSystemInfo::getOperatingSystem()).toAscii() ); + + // Set default values for all by UniversalIndentGUI used settings objects. + QCoreApplication::setOrganizationName("UniversalIndentGUI"); + QCoreApplication::setOrganizationDomain("universalindent.sf.net"); + QCoreApplication::setApplicationName("UniversalIndentGUI"); + + // Start normal with full gui and without server. + if ( !startAsPlugin && !startAsServer ) { + mainWindow = new MainWindow(file2OpenOnStart); + mainWindow->show(); + } + // Start as plugin with server. + else if ( startAsPlugin ) { + server.startServer(); + indentHandler = new IndentHandler(0); + indentHandler->show(); + } + // Start as server only without any gui. + else if ( startAsServer ) { + server.startServer(); + } + + try { + returnValue = app.exec(); + } + catch (std::exception &ex) { + qCritical() << __LINE__ << " " << __FUNCTION__ << ": Something went terribly wrong:" << ex.what(); + } + + if ( startAsPlugin || startAsServer ) + server.stopServer(); + + delete indentHandler; + delete mainWindow; + + SettingsPaths::cleanAndRemoveTempDir(); + TSLogger::deleteInstance(); + + return returnValue; +} diff --git a/src/tclap/.svn/all-wcprops b/src/tclap/.svn/all-wcprops new file mode 100755 index 0000000..9b2aa5c --- /dev/null +++ b/src/tclap/.svn/all-wcprops @@ -0,0 +1,161 @@ +K 25 +svn:wc:ra_dav:version-url +V 54 +/svnroot/universalindent/!svn/ver/1011/trunk/src/tclap +END +SwitchArg.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/SwitchArg.h +END +Makefile.in +K 25 +svn:wc:ra_dav:version-url +V 65 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/Makefile.in +END +CmdLineOutput.h +K 25 +svn:wc:ra_dav:version-url +V 69 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/CmdLineOutput.h +END +CmdLineInterface.h +K 25 +svn:wc:ra_dav:version-url +V 72 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/CmdLineInterface.h +END +Visitor.h +K 25 +svn:wc:ra_dav:version-url +V 63 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/Visitor.h +END +ArgTraits.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/ArgTraits.h +END +UnlabeledMultiArg.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/UnlabeledMultiArg.h +END +IgnoreRestVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/IgnoreRestVisitor.h +END +DocBookOutput.h +K 25 +svn:wc:ra_dav:version-url +V 69 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/DocBookOutput.h +END +ValuesConstraint.h +K 25 +svn:wc:ra_dav:version-url +V 72 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/ValuesConstraint.h +END +VersionVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/VersionVisitor.h +END +MultiSwitchArg.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/MultiSwitchArg.h +END +ValueArg.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/ValueArg.h +END +XorHandler.h +K 25 +svn:wc:ra_dav:version-url +V 66 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/XorHandler.h +END +HelpVisitor.h +K 25 +svn:wc:ra_dav:version-url +V 67 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/HelpVisitor.h +END +Arg.h +K 25 +svn:wc:ra_dav:version-url +V 59 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/Arg.h +END +CmdLine.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/svnroot/universalindent/!svn/ver/1011/trunk/src/tclap/CmdLine.h +END +StdOutput.h +K 25 +svn:wc:ra_dav:version-url +V 65 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/StdOutput.h +END +OptionalUnlabeledTracker.h +K 25 +svn:wc:ra_dav:version-url +V 80 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/OptionalUnlabeledTracker.h +END +ZshCompletionOutput.h +K 25 +svn:wc:ra_dav:version-url +V 75 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/ZshCompletionOutput.h +END +UnlabeledValueArg.h +K 25 +svn:wc:ra_dav:version-url +V 73 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/UnlabeledValueArg.h +END +Makefile.am +K 25 +svn:wc:ra_dav:version-url +V 65 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/Makefile.am +END +MultiArg.h +K 25 +svn:wc:ra_dav:version-url +V 64 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/MultiArg.h +END +Constraint.h +K 25 +svn:wc:ra_dav:version-url +V 66 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/Constraint.h +END +StandardTraits.h +K 25 +svn:wc:ra_dav:version-url +V 70 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/StandardTraits.h +END +ArgException.h +K 25 +svn:wc:ra_dav:version-url +V 68 +/svnroot/universalindent/!svn/ver/992/trunk/src/tclap/ArgException.h +END diff --git a/src/tclap/.svn/entries b/src/tclap/.svn/entries new file mode 100755 index 0000000..605f3ad --- /dev/null +++ b/src/tclap/.svn/entries @@ -0,0 +1,912 @@ +10 + +dir +1074 +https://universalindent.svn.sourceforge.net/svnroot/universalindent/trunk/src/tclap +https://universalindent.svn.sourceforge.net/svnroot/universalindent + + + +2010-09-12T18:15:49.802183Z +1011 +thomas_-_s + + + + + + + + + + + + + + +c764a436-2d14-0410-8e4b-8664b97a5d8c + +Arg.h +file + + + + +2011-12-26T15:10:20.000000Z +09340efa3f5cc9e93bf4eb26e9d284d0 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +16870 + +ArgException.h +file + + + + +2011-12-26T15:10:20.000000Z +add3605d743e771cd6513d7355f3ba78 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +5044 + +ArgTraits.h +file + + + + +2011-12-26T15:10:20.000000Z +c149e1b3a809bbff8dfda3c4a5f76e4c +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +2491 + +CmdLine.h +file + + + + +2011-12-26T15:10:20.000000Z +e0dddb44d8d6bb2528dc422b6c78c4ad +2010-09-12T18:15:49.802183Z +1011 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +13470 + +CmdLineInterface.h +file + + + + +2011-12-26T15:10:20.000000Z +0237df8c4d116c7069f32ec4516b770d +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +3627 + +CmdLineOutput.h +file + + + + +2011-12-26T15:10:20.000000Z +5784b4f0dbad77f47328a0ba9dcbf2ce +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1925 + +Constraint.h +file + + + + +2011-12-26T15:10:20.000000Z +e9497994c72ce633bda4ed865cb0f1f6 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1800 + +DocBookOutput.h +file + + + + +2011-12-26T15:10:20.000000Z +fb4a662ffb86c86481753e4a4cce850c +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +8356 + +HelpVisitor.h +file + + + + +2011-12-26T15:10:20.000000Z +f432610edb2ff493b4a20f69dac67409 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1799 + +IgnoreRestVisitor.h +file + + + + +2011-12-26T15:10:20.000000Z +5b27cd9d577831297d19c3383f3f3eec +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1335 + +Makefile.am +file + + + + +2011-12-26T15:10:20.000000Z +f9e6594d9210175e8b4a6cdda7c483db +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +577 + +Makefile.in +file + + + + +2011-12-26T15:10:20.000000Z +a5268723844f898de6231869dda71b18 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +11654 + +MultiArg.h +file + + + + +2011-12-26T15:10:20.000000Z +bacd0ddec8b55cc17e5ab4bf40eb41ba +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +11756 + +MultiSwitchArg.h +file + + + + +2011-12-26T15:10:20.000000Z +7e669d165cb2c6402d7264828948d4f9 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +5627 + +OptionalUnlabeledTracker.h +file + + + + +2011-12-26T15:10:20.000000Z +f9333d5483b7d17e80da895c595aaf9b +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1721 + +StandardTraits.h +file + + + + +2011-12-26T15:10:20.000000Z +1cb176d1d90a53b7a08ffc0b9e663465 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +3975 + +StdOutput.h +file + + + + +2011-12-26T15:10:20.000000Z +08a4119d6d4a2cce997c5f160df1f232 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +8452 + +SwitchArg.h +file + + + + +2011-12-26T15:10:20.000000Z +6d76231f04804a4a435e0794cf0ccc3f +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +6509 + +UnlabeledMultiArg.h +file + + + + +2011-12-26T15:10:20.000000Z +d393b2eb56e557c986d2b8fea90e6160 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +9619 + +UnlabeledValueArg.h +file + + + + +2011-12-26T15:10:20.000000Z +7a6b40bb7dbd6f64ba6a7e6891754cf0 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +11445 + +ValueArg.h +file + + + + +2011-12-26T15:10:20.000000Z +0f7d76772ff882bcd713ad787f88eb92 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +13774 + +ValuesConstraint.h +file + + + + +2011-12-26T15:10:20.000000Z +b5e4d680c9b833a1f25528de649d85f0 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +3184 + +VersionVisitor.h +file + + + + +2011-12-26T15:10:20.000000Z +7a04573b6407dc141dea0e2b4a5f0b28 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1871 + +Visitor.h +file + + + + +2011-12-26T15:10:20.000000Z +ab867636e6271b3476d6a679b2e73d1a +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +1258 + +XorHandler.h +file + + + + +2011-12-26T15:10:20.000000Z +44270ab0432092c3e32618c0cb91b3e2 +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +3967 + +ZshCompletionOutput.h +file + + + + +2011-12-26T15:10:20.000000Z +090a702ea2dd93dd4ce47dabdc70335c +2009-12-22T23:07:56.706565Z +992 +thomas_-_s +has-props + + + + + + + + + + + + + + + + + + + + +7931 + diff --git a/src/tclap/.svn/prop-base/Arg.h.svn-base b/src/tclap/.svn/prop-base/Arg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/Arg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/ArgException.h.svn-base b/src/tclap/.svn/prop-base/ArgException.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/ArgException.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/ArgTraits.h.svn-base b/src/tclap/.svn/prop-base/ArgTraits.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/ArgTraits.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/CmdLine.h.svn-base b/src/tclap/.svn/prop-base/CmdLine.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/CmdLine.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/CmdLineInterface.h.svn-base b/src/tclap/.svn/prop-base/CmdLineInterface.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/CmdLineInterface.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/CmdLineOutput.h.svn-base b/src/tclap/.svn/prop-base/CmdLineOutput.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/CmdLineOutput.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/Constraint.h.svn-base b/src/tclap/.svn/prop-base/Constraint.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/Constraint.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/DocBookOutput.h.svn-base b/src/tclap/.svn/prop-base/DocBookOutput.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/DocBookOutput.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/HelpVisitor.h.svn-base b/src/tclap/.svn/prop-base/HelpVisitor.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/HelpVisitor.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/IgnoreRestVisitor.h.svn-base b/src/tclap/.svn/prop-base/IgnoreRestVisitor.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/IgnoreRestVisitor.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/Makefile.am.svn-base b/src/tclap/.svn/prop-base/Makefile.am.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/Makefile.am.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/Makefile.in.svn-base b/src/tclap/.svn/prop-base/Makefile.in.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/Makefile.in.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/MultiArg.h.svn-base b/src/tclap/.svn/prop-base/MultiArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/MultiArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/MultiSwitchArg.h.svn-base b/src/tclap/.svn/prop-base/MultiSwitchArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/MultiSwitchArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/OptionalUnlabeledTracker.h.svn-base b/src/tclap/.svn/prop-base/OptionalUnlabeledTracker.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/OptionalUnlabeledTracker.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/StandardTraits.h.svn-base b/src/tclap/.svn/prop-base/StandardTraits.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/StandardTraits.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/StdOutput.h.svn-base b/src/tclap/.svn/prop-base/StdOutput.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/StdOutput.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/SwitchArg.h.svn-base b/src/tclap/.svn/prop-base/SwitchArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/SwitchArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/UnlabeledMultiArg.h.svn-base b/src/tclap/.svn/prop-base/UnlabeledMultiArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/UnlabeledMultiArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/UnlabeledValueArg.h.svn-base b/src/tclap/.svn/prop-base/UnlabeledValueArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/UnlabeledValueArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/ValueArg.h.svn-base b/src/tclap/.svn/prop-base/ValueArg.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/ValueArg.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/ValuesConstraint.h.svn-base b/src/tclap/.svn/prop-base/ValuesConstraint.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/ValuesConstraint.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/VersionVisitor.h.svn-base b/src/tclap/.svn/prop-base/VersionVisitor.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/VersionVisitor.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/Visitor.h.svn-base b/src/tclap/.svn/prop-base/Visitor.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/Visitor.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/XorHandler.h.svn-base b/src/tclap/.svn/prop-base/XorHandler.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/XorHandler.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/prop-base/ZshCompletionOutput.h.svn-base b/src/tclap/.svn/prop-base/ZshCompletionOutput.h.svn-base new file mode 100755 index 0000000..bdbd305 --- /dev/null +++ b/src/tclap/.svn/prop-base/ZshCompletionOutput.h.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:eol-style +V 6 +native +END diff --git a/src/tclap/.svn/text-base/Arg.h.svn-base b/src/tclap/.svn/text-base/Arg.h.svn-base new file mode 100755 index 0000000..3d44c85 --- /dev/null +++ b/src/tclap/.svn/text-base/Arg.h.svn-base @@ -0,0 +1,672 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: Arg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARGUMENT_H +#define TCLAP_ARGUMENT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <cstdio> + +#if defined(HAVE_SSTREAM) +#include <sstream> +typedef std::istringstream istringstream; +#elif defined(HAVE_STRSTREAM) +#include <strstream> +typedef std::istrstream istringstream; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +#include <tclap/ArgException.h> +#include <tclap/Visitor.h> +#include <tclap/CmdLineInterface.h> +#include <tclap/ArgTraits.h> +#include <tclap/StandardTraits.h> + +namespace TCLAP { + +/** + * A virtual base class that defines the essential data for all arguments. + * This class, or one of its existing children, must be subclassed to do + * anything. + */ +class Arg +{ + private: + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool& ignoreRestRef() { static bool ign = false; return ign; } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char& delimiterRef() { static char delim = ' '; return delim; } + + protected: + + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor* _visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v = NULL ); + + public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Currently '-'. + */ + static char flagStartChar() { return '-'; } + + /** + * The sting that indicates the beginning of a flag. Currently "-". + * Should be identical to flagStartChar. + */ + static const std::string flagStartString() { return "-"; } + + /** + * The sting that indicates the beginning of a name. Currently "--". + * Should be flagStartChar twice. + */ + static const std::string nameStartString() { return "--"; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter( char c ) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector<std::string>& args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Returns the argument flag. + */ + const std::string& getFlag() const; + + /** + * Returns the argument name. + */ + const std::string& getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches( const std::string& s ) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID( const std::string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID( const std::string& valueId = "val" ) const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag( std::string& flag, std::string& value ) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks( const std::string& s ) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel( const std::string& s ); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); +}; + +/** + * Typedef of an Arg list iterator. + */ +typedef std::list<Arg*>::iterator ArgListIterator; + +/** + * Typedef of an Arg vector iterator. + */ +typedef std::vector<Arg*>::iterator ArgVectorIterator; + +/** + * Typedef of a Visitor list iterator. + */ +typedef std::list<Visitor*>::iterator VisitorListIterator; + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * ValueLike traits use operator>> to assign the value from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) +{ + static_cast<void>(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while ( is.good() ) { + if ( is.peek() != EOF ) +#ifdef TCLAP_SETBASE_ZERO + is >> std::setbase(0) >> destVal; +#else + is >> destVal; +#endif + else + break; + + valuesRead++; + } + + if ( is.fail() ) + throw( ArgParseException("Couldn't read argument value " + "from string '" + strVal + "'")); + + + if ( valuesRead > 1 ) + throw( ArgParseException("More than one valid value parsed from " + "string '" + strVal + "'")); + +} + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * StringLike uses assignment (operator=) to assign from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, StringLike sl) +{ + static_cast<void>(sl); // Avoid warning about unused sl + SetString(destVal, strVal); +} + +////////////////////////////////////////////////////////////////////// +//BEGIN Arg.cpp +////////////////////////////////////////////////////////////////////// + +inline Arg::Arg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v) : + _flag(flag), + _name(name), + _description(desc), + _required(req), + _requireLabel("required"), + _valueRequired(valreq), + _alreadySet(false), + _visitor( v ), + _ignoreable(true), + _xorSet(false), + _acceptsMultipleValues(false) +{ + if ( _flag.length() > 1 ) + throw(SpecificationException( + "Argument flag can only be one character long", toString() ) ); + + if ( _name != ignoreNameString() && + ( _flag == Arg::flagStartString() || + _flag == Arg::nameStartString() || + _flag == " " ) ) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString() ) ); + + if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || + ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || + ( _name.find( " ", 0 ) != std::string::npos ) ) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString() ) ); + +} + +inline Arg::~Arg() { } + +inline std::string Arg::shortID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +inline std::string Arg::longID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + { + id += Arg::flagStartString() + _flag; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + id += ", "; + } + + id += Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + return id; + +} + +inline bool Arg::operator==(const Arg& a) const +{ + if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) + return true; + else + return false; +} + +inline std::string Arg::getDescription() const +{ + std::string desc = ""; + if ( _required ) + desc = "(" + _requireLabel + ") "; + +// if ( _valueRequired ) +// desc += "(value required) "; + + desc += _description; + return desc; +} + +inline const std::string& Arg::getFlag() const { return _flag; } + +inline const std::string& Arg::getName() const { return _name; } + +inline bool Arg::isRequired() const { return _required; } + +inline bool Arg::isValueRequired() const { return _valueRequired; } + +inline bool Arg::isSet() const +{ + if ( _alreadySet && !_xorSet ) + return true; + else + return false; +} + +inline bool Arg::isIgnoreable() const { return _ignoreable; } + +inline void Arg::setRequireLabel( const std::string& s) +{ + _requireLabel = s; +} + +inline bool Arg::argMatches( const std::string& argFlag ) const +{ + if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || + argFlag == Arg::nameStartString() + _name ) + return true; + else + return false; +} + +inline std::string Arg::toString() const +{ + std::string s = ""; + + if ( _flag != "" ) + s += Arg::flagStartString() + _flag + " "; + + s += "(" + Arg::nameStartString() + _name + ")"; + + return s; +} + +inline void Arg::_checkWithVisitor() const +{ + if ( _visitor != NULL ) + _visitor->visit(); +} + +/** + * Implementation of trimFlag. + */ +inline void Arg::trimFlag(std::string& flag, std::string& value) const +{ + int stop = 0; + for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ ) + if ( flag[i] == Arg::delimiter() ) + { + stop = i; + break; + } + + if ( stop > 1 ) + { + value = flag.substr(stop+1); + flag = flag.substr(0,stop); + } + +} + +/** + * Implementation of _hasBlanks. + */ +inline bool Arg::_hasBlanks( const std::string& s ) const +{ + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] == Arg::blankChar() ) + return true; + + return false; +} + +inline void Arg::forceRequired() +{ + _required = true; +} + +inline void Arg::xorSet() +{ + _alreadySet = true; + _xorSet = true; +} + +/** + * Overridden by Args that need to added to the end of the list. + */ +inline void Arg::addToList( std::list<Arg*>& argList ) const +{ + argList.push_front( const_cast<Arg*>(this) ); +} + +inline bool Arg::allowMore() +{ + return false; +} + +inline bool Arg::acceptsMultipleValues() +{ + return _acceptsMultipleValues; +} + +inline void Arg::reset() +{ + _xorSet = false; + _alreadySet = false; +} + +////////////////////////////////////////////////////////////////////// +//END Arg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif + diff --git a/src/tclap/.svn/text-base/ArgException.h.svn-base b/src/tclap/.svn/text-base/ArgException.h.svn-base new file mode 100755 index 0000000..3411aa9 --- /dev/null +++ b/src/tclap/.svn/text-base/ArgException.h.svn-base @@ -0,0 +1,200 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgException.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARG_EXCEPTION_H +#define TCLAP_ARG_EXCEPTION_H + +#include <string> +#include <exception> + +namespace TCLAP { + +/** + * A simple class that defines and argument exception. Should be caught + * whenever a CmdLine is created and parsed. + */ +class ArgException : public std::exception +{ + public: + + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException( const std::string& text = "undefined exception", + const std::string& id = "undefined", + const std::string& td = "Generic ArgException") + : std::exception(), + _errorText(text), + _argId( id ), + _typeDescription(td) + { } + + /** + * Destructor. + */ + virtual ~ArgException() throw() { } + + /** + * Returns the error text. + */ + std::string error() const { return ( _errorText ); } + + /** + * Returns the argument id. + */ + std::string argId() const + { + if ( _argId == "undefined" ) + return " "; + else + return ( "Argument: " + _argId ); + } + + /** + * Returns the arg id and error text. + */ + const char* what() const throw() + { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const + { + return _typeDescription; + } + + + private: + + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; + +}; + +/** + * Thrown from within the child Arg classes when it fails to properly + * parse the argument it has been passed. + */ +class ArgParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found while parsing " ) + + std::string( "the value the Arg has been passed." )) + { } +}; + +/** + * Thrown from CmdLine when the arguments on the command line are not + * properly specified, e.g. too many arguments, required argument missing, etc. + */ +class CmdLineParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found when the values ") + + std::string( "on the command line do not meet ") + + std::string( "the requirements of the defined ") + + std::string( "Args." )) + { } +}; + +/** + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * same flag as another Arg, same name, etc. + */ +class SpecificationException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string("Exception found when an Arg object ")+ + std::string("is improperly defined by the ") + + std::string("developer." )) + { } + +}; + +class ExitException { +public: + ExitException(int estat) : _estat(estat) {} + + int getExitStatus() const { return _estat; } + +private: + int _estat; +}; + +} // namespace TCLAP + +#endif + diff --git a/src/tclap/.svn/text-base/ArgTraits.h.svn-base b/src/tclap/.svn/text-base/ArgTraits.h.svn-base new file mode 100755 index 0000000..a89ed12 --- /dev/null +++ b/src/tclap/.svn/text-base/ArgTraits.h.svn-base @@ -0,0 +1,81 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_ARGTRAITS_H +#define TCLAP_ARGTRAITS_H + +namespace TCLAP { + +// We use two empty structs to get compile type specialization +// function to work + +/** + * A value like argument value type is a value that can be set using + * operator>>. This is the default value type. + */ +struct ValueLike { + typedef ValueLike ValueCategory; +}; + +/** + * A string like argument value type is a value that can be set using + * operator=(string). Usefull if the value type contains spaces which + * will be broken up into individual tokens by operator>>. + */ +struct StringLike {}; + +/** + * A class can inherit from this object to make it have string like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct StringLikeTrait { + typedef StringLike ValueCategory; +}; + +/** + * A class can inherit from this object to make it have value like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct ValueLikeTrait { + typedef ValueLike ValueCategory; +}; + +/** + * Arg traits are used to get compile type specialization when parsing + * argument values. Using an ArgTraits you can specify the way that + * values gets assigned to any particular type during parsing. The two + * supported types are string like and value like. + */ +template<typename T> +struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + //typedef ValueLike ValueCategory; +}; + +#endif + +} // namespace diff --git a/src/tclap/.svn/text-base/CmdLine.h.svn-base b/src/tclap/.svn/text-base/CmdLine.h.svn-base new file mode 100755 index 0000000..90d0e65 --- /dev/null +++ b/src/tclap/.svn/text-base/CmdLine.h.svn-base @@ -0,0 +1,621 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: CmdLine.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINE_H +#define TCLAP_CMDLINE_H + +#include <tclap/SwitchArg.h> +#include <tclap/MultiSwitchArg.h> +#include <tclap/UnlabeledValueArg.h> +#include <tclap/UnlabeledMultiArg.h> + +#include <tclap/XorHandler.h> +#include <tclap/HelpVisitor.h> +#include <tclap/VersionVisitor.h> +#include <tclap/IgnoreRestVisitor.h> + +#include <tclap/CmdLineOutput.h> +#include <tclap/StdOutput.h> + +#include <tclap/Constraint.h> +#include <tclap/ValuesConstraint.h> + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> +#include <stdlib.h> // Needed for exit(), which isn't defined in some envs. + +namespace TCLAP { + +template<typename T> void DelPtr(T ptr) +{ + delete ptr; +} + +template<typename C> void ClearContainer(C &c) +{ + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr<value_type>); + c.clear(); +} + + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLine : public CmdLineInterface +{ + protected: + + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list<Arg*> _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list<Arg*> _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list<Visitor*> _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput* _output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string& s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg* ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor* ptr); + +private: + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + + public: + + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string& message, + const char delimiter = ' ', + const std::string& version = "none", + bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add( Arg& a ); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add( Arg* a ); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd( Arg& a, Arg& b ); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd( std::vector<Arg*>& xors ); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char * const * argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * + */ + CmdLineOutput* getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput* co); + + /** + * + */ + std::string& getVersion(); + + /** + * + */ + std::string& getProgramName(); + + /** + * + */ + std::list<Arg*>& getArgList(); + + /** + * + */ + XorHandler& getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string& getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); + +}; + + +/////////////////////////////////////////////////////////////////////////////// +//Begin CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + +inline CmdLine::CmdLine(const std::string& m, + char delim, + const std::string& v, + bool help ) +: _progName("not_set_yet"), + _message(m), + _version(v), + _numRequired(0), + _delimiter(delim), + _handleExceptions(true), + _userSetOutput(false), + _helpAndVersion(help) +{ + _constructor(); +} + +inline CmdLine::~CmdLine() +{ + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); + + if ( !_userSetOutput ) { + delete _output; + _output = 0; + } +} + +inline void CmdLine::_constructor() +{ + _output = new StdOutput; + + Arg::setDelimiter( _delimiter ); + + Visitor* v; + + if ( _helpAndVersion ) + { + v = new HelpVisitor( this, &_output ); + SwitchArg* help = new SwitchArg("h","help", + "Displays usage information and exits.", + false, v); + add( help ); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor( this, &_output ); + SwitchArg* vers = new SwitchArg("","version", + "Displays version information and exits.", + false, v); + add( vers ); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), + Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", + false, v); + add( ignore ); + deleteOnExit(ignore); + deleteOnExit(v); +} + +inline void CmdLine::xorAdd( std::vector<Arg*>& ors ) +{ + _xorHandler.add( ors ); + + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) + { + (*it)->forceRequired(); + (*it)->setRequireLabel( "OR required" ); + + add( *it ); + } +} + +inline void CmdLine::xorAdd( Arg& a, Arg& b ) +{ + std::vector<Arg*> ors; + ors.push_back( &a ); + ors.push_back( &b ); + xorAdd( ors ); +} + +inline void CmdLine::add( Arg& a ) +{ + add( &a ); +} + +inline void CmdLine::add( Arg* a ) +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + if ( *a == *(*it) ) + throw( SpecificationException( + "Argument with same flag/name already exists!", + a->longID() ) ); + + a->addToList( _argList ); + + if ( a->isRequired() ) + _numRequired++; +} + + +inline void CmdLine::parse(int argc, const char * const * argv) +{ + // this step is necessary so that we have easy access to + // mutable strings. + std::vector<std::string> args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + + parse(args); +} + +inline void CmdLine::parse(std::vector<std::string>& args) +{ + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) { + bool matched = false; + for (ArgListIterator it = _argList.begin(); + it != _argList.end(); it++) { + if ( (*it)->processArg( &i, args ) ) + { + requiredCount += _xorHandler.check( *it ); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if ( !matched && _emptyCombined( args[i] ) ) + matched = true; + + if ( !matched && !Arg::ignoreRest() ) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if ( requiredCount < _numRequired ) + missingArgsException(); + + if ( requiredCount > _numRequired ) + throw(CmdLineParseException("Too many arguments!")); + + } catch ( ArgException& e ) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + try { + _output->failure(*this,e); + } catch ( ExitException &ee ) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); +} + +inline bool CmdLine::_emptyCombined(const std::string& s) +{ + if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) + return false; + + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline void CmdLine::missingArgsException() +{ + int count = 0; + + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + { + if ( (*it)->isRequired() && !(*it)->isSet() ) + { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0,missingArgList.length()-2); + + std::string msg; + if ( count > 1 ) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; + + msg += missingArgList; + + throw(CmdLineParseException(msg)); +} + +inline void CmdLine::deleteOnExit(Arg* ptr) +{ + _argDeleteOnExitList.push_back(ptr); +} + +inline void CmdLine::deleteOnExit(Visitor* ptr) +{ + _visitorDeleteOnExitList.push_back(ptr); +} + +inline CmdLineOutput* CmdLine::getOutput() +{ + return _output; +} + +inline void CmdLine::setOutput(CmdLineOutput* co) +{ + _userSetOutput = true; + _output = co; +} + +inline std::string& CmdLine::getVersion() +{ + return _version; +} + +inline std::string& CmdLine::getProgramName() +{ + return _progName; +} + +inline std::list<Arg*>& CmdLine::getArgList() +{ + return _argList; +} + +inline XorHandler& CmdLine::getXorHandler() +{ + return _xorHandler; +} + +inline char CmdLine::getDelimiter() +{ + return _delimiter; +} + +inline std::string& CmdLine::getMessage() +{ + return _message; +} + +inline bool CmdLine::hasHelpAndVersion() +{ + return _helpAndVersion; +} + +inline void CmdLine::setExceptionHandling(const bool state) +{ + _handleExceptions = state; +} + +inline bool CmdLine::getExceptionHandling() const +{ + return _handleExceptions; +} + +inline void CmdLine::reset() +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + { + (*it)->reset(); + } + + _progName.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +//End CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + + + +} //namespace TCLAP +#endif diff --git a/src/tclap/.svn/text-base/CmdLineInterface.h.svn-base b/src/tclap/.svn/text-base/CmdLineInterface.h.svn-base new file mode 100755 index 0000000..1b25e9b --- /dev/null +++ b/src/tclap/.svn/text-base/CmdLineInterface.h.svn-base @@ -0,0 +1,150 @@ + +/****************************************************************************** + * + * file: CmdLineInterface.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_COMMANDLINE_INTERFACE_H +#define TCLAP_COMMANDLINE_INTERFACE_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + + +namespace TCLAP { + +class Arg; +class CmdLineOutput; +class XorHandler; + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLineInterface +{ + public: + + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add( Arg& a )=0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add( Arg* a )=0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd( Arg& a, Arg& b )=0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd( std::vector<Arg*>& xors )=0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char * const * argv)=0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput* getOutput()=0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput* co)=0; + + /** + * Returns the version string. + */ + virtual std::string& getVersion()=0; + + /** + * Returns the program name string. + */ + virtual std::string& getProgramName()=0; + + /** + * Returns the argList. + */ + virtual std::list<Arg*>& getArgList()=0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler& getXorHandler()=0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter()=0; + + /** + * Returns the message string. + */ + virtual std::string& getMessage()=0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion()=0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset()=0; +}; + +} //namespace + + +#endif diff --git a/src/tclap/.svn/text-base/CmdLineOutput.h.svn-base b/src/tclap/.svn/text-base/CmdLineOutput.h.svn-base new file mode 100755 index 0000000..71ee5a3 --- /dev/null +++ b/src/tclap/.svn/text-base/CmdLineOutput.h.svn-base @@ -0,0 +1,74 @@ + + +/****************************************************************************** + * + * file: CmdLineOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINEOUTPUT_H +#define TCLAP_CMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +class CmdLineInterface; +class ArgException; + +/** + * The interface that any output object must implement. + */ +class CmdLineOutput +{ + + public: + + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} + + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure( CmdLineInterface& c, + ArgException& e )=0; + +}; + +} //namespace TCLAP +#endif diff --git a/src/tclap/.svn/text-base/Constraint.h.svn-base b/src/tclap/.svn/text-base/Constraint.h.svn-base new file mode 100755 index 0000000..a92acf9 --- /dev/null +++ b/src/tclap/.svn/text-base/Constraint.h.svn-base @@ -0,0 +1,68 @@ + +/****************************************************************************** + * + * file: Constraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CONSTRAINT_H +#define TCLAP_CONSTRAINT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +/** + * The interface that defines the interaction between the Arg and Constraint. + */ +template<class T> +class Constraint +{ + + public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const =0; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const =0; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const =0; + + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } +}; + +} //namespace TCLAP +#endif diff --git a/src/tclap/.svn/text-base/DocBookOutput.h.svn-base b/src/tclap/.svn/text-base/DocBookOutput.h.svn-base new file mode 100755 index 0000000..d2f1290 --- /dev/null +++ b/src/tclap/.svn/text-base/DocBookOutput.h.svn-base @@ -0,0 +1,299 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: DocBookOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_DOCBOOKOUTPUT_H +#define TCLAP_DOCBOOKOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates DocBook output for usage() method for the + * given CmdLine and its Args. + */ +class DocBookOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars( std::string& s, char r, std::string& x ); + void removeChar( std::string& s, char r); + void basename( std::string& s ); + + void printShortArg(Arg* it); + void printLongArg(Arg* it); + + char theDelimiter; +}; + + +inline void DocBookOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void DocBookOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "<?xml version='1.0'?>" << std::endl; + std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl; + std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl; + + std::cout << "<refentry>" << std::endl; + + std::cout << "<refmeta>" << std::endl; + std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl; + std::cout << "<manvolnum>1</manvolnum>" << std::endl; + std::cout << "</refmeta>" << std::endl; + + std::cout << "<refnamediv>" << std::endl; + std::cout << "<refname>" << progName << "</refname>" << std::endl; + std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl; + std::cout << "</refnamediv>" << std::endl; + + std::cout << "<refsynopsisdiv>" << std::endl; + std::cout << "<cmdsynopsis>" << std::endl; + + std::cout << "<command>" << progName << "</command>" << std::endl; + + // xor + for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) + { + std::cout << "<group choice='req'>" << std::endl; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + printShortArg((*it)); + + std::cout << "</group>" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + printShortArg((*it)); + + std::cout << "</cmdsynopsis>" << std::endl; + std::cout << "</refsynopsisdiv>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Description</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Options</title>" << std::endl; + + std::cout << "<variablelist>" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "</variablelist>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Version</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << version << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "</refentry>" << std::endl; + +} + +inline void DocBookOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); +} + +inline void DocBookOutput::substituteSpecialChars( std::string& s, + char r, + std::string& x ) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + s.insert(p,x); + } +} + +inline void DocBookOutput::removeChar( std::string& s, char r) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + } +} + +inline void DocBookOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void DocBookOutput::printShortArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id,'<',lt); + substituteSpecialChars(id,'>',gt); + removeChar(id,'['); + removeChar(id,']'); + + std::string choice = "opt"; + if ( a->isRequired() ) + choice = "plain"; + + std::cout << "<arg choice='" << choice << '\''; + if ( a->acceptsMultipleValues() ) + std::cout << " rep='repeat'"; + + + std::cout << '>'; + if ( !a->getFlag().empty() ) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</arg>" << std::endl; + +} + +inline void DocBookOutput::printLongArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc,'<',lt); + substituteSpecialChars(desc,'>',gt); + + std::cout << "<varlistentry>" << std::endl; + + if ( !a->getFlag().empty() ) + { + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->flagStartChar() << a->getFlag(); + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + } + + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + + std::cout << "<listitem>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << desc << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</listitem>" << std::endl; + + std::cout << "</varlistentry>" << std::endl; +} + +} //namespace TCLAP +#endif diff --git a/src/tclap/.svn/text-base/HelpVisitor.h.svn-base b/src/tclap/.svn/text-base/HelpVisitor.h.svn-base new file mode 100755 index 0000000..2cdb997 --- /dev/null +++ b/src/tclap/.svn/text-base/HelpVisitor.h.svn-base @@ -0,0 +1,69 @@ + +/****************************************************************************** + * + * file: HelpVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_HELP_VISITOR_H +#define TCLAP_HELP_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Visitor object that calls the usage method of the given CmdLineOutput + * object for the specified CmdLine object. + */ +class HelpVisitor: public Visitor +{ + protected: + + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } + +}; + +} + +#endif diff --git a/src/tclap/.svn/text-base/IgnoreRestVisitor.h.svn-base b/src/tclap/.svn/text-base/IgnoreRestVisitor.h.svn-base new file mode 100755 index 0000000..e328649 --- /dev/null +++ b/src/tclap/.svn/text-base/IgnoreRestVisitor.h.svn-base @@ -0,0 +1,52 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_IGNORE_REST_VISITOR_H +#define TCLAP_IGNORE_REST_VISITOR_H + +#include <tclap/Visitor.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A Vistor that tells the CmdLine to begin ignoring arguments after + * this one is parsed. + */ +class IgnoreRestVisitor: public Visitor +{ + public: + + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/src/tclap/.svn/text-base/Makefile.am.svn-base b/src/tclap/.svn/text-base/Makefile.am.svn-base new file mode 100755 index 0000000..0e247bf --- /dev/null +++ b/src/tclap/.svn/text-base/Makefile.am.svn-base @@ -0,0 +1,28 @@ + +libtclapincludedir = $(includedir)/tclap + +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + diff --git a/src/tclap/.svn/text-base/Makefile.in.svn-base b/src/tclap/.svn/text-base/Makefile.in.svn-base new file mode 100755 index 0000000..d4b451f --- /dev/null +++ b/src/tclap/.svn/text-base/Makefile.in.svn-base @@ -0,0 +1,387 @@ +# Makefile.in generated by automake 1.9.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = include/tclap +DIST_COMMON = $(libtclapinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ac_cxx_have_long_long.m4 \ + $(top_srcdir)/config/ac_cxx_have_sstream.m4 \ + $(top_srcdir)/config/ac_cxx_have_strstream.m4 \ + $(top_srcdir)/config/ac_cxx_namespaces.m4 \ + $(top_srcdir)/config/bb_enable_doxygen.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libtclapincludedir)" +libtclapincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(libtclapinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_FALSE = @DOC_FALSE@ +DOC_TRUE = @DOC_TRUE@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +HAVE_GNU_COMPILERS_FALSE = @HAVE_GNU_COMPILERS_FALSE@ +HAVE_GNU_COMPILERS_TRUE = @HAVE_GNU_COMPILERS_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +libtclapincludedir = $(includedir)/tclap +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/tclap/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/tclap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-libtclapincludeHEADERS: $(libtclapinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libtclapincludedir)" || $(mkdir_p) "$(DESTDIR)$(libtclapincludedir)" + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(libtclapincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + $(libtclapincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +uninstall-libtclapincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libtclapincludedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-libtclapincludeHEADERS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libtclapincludeHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + ctags distclean distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-libtclapincludeHEADERS \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am \ + uninstall-libtclapincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/tclap/.svn/text-base/MultiArg.h.svn-base b/src/tclap/.svn/text-base/MultiArg.h.svn-base new file mode 100755 index 0000000..460e5cb --- /dev/null +++ b/src/tclap/.svn/text-base/MultiArg.h.svn-base @@ -0,0 +1,422 @@ +/****************************************************************************** + * + * file: MultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_ARGUMENT_H +#define TCLAP_MULTIPLE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { +/** + * An argument that allows multiple values of type T to be specified. Very + * similar to a ValueArg, except a vector of values will be returned + * instead of just one. + */ +template<class T> +class MultiArg : public Arg +{ +public: + typedef std::vector<T> container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + +protected: + + /** + * The list of values parsed from the CmdLine. + */ + std::vector<T> _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue( const std::string& val ); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; + +public: + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector<T>& getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); + +}; + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +/** + * + */ +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +template<class T> +const std::vector<T>& MultiArg<T>::getValue() { return _values; } + +template<class T> +bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + // always take the first one, regardless of start string + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } + else + return false; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; +} + +/** + * Once we've matched the first value, then the arg is no longer + * required. + */ +template<class T> +bool MultiArg<T>::isRequired() const +{ + if ( _required ) + { + if ( _values.size() > 1 ) + return false; + else + return true; + } + else + return false; + +} + +template<class T> +void MultiArg<T>::_extractValue( const std::string& val ) +{ + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory()); + _values.push_back(tmp); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _values.back() ) ) + throw( CmdLineParseException( "Value '" + val + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +bool MultiArg<T>::allowMore() +{ + bool am = _allowMore; + _allowMore = true; + return am; +} + +template<class T> +void MultiArg<T>::reset() +{ + Arg::reset(); + _values.clear(); +} + +} // namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/MultiSwitchArg.h.svn-base b/src/tclap/.svn/text-base/MultiSwitchArg.h.svn-base new file mode 100755 index 0000000..8820b64 --- /dev/null +++ b/src/tclap/.svn/text-base/MultiSwitchArg.h.svn-base @@ -0,0 +1,216 @@ + +/****************************************************************************** +* +* file: MultiSwitchArg.h +* +* Copyright (c) 2003, Michael E. Smoot . +* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. +* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. +* All rights reverved. +* +* See the file COPYING in the top directory of this distribution for +* more information. +* +* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + + +#ifndef TCLAP_MULTI_SWITCH_ARG_H +#define TCLAP_MULTI_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/SwitchArg.h> + +namespace TCLAP { + +/** +* A multiple switch argument. If the switch is set on the command line, then +* the getValue method will return the number of times the switch appears. +*/ +class MultiSwitchArg : public SwitchArg +{ + protected: + + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + + public: + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init = 0, + Visitor* v = NULL); + + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init = 0, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string& val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string& val) const; + + void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ } + +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ + parser.add( this ); +} + +inline int MultiSwitchArg::getValue() { return _value; } + +inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] )) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + _checkWithVisitor(); + + return true; + } + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + // Check for more in argument and increment value. + while ( combinedSwitchesMatch( args[*i] ) ) + ++_value; + + _checkWithVisitor(); + + return false; + } + else + return false; +} + +inline std::string +MultiSwitchArg::shortID(const std::string& val) const +{ + return Arg::shortID(val) + " ... "; +} + +inline std::string +MultiSwitchArg::longID(const std::string& val) const +{ + return Arg::longID(val) + " (accepted multiple times)"; +} + +inline void +MultiSwitchArg::reset() +{ + MultiSwitchArg::_value = MultiSwitchArg::_default; +} + +////////////////////////////////////////////////////////////////////// +//END MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/OptionalUnlabeledTracker.h.svn-base b/src/tclap/.svn/text-base/OptionalUnlabeledTracker.h.svn-base new file mode 100755 index 0000000..8174c5f --- /dev/null +++ b/src/tclap/.svn/text-base/OptionalUnlabeledTracker.h.svn-base @@ -0,0 +1,62 @@ + + +/****************************************************************************** + * + * file: OptionalUnlabeledTracker.h + * + * Copyright (c) 2005, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H +#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H + +#include <string> + +namespace TCLAP { + +class OptionalUnlabeledTracker +{ + + public: + + static void check( bool req, const std::string& argName ); + + static void gotOptional() { alreadyOptionalRef() = true; } + + static bool& alreadyOptional() { return alreadyOptionalRef(); } + + private: + + static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +}; + + +inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) +{ + if ( OptionalUnlabeledTracker::alreadyOptional() ) + throw( SpecificationException( + "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", + argName ) ); + + if ( !req ) + OptionalUnlabeledTracker::gotOptional(); +} + + +} // namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/StandardTraits.h.svn-base b/src/tclap/.svn/text-base/StandardTraits.h.svn-base new file mode 100755 index 0000000..151b851 --- /dev/null +++ b/src/tclap/.svn/text-base/StandardTraits.h.svn-base @@ -0,0 +1,186 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StandardTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_STANDARD_TRAITS_H +#define TCLAP_STANDARD_TRAITS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> // To check for long long +#endif + +namespace TCLAP { + +// ====================================================================== +// Integer types +// ====================================================================== + +/** + * longs have value-like semantics. + */ +template<> +struct ArgTraits<long> { + typedef ValueLike ValueCategory; +}; + +/** + * ints have value-like semantics. + */ +template<> +struct ArgTraits<int> { + typedef ValueLike ValueCategory; +}; + +/** + * shorts have value-like semantics. + */ +template<> +struct ArgTraits<short> { + typedef ValueLike ValueCategory; +}; + +/** + * chars have value-like semantics. + */ +template<> +struct ArgTraits<char> { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * long longs have value-like semantics. + */ +template<> +struct ArgTraits<long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Unsigned integer types +// ====================================================================== + +/** + * unsigned longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned ints have value-like semantics. + */ +template<> +struct ArgTraits<unsigned int> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned shorts have value-like semantics. + */ +template<> +struct ArgTraits<unsigned short> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned chars have value-like semantics. + */ +template<> +struct ArgTraits<unsigned char> { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * unsigned long longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Float types +// ====================================================================== + +/** + * floats have value-like semantics. + */ +template<> +struct ArgTraits<float> { + typedef ValueLike ValueCategory; +}; + +/** + * doubles have value-like semantics. + */ +template<> +struct ArgTraits<double> { + typedef ValueLike ValueCategory; +}; + +// ====================================================================== +// Other types +// ====================================================================== + +/** + * bools have value-like semantics. + */ +template<> +struct ArgTraits<bool> { + typedef ValueLike ValueCategory; +}; + +/** + * wchar_ts have value-like semantics. + */ +/* +template<> +struct ArgTraits<wchar_t> { + typedef ValueLike ValueCategory; +}; +*/ + +/** + * Strings have string like argument traits. + */ +template<> +struct ArgTraits<std::string> { + typedef StringLike ValueCategory; +}; + +template<typename T> +void SetString(T &dst, const std::string &src) +{ + dst = src; +} + +} // namespace + +#endif + diff --git a/src/tclap/.svn/text-base/StdOutput.h.svn-base b/src/tclap/.svn/text-base/StdOutput.h.svn-base new file mode 100755 index 0000000..9ceac0c --- /dev/null +++ b/src/tclap/.svn/text-base/StdOutput.h.svn-base @@ -0,0 +1,298 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StdOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_STDCMDLINEOUTPUT_H +#define TCLAP_STDCMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that isolates any output from the CmdLine object so that it + * may be easily modified. + */ +class StdOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const; + +}; + + +inline void StdOutput::version(CmdLineInterface& _cmd) +{ + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + + std::cout << std::endl << progName << " version: " + << version << std::endl << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface& _cmd ) +{ + std::cout << std::endl << "USAGE: " << std::endl << std::endl; + + _shortUsage( _cmd, std::cout ); + + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage( _cmd, std::cout ); + + std::cout << std::endl; + +} + +inline void StdOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + std::string progName = _cmd.getProgramName(); + + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl << std::endl; + + if ( _cmd.hasHelpAndVersion() ) + { + std::cerr << "Brief USAGE: " << std::endl; + + _shortUsage( _cmd, std::cerr ); + + std::cerr << std::endl << "For complete USAGE and HELP type: " + << std::endl << " " << progName << " --help" + << std::endl << std::endl; + } + else + usage(_cmd); + + throw ExitException(1); +} + +inline void +StdOutput::_shortUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + std::string s = progName + " "; + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + s += " {"; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + s += (*it)->shortID() + "|"; + + s[s.length()-1] = '}'; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + s += " " + (*it)->shortID(); + + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast<int>(progName.length()) + 2; + if ( secondLineOffset > 75/2 ) + secondLineOffset = static_cast<int>(75/2); + + spacePrint( os, s, 75, 3, secondLineOffset ); +} + +inline void +StdOutput::_longUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++ ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + + if ( it+1 != xorList[i].end() ) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + os << std::endl; + } + + os << std::endl; + + spacePrint( os, message, 75, 3, 0 ); +} + +inline void StdOutput::spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const +{ + int len = static_cast<int>(s.length()); + + if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) + { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while ( start < len ) + { + // find the substring length + // int stringLen = std::min<int>( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min<int>( len - start, allowedLen ); + + // trim the length so it doesn't end in middle of a word + if ( stringLen == allowedLen ) + while ( stringLen >= 0 && + s[stringLen+start] != ' ' && + s[stringLen+start] != ',' && + s[stringLen+start] != '|' ) + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if ( stringLen <= 0 ) + stringLen = allowedLen; + + // check for newlines + for ( int i = 0; i < stringLen; i++ ) + if ( s[start+i] == '\n' ) + stringLen = i+1; + + // print the indent + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + + if ( start == 0 ) + { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start,stringLen) << std::endl; + + // so we don't start a line with a space + while ( s[stringLen+start] == ' ' && start < len ) + start++; + + start += stringLen; + } + } + else + { + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + os << s << std::endl; + } +} + +} //namespace TCLAP +#endif diff --git a/src/tclap/.svn/text-base/SwitchArg.h.svn-base b/src/tclap/.svn/text-base/SwitchArg.h.svn-base new file mode 100755 index 0000000..dc4952e --- /dev/null +++ b/src/tclap/.svn/text-base/SwitchArg.h.svn-base @@ -0,0 +1,228 @@ + +/****************************************************************************** + * + * file: SwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_SWITCH_ARG_H +#define TCLAP_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A simple switch argument. If the switch is set on the command line, then + * the getValue method will return the opposite of the default value for the + * switch. + */ +class SwitchArg : public Arg +{ + protected: + + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + + public: + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool def = false, + Visitor* v = NULL); + + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool def = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string& combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN SwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default( default_val ) +{ } + +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default(default_val) +{ + parser.add( this ); +} + +inline bool SwitchArg::getValue() { return _value; } + +inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) +{ + // make sure this is actually a combined switch + if ( combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0] ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == + Arg::nameStartString() ) + return false; + + // make sure the delimiter isn't in the string + if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( _flag.length() > 0 && + combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + //combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; +} + + +inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] ) || combinedSwitchesMatch( args[*i] ) ) + { + // If we match on a combined switch, then we want to return false + // so that other switches in the combination will also have a + // chance to match. + bool ret = false; + if ( argMatches( args[*i] ) ) + ret = true; + + if ( _alreadySet || ( !ret && combinedSwitchesMatch( args[*i] ) ) ) + throw(CmdLineParseException("Argument already set!", toString())); + + _alreadySet = true; + + if ( _value == true ) + _value = false; + else + _value = true; + + _checkWithVisitor(); + + return ret; + } + else + return false; +} + +inline void SwitchArg::reset() +{ + Arg::reset(); + _value = _default; +} +////////////////////////////////////////////////////////////////////// +//End SwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/UnlabeledMultiArg.h.svn-base b/src/tclap/.svn/text-base/UnlabeledMultiArg.h.svn-base new file mode 100755 index 0000000..d5e1781 --- /dev/null +++ b/src/tclap/.svn/text-base/UnlabeledMultiArg.h.svn-base @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H +#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/MultiArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + +namespace TCLAP { + +/** + * Just like a MultiArg, except that the arguments are unlabeled. Basically, + * this Arg will slurp up everything that hasn't been matched to another + * Arg. + */ +template<class T> +class UnlabeledMultiArg : public MultiArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg<T>::_ignoreable; + using MultiArg<T>::_hasBlanks; + using MultiArg<T>::_extractValue; + using MultiArg<T>::_typeDesc; + using MultiArg<T>::_name; + using MultiArg<T>::_description; + using MultiArg<T>::_alreadySet; + using MultiArg<T>::toString; + + public: + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; +}; + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled multi arg + + + // always take the first value, regardless of the start string + _extractValue( args[(*i)] ); + + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + + return true; +} + +template<class T> +std::string UnlabeledMultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; +} + +template<class T> +std::string UnlabeledMultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; +} + +template<class T> +bool UnlabeledMultiArg<T>::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledMultiArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} + +#endif diff --git a/src/tclap/.svn/text-base/UnlabeledValueArg.h.svn-base b/src/tclap/.svn/text-base/UnlabeledValueArg.h.svn-base new file mode 100755 index 0000000..5721d61 --- /dev/null +++ b/src/tclap/.svn/text-base/UnlabeledValueArg.h.svn-base @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H +#define TCLAP_UNLABELED_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/ValueArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template<class T> +class UnlabeledValueArg : public ValueArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg<T>::_ignoreable; + using ValueArg<T>::_hasBlanks; + using ValueArg<T>::_extractValue; + using ValueArg<T>::_typeDesc; + using ValueArg<T>::_name; + using ValueArg<T>::_description; + using ValueArg<T>::_alreadySet; + using ValueArg<T>::toString; + + public: + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + +}; + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); + +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Implementation of processArg(). + */ +template<class T> +bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _alreadySet ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled arg + + _extractValue( args[*i] ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding longID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding operator== for specific behavior. + */ +template<class T> +bool UnlabeledValueArg<T>::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledValueArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} +#endif diff --git a/src/tclap/.svn/text-base/ValueArg.h.svn-base b/src/tclap/.svn/text-base/ValueArg.h.svn-base new file mode 100755 index 0000000..28117f6 --- /dev/null +++ b/src/tclap/.svn/text-base/ValueArg.h.svn-base @@ -0,0 +1,411 @@ +/****************************************************************************** + * + * file: ValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VALUE_ARGUMENT_H +#define TCLAP_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { + +/** + * The basic labeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when the flag/name is matched + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. + */ +template<class T> +class ValueArg : public Arg +{ + protected: + + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue( const std::string& val ); + + public: + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + Visitor* v = NULL); + + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the value of the argument. + */ + T& getValue() ; + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val = "val") const; + + virtual void reset() ; + +}; + + +/** + * Constructor implementation. + */ +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ + parser.add( this ); +} + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ + parser.add( this ); +} + + +/** + * Implementation of getValue(). + */ +template<class T> +T& ValueArg<T>::getValue() { return _value; } + +/** + * Implementation of processArg(). + */ +template<class T> +bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( _alreadySet ) + throw( CmdLineParseException("Argument already set!", toString()) ); + + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } + else + return false; +} + +/** + * Implementation of shortID. + */ +template<class T> +std::string ValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template<class T> +std::string ValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID( _typeDesc ); +} + +template<class T> +void ValueArg<T>::_extractValue( const std::string& val ) +{ + try { + ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory()); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _value ) ) + throw( CmdLineParseException( "Value '" + val + + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +void ValueArg<T>::reset() +{ + Arg::reset(); + _value = _default; +} + +} // namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/ValuesConstraint.h.svn-base b/src/tclap/.svn/text-base/ValuesConstraint.h.svn-base new file mode 100755 index 0000000..235939c --- /dev/null +++ b/src/tclap/.svn/text-base/ValuesConstraint.h.svn-base @@ -0,0 +1,147 @@ + + +/****************************************************************************** + * + * file: ValuesConstraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_VALUESCONSTRAINT_H +#define TCLAP_VALUESCONSTRAINT_H + +#include <string> +#include <vector> +#include <tclap/Constraint.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#if defined(HAVE_SSTREAM) +#include <sstream> +#elif defined(HAVE_STRSTREAM) +#include <strstream> +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +namespace TCLAP { + +/** + * A Constraint that constrains the Arg to only those values specified + * in the constraint. + */ +template<class T> +class ValuesConstraint : public Constraint<T> +{ + + public: + + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector<T>& allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const; + + protected: + + /** + * The list of valid values. + */ + std::vector<T> _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; + +}; + +template<class T> +ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed) +: _allowed(allowed) +{ + for ( unsigned int i = 0; i < _allowed.size(); i++ ) + { + +#if defined(HAVE_SSTREAM) + std::ostringstream os; +#elif defined(HAVE_STRSTREAM) + std::ostrstream os; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + + os << _allowed[i]; + + std::string temp( os.str() ); + + if ( i > 0 ) + _typeDesc += "|"; + _typeDesc += temp; + } +} + +template<class T> +bool ValuesConstraint<T>::check( const T& val ) const +{ + if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) + return false; + else + return true; +} + +template<class T> +std::string ValuesConstraint<T>::shortID() const +{ + return _typeDesc; +} + +template<class T> +std::string ValuesConstraint<T>::description() const +{ + return _typeDesc; +} + + +} //namespace TCLAP +#endif + diff --git a/src/tclap/.svn/text-base/VersionVisitor.h.svn-base b/src/tclap/.svn/text-base/VersionVisitor.h.svn-base new file mode 100755 index 0000000..3e55921 --- /dev/null +++ b/src/tclap/.svn/text-base/VersionVisitor.h.svn-base @@ -0,0 +1,74 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: VersionVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VERSION_VISITOR_H +#define TCLAP_VERSION_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Vistor that will call the version method of the given CmdLineOutput + * for the specified CmdLine object and then exit. + */ +class VersionVisitor: public Visitor +{ + protected: + + /** + * The CmdLine of interest. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } + +}; + +} + +#endif diff --git a/src/tclap/.svn/text-base/Visitor.h.svn-base b/src/tclap/.svn/text-base/Visitor.h.svn-base new file mode 100755 index 0000000..38ddcbd --- /dev/null +++ b/src/tclap/.svn/text-base/Visitor.h.svn-base @@ -0,0 +1,53 @@ + +/****************************************************************************** + * + * file: Visitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VISITOR_H +#define TCLAP_VISITOR_H + +namespace TCLAP { + +/** + * A base class that defines the interface for visitors. + */ +class Visitor +{ + public: + + /** + * Constructor. Does nothing. + */ + Visitor() { } + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() { } + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() { } +}; + +} + +#endif diff --git a/src/tclap/.svn/text-base/XorHandler.h.svn-base b/src/tclap/.svn/text-base/XorHandler.h.svn-base new file mode 100755 index 0000000..af68943 --- /dev/null +++ b/src/tclap/.svn/text-base/XorHandler.h.svn-base @@ -0,0 +1,156 @@ + +/****************************************************************************** + * + * file: XorHandler.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_XORHANDLER_H +#define TCLAP_XORHANDLER_H + +#include <tclap/Arg.h> +#include <string> +#include <vector> +#include <algorithm> +#include <iostream> + +namespace TCLAP { + +/** + * This class handles lists of Arg's that are to be XOR'd on the command + * line. This is used by CmdLine and you shouldn't ever use it. + */ +class XorHandler +{ + protected: + + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector< std::vector<Arg*> > _orList; + + public: + + /** + * Constructor. Does nothing. + */ + XorHandler( ) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add( std::vector<Arg*>& ors ); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check( const Arg* a ); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream& os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains( const Arg* a ); + + std::vector< std::vector<Arg*> >& getXorList(); + +}; + + +////////////////////////////////////////////////////////////////////// +//BEGIN XOR.cpp +////////////////////////////////////////////////////////////////////// +inline void XorHandler::add( std::vector<Arg*>& ors ) +{ + _orList.push_back( ors ); +} + +inline int XorHandler::check( const Arg* a ) +{ + // iterate over each XOR list + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find( _orList[i].begin(), + _orList[i].end(), a ); + if ( ait != _orList[i].end() ) + { + // go through and set each arg that is not a + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) ) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ( (*ait)->allowMore() ) + return 0; + else + return static_cast<int>(_orList[i].size()); + } + } + + if ( a->isRequired() ) + return 1; + else + return 0; +} + +inline bool XorHandler::contains( const Arg* a ) +{ + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a == (*it) ) + return true; + + return false; +} + +inline std::vector< std::vector<Arg*> >& XorHandler::getXorList() +{ + return _orList; +} + + + +////////////////////////////////////////////////////////////////////// +//END XOR.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/.svn/text-base/ZshCompletionOutput.h.svn-base b/src/tclap/.svn/text-base/ZshCompletionOutput.h.svn-base new file mode 100755 index 0000000..1ed4381 --- /dev/null +++ b/src/tclap/.svn/text-base/ZshCompletionOutput.h.svn-base @@ -0,0 +1,321 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ZshCompletionOutput.h + * + * Copyright (c) 2006, Oliver Kiddle + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H +#define TCLAP_ZSHCOMPLETIONOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <map> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates a Zsh completion function as output from the usage() + * method for the given CmdLine and its Args. + */ +class ZshCompletionOutput : public CmdLineOutput +{ + + public: + + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + void basename( std::string& s ); + void quoteSpecialChars( std::string& s ); + + std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); + void printOption( Arg* it, std::string mutex ); + void printArg( Arg* it ); + + std::map<std::string, std::string> common; + char theDelimiter; +}; + +ZshCompletionOutput::ZshCompletionOutput() +{ + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; +} + +inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl << std::endl << + "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << + "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + { + if ( (*it)->shortID().at(0) == '<' ) + printArg((*it)); + else if ( (*it)->getFlag() != "-" ) + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; +} + +inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; +} + +inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) +{ + size_t idx = s.find_last_of(':'); + while ( idx != std::string::npos ) + { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while ( idx != std::string::npos ) + { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } +} + +inline void ZshCompletionOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void ZshCompletionOutput::printArg(Arg* a) +{ + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if ( a->acceptsMultipleValues() ) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if ( !a->isRequired() ) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map<std::string, std::string>::iterator compArg = common.find(a->getName()); + if ( compArg != common.end() ) + { + std::cout << compArg->second; + } + else + { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; +} + +inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) +{ + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) + { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) + { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') + { + desc.erase(len); + } + if (len) + { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if ( a->getFlag().empty() ) + { + std::cout << name; + } + else + { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if ( theDelimiter == '=' && a->isValueRequired() ) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if ( arg.at(arg.length()-1) == ']' ) + arg.erase(arg.length()-1); + if ( arg.at(arg.length()-1) == ']' ) + { + arg.erase(arg.length()-1); + } + if ( arg.at(0) == '<' ) + { + arg.erase(arg.length()-1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if ( p != std::string::npos ) + { + do + { + arg.replace(p, 1, 1, ' '); + } + while ( (p = arg.find_first_of('|', p)) != std::string::npos ); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } + else + { + std::cout << ':' << arg; + std::map<std::string, std::string>::iterator compArg = common.find(arg); + if ( compArg != common.end() ) + { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; +} + +inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) +{ + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") + { + return "(-)"; + } + + std::ostringstream list; + if ( a->acceptsMultipleValues() ) + { + list << '*'; + } + + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++) + if ( a == (*it) ) + { + list << '('; + for ( ArgVectorIterator iu = xorList[i].begin(); + iu != xorList[i].end(); + iu++ ) + { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if ( iu != xorList[i].begin() && (notCur || hasFlag) ) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if ( notCur || hasFlag ) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' << + a->nameStartString() << a->getName() << ')'; + } + + return list.str(); +} + +} //namespace TCLAP +#endif diff --git a/src/tclap/Arg.h b/src/tclap/Arg.h new file mode 100755 index 0000000..3d44c85 --- /dev/null +++ b/src/tclap/Arg.h @@ -0,0 +1,672 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: Arg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARGUMENT_H +#define TCLAP_ARGUMENT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <cstdio> + +#if defined(HAVE_SSTREAM) +#include <sstream> +typedef std::istringstream istringstream; +#elif defined(HAVE_STRSTREAM) +#include <strstream> +typedef std::istrstream istringstream; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +#include <tclap/ArgException.h> +#include <tclap/Visitor.h> +#include <tclap/CmdLineInterface.h> +#include <tclap/ArgTraits.h> +#include <tclap/StandardTraits.h> + +namespace TCLAP { + +/** + * A virtual base class that defines the essential data for all arguments. + * This class, or one of its existing children, must be subclassed to do + * anything. + */ +class Arg +{ + private: + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool& ignoreRestRef() { static bool ign = false; return ign; } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char& delimiterRef() { static char delim = ' '; return delim; } + + protected: + + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor* _visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v = NULL ); + + public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Currently '-'. + */ + static char flagStartChar() { return '-'; } + + /** + * The sting that indicates the beginning of a flag. Currently "-". + * Should be identical to flagStartChar. + */ + static const std::string flagStartString() { return "-"; } + + /** + * The sting that indicates the beginning of a name. Currently "--". + * Should be flagStartChar twice. + */ + static const std::string nameStartString() { return "--"; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter( char c ) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector<std::string>& args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Returns the argument flag. + */ + const std::string& getFlag() const; + + /** + * Returns the argument name. + */ + const std::string& getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches( const std::string& s ) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID( const std::string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID( const std::string& valueId = "val" ) const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag( std::string& flag, std::string& value ) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks( const std::string& s ) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel( const std::string& s ); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); +}; + +/** + * Typedef of an Arg list iterator. + */ +typedef std::list<Arg*>::iterator ArgListIterator; + +/** + * Typedef of an Arg vector iterator. + */ +typedef std::vector<Arg*>::iterator ArgVectorIterator; + +/** + * Typedef of a Visitor list iterator. + */ +typedef std::list<Visitor*>::iterator VisitorListIterator; + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * ValueLike traits use operator>> to assign the value from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) +{ + static_cast<void>(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while ( is.good() ) { + if ( is.peek() != EOF ) +#ifdef TCLAP_SETBASE_ZERO + is >> std::setbase(0) >> destVal; +#else + is >> destVal; +#endif + else + break; + + valuesRead++; + } + + if ( is.fail() ) + throw( ArgParseException("Couldn't read argument value " + "from string '" + strVal + "'")); + + + if ( valuesRead > 1 ) + throw( ArgParseException("More than one valid value parsed from " + "string '" + strVal + "'")); + +} + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * StringLike uses assignment (operator=) to assign from strVal. + */ +template<typename T> void +ExtractValue(T &destVal, const std::string& strVal, StringLike sl) +{ + static_cast<void>(sl); // Avoid warning about unused sl + SetString(destVal, strVal); +} + +////////////////////////////////////////////////////////////////////// +//BEGIN Arg.cpp +////////////////////////////////////////////////////////////////////// + +inline Arg::Arg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v) : + _flag(flag), + _name(name), + _description(desc), + _required(req), + _requireLabel("required"), + _valueRequired(valreq), + _alreadySet(false), + _visitor( v ), + _ignoreable(true), + _xorSet(false), + _acceptsMultipleValues(false) +{ + if ( _flag.length() > 1 ) + throw(SpecificationException( + "Argument flag can only be one character long", toString() ) ); + + if ( _name != ignoreNameString() && + ( _flag == Arg::flagStartString() || + _flag == Arg::nameStartString() || + _flag == " " ) ) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString() ) ); + + if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || + ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || + ( _name.find( " ", 0 ) != std::string::npos ) ) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString() ) ); + +} + +inline Arg::~Arg() { } + +inline std::string Arg::shortID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +inline std::string Arg::longID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + { + id += Arg::flagStartString() + _flag; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + id += ", "; + } + + id += Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + return id; + +} + +inline bool Arg::operator==(const Arg& a) const +{ + if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) + return true; + else + return false; +} + +inline std::string Arg::getDescription() const +{ + std::string desc = ""; + if ( _required ) + desc = "(" + _requireLabel + ") "; + +// if ( _valueRequired ) +// desc += "(value required) "; + + desc += _description; + return desc; +} + +inline const std::string& Arg::getFlag() const { return _flag; } + +inline const std::string& Arg::getName() const { return _name; } + +inline bool Arg::isRequired() const { return _required; } + +inline bool Arg::isValueRequired() const { return _valueRequired; } + +inline bool Arg::isSet() const +{ + if ( _alreadySet && !_xorSet ) + return true; + else + return false; +} + +inline bool Arg::isIgnoreable() const { return _ignoreable; } + +inline void Arg::setRequireLabel( const std::string& s) +{ + _requireLabel = s; +} + +inline bool Arg::argMatches( const std::string& argFlag ) const +{ + if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || + argFlag == Arg::nameStartString() + _name ) + return true; + else + return false; +} + +inline std::string Arg::toString() const +{ + std::string s = ""; + + if ( _flag != "" ) + s += Arg::flagStartString() + _flag + " "; + + s += "(" + Arg::nameStartString() + _name + ")"; + + return s; +} + +inline void Arg::_checkWithVisitor() const +{ + if ( _visitor != NULL ) + _visitor->visit(); +} + +/** + * Implementation of trimFlag. + */ +inline void Arg::trimFlag(std::string& flag, std::string& value) const +{ + int stop = 0; + for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ ) + if ( flag[i] == Arg::delimiter() ) + { + stop = i; + break; + } + + if ( stop > 1 ) + { + value = flag.substr(stop+1); + flag = flag.substr(0,stop); + } + +} + +/** + * Implementation of _hasBlanks. + */ +inline bool Arg::_hasBlanks( const std::string& s ) const +{ + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] == Arg::blankChar() ) + return true; + + return false; +} + +inline void Arg::forceRequired() +{ + _required = true; +} + +inline void Arg::xorSet() +{ + _alreadySet = true; + _xorSet = true; +} + +/** + * Overridden by Args that need to added to the end of the list. + */ +inline void Arg::addToList( std::list<Arg*>& argList ) const +{ + argList.push_front( const_cast<Arg*>(this) ); +} + +inline bool Arg::allowMore() +{ + return false; +} + +inline bool Arg::acceptsMultipleValues() +{ + return _acceptsMultipleValues; +} + +inline void Arg::reset() +{ + _xorSet = false; + _alreadySet = false; +} + +////////////////////////////////////////////////////////////////////// +//END Arg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif + diff --git a/src/tclap/ArgException.h b/src/tclap/ArgException.h new file mode 100755 index 0000000..3411aa9 --- /dev/null +++ b/src/tclap/ArgException.h @@ -0,0 +1,200 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgException.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARG_EXCEPTION_H +#define TCLAP_ARG_EXCEPTION_H + +#include <string> +#include <exception> + +namespace TCLAP { + +/** + * A simple class that defines and argument exception. Should be caught + * whenever a CmdLine is created and parsed. + */ +class ArgException : public std::exception +{ + public: + + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException( const std::string& text = "undefined exception", + const std::string& id = "undefined", + const std::string& td = "Generic ArgException") + : std::exception(), + _errorText(text), + _argId( id ), + _typeDescription(td) + { } + + /** + * Destructor. + */ + virtual ~ArgException() throw() { } + + /** + * Returns the error text. + */ + std::string error() const { return ( _errorText ); } + + /** + * Returns the argument id. + */ + std::string argId() const + { + if ( _argId == "undefined" ) + return " "; + else + return ( "Argument: " + _argId ); + } + + /** + * Returns the arg id and error text. + */ + const char* what() const throw() + { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const + { + return _typeDescription; + } + + + private: + + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; + +}; + +/** + * Thrown from within the child Arg classes when it fails to properly + * parse the argument it has been passed. + */ +class ArgParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found while parsing " ) + + std::string( "the value the Arg has been passed." )) + { } +}; + +/** + * Thrown from CmdLine when the arguments on the command line are not + * properly specified, e.g. too many arguments, required argument missing, etc. + */ +class CmdLineParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found when the values ") + + std::string( "on the command line do not meet ") + + std::string( "the requirements of the defined ") + + std::string( "Args." )) + { } +}; + +/** + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * same flag as another Arg, same name, etc. + */ +class SpecificationException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string("Exception found when an Arg object ")+ + std::string("is improperly defined by the ") + + std::string("developer." )) + { } + +}; + +class ExitException { +public: + ExitException(int estat) : _estat(estat) {} + + int getExitStatus() const { return _estat; } + +private: + int _estat; +}; + +} // namespace TCLAP + +#endif + diff --git a/src/tclap/ArgTraits.h b/src/tclap/ArgTraits.h new file mode 100755 index 0000000..a89ed12 --- /dev/null +++ b/src/tclap/ArgTraits.h @@ -0,0 +1,81 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_ARGTRAITS_H +#define TCLAP_ARGTRAITS_H + +namespace TCLAP { + +// We use two empty structs to get compile type specialization +// function to work + +/** + * A value like argument value type is a value that can be set using + * operator>>. This is the default value type. + */ +struct ValueLike { + typedef ValueLike ValueCategory; +}; + +/** + * A string like argument value type is a value that can be set using + * operator=(string). Usefull if the value type contains spaces which + * will be broken up into individual tokens by operator>>. + */ +struct StringLike {}; + +/** + * A class can inherit from this object to make it have string like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct StringLikeTrait { + typedef StringLike ValueCategory; +}; + +/** + * A class can inherit from this object to make it have value like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct ValueLikeTrait { + typedef ValueLike ValueCategory; +}; + +/** + * Arg traits are used to get compile type specialization when parsing + * argument values. Using an ArgTraits you can specify the way that + * values gets assigned to any particular type during parsing. The two + * supported types are string like and value like. + */ +template<typename T> +struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + //typedef ValueLike ValueCategory; +}; + +#endif + +} // namespace diff --git a/src/tclap/CmdLine.h b/src/tclap/CmdLine.h new file mode 100755 index 0000000..90d0e65 --- /dev/null +++ b/src/tclap/CmdLine.h @@ -0,0 +1,621 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: CmdLine.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINE_H +#define TCLAP_CMDLINE_H + +#include <tclap/SwitchArg.h> +#include <tclap/MultiSwitchArg.h> +#include <tclap/UnlabeledValueArg.h> +#include <tclap/UnlabeledMultiArg.h> + +#include <tclap/XorHandler.h> +#include <tclap/HelpVisitor.h> +#include <tclap/VersionVisitor.h> +#include <tclap/IgnoreRestVisitor.h> + +#include <tclap/CmdLineOutput.h> +#include <tclap/StdOutput.h> + +#include <tclap/Constraint.h> +#include <tclap/ValuesConstraint.h> + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> +#include <stdlib.h> // Needed for exit(), which isn't defined in some envs. + +namespace TCLAP { + +template<typename T> void DelPtr(T ptr) +{ + delete ptr; +} + +template<typename C> void ClearContainer(C &c) +{ + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr<value_type>); + c.clear(); +} + + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLine : public CmdLineInterface +{ + protected: + + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list<Arg*> _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list<Arg*> _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list<Visitor*> _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput* _output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string& s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg* ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor* ptr); + +private: + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + + public: + + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string& message, + const char delimiter = ' ', + const std::string& version = "none", + bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add( Arg& a ); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add( Arg* a ); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd( Arg& a, Arg& b ); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd( std::vector<Arg*>& xors ); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char * const * argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * + */ + CmdLineOutput* getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput* co); + + /** + * + */ + std::string& getVersion(); + + /** + * + */ + std::string& getProgramName(); + + /** + * + */ + std::list<Arg*>& getArgList(); + + /** + * + */ + XorHandler& getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string& getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); + +}; + + +/////////////////////////////////////////////////////////////////////////////// +//Begin CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + +inline CmdLine::CmdLine(const std::string& m, + char delim, + const std::string& v, + bool help ) +: _progName("not_set_yet"), + _message(m), + _version(v), + _numRequired(0), + _delimiter(delim), + _handleExceptions(true), + _userSetOutput(false), + _helpAndVersion(help) +{ + _constructor(); +} + +inline CmdLine::~CmdLine() +{ + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); + + if ( !_userSetOutput ) { + delete _output; + _output = 0; + } +} + +inline void CmdLine::_constructor() +{ + _output = new StdOutput; + + Arg::setDelimiter( _delimiter ); + + Visitor* v; + + if ( _helpAndVersion ) + { + v = new HelpVisitor( this, &_output ); + SwitchArg* help = new SwitchArg("h","help", + "Displays usage information and exits.", + false, v); + add( help ); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor( this, &_output ); + SwitchArg* vers = new SwitchArg("","version", + "Displays version information and exits.", + false, v); + add( vers ); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), + Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", + false, v); + add( ignore ); + deleteOnExit(ignore); + deleteOnExit(v); +} + +inline void CmdLine::xorAdd( std::vector<Arg*>& ors ) +{ + _xorHandler.add( ors ); + + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) + { + (*it)->forceRequired(); + (*it)->setRequireLabel( "OR required" ); + + add( *it ); + } +} + +inline void CmdLine::xorAdd( Arg& a, Arg& b ) +{ + std::vector<Arg*> ors; + ors.push_back( &a ); + ors.push_back( &b ); + xorAdd( ors ); +} + +inline void CmdLine::add( Arg& a ) +{ + add( &a ); +} + +inline void CmdLine::add( Arg* a ) +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + if ( *a == *(*it) ) + throw( SpecificationException( + "Argument with same flag/name already exists!", + a->longID() ) ); + + a->addToList( _argList ); + + if ( a->isRequired() ) + _numRequired++; +} + + +inline void CmdLine::parse(int argc, const char * const * argv) +{ + // this step is necessary so that we have easy access to + // mutable strings. + std::vector<std::string> args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + + parse(args); +} + +inline void CmdLine::parse(std::vector<std::string>& args) +{ + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) { + bool matched = false; + for (ArgListIterator it = _argList.begin(); + it != _argList.end(); it++) { + if ( (*it)->processArg( &i, args ) ) + { + requiredCount += _xorHandler.check( *it ); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if ( !matched && _emptyCombined( args[i] ) ) + matched = true; + + if ( !matched && !Arg::ignoreRest() ) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if ( requiredCount < _numRequired ) + missingArgsException(); + + if ( requiredCount > _numRequired ) + throw(CmdLineParseException("Too many arguments!")); + + } catch ( ArgException& e ) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + try { + _output->failure(*this,e); + } catch ( ExitException &ee ) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); +} + +inline bool CmdLine::_emptyCombined(const std::string& s) +{ + if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) + return false; + + for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ ) + if ( s[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline void CmdLine::missingArgsException() +{ + int count = 0; + + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + { + if ( (*it)->isRequired() && !(*it)->isSet() ) + { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0,missingArgList.length()-2); + + std::string msg; + if ( count > 1 ) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; + + msg += missingArgList; + + throw(CmdLineParseException(msg)); +} + +inline void CmdLine::deleteOnExit(Arg* ptr) +{ + _argDeleteOnExitList.push_back(ptr); +} + +inline void CmdLine::deleteOnExit(Visitor* ptr) +{ + _visitorDeleteOnExitList.push_back(ptr); +} + +inline CmdLineOutput* CmdLine::getOutput() +{ + return _output; +} + +inline void CmdLine::setOutput(CmdLineOutput* co) +{ + _userSetOutput = true; + _output = co; +} + +inline std::string& CmdLine::getVersion() +{ + return _version; +} + +inline std::string& CmdLine::getProgramName() +{ + return _progName; +} + +inline std::list<Arg*>& CmdLine::getArgList() +{ + return _argList; +} + +inline XorHandler& CmdLine::getXorHandler() +{ + return _xorHandler; +} + +inline char CmdLine::getDelimiter() +{ + return _delimiter; +} + +inline std::string& CmdLine::getMessage() +{ + return _message; +} + +inline bool CmdLine::hasHelpAndVersion() +{ + return _helpAndVersion; +} + +inline void CmdLine::setExceptionHandling(const bool state) +{ + _handleExceptions = state; +} + +inline bool CmdLine::getExceptionHandling() const +{ + return _handleExceptions; +} + +inline void CmdLine::reset() +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + { + (*it)->reset(); + } + + _progName.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +//End CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + + + +} //namespace TCLAP +#endif diff --git a/src/tclap/CmdLineInterface.h b/src/tclap/CmdLineInterface.h new file mode 100755 index 0000000..1b25e9b --- /dev/null +++ b/src/tclap/CmdLineInterface.h @@ -0,0 +1,150 @@ + +/****************************************************************************** + * + * file: CmdLineInterface.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_COMMANDLINE_INTERFACE_H +#define TCLAP_COMMANDLINE_INTERFACE_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + + +namespace TCLAP { + +class Arg; +class CmdLineOutput; +class XorHandler; + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLineInterface +{ + public: + + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add( Arg& a )=0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add( Arg* a )=0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd( Arg& a, Arg& b )=0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd( std::vector<Arg*>& xors )=0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char * const * argv)=0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector<std::string>& args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput* getOutput()=0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput* co)=0; + + /** + * Returns the version string. + */ + virtual std::string& getVersion()=0; + + /** + * Returns the program name string. + */ + virtual std::string& getProgramName()=0; + + /** + * Returns the argList. + */ + virtual std::list<Arg*>& getArgList()=0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler& getXorHandler()=0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter()=0; + + /** + * Returns the message string. + */ + virtual std::string& getMessage()=0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion()=0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset()=0; +}; + +} //namespace + + +#endif diff --git a/src/tclap/CmdLineOutput.h b/src/tclap/CmdLineOutput.h new file mode 100755 index 0000000..71ee5a3 --- /dev/null +++ b/src/tclap/CmdLineOutput.h @@ -0,0 +1,74 @@ + + +/****************************************************************************** + * + * file: CmdLineOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINEOUTPUT_H +#define TCLAP_CMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +class CmdLineInterface; +class ArgException; + +/** + * The interface that any output object must implement. + */ +class CmdLineOutput +{ + + public: + + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} + + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure( CmdLineInterface& c, + ArgException& e )=0; + +}; + +} //namespace TCLAP +#endif diff --git a/src/tclap/Constraint.h b/src/tclap/Constraint.h new file mode 100755 index 0000000..a92acf9 --- /dev/null +++ b/src/tclap/Constraint.h @@ -0,0 +1,68 @@ + +/****************************************************************************** + * + * file: Constraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CONSTRAINT_H +#define TCLAP_CONSTRAINT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <iomanip> +#include <algorithm> + +namespace TCLAP { + +/** + * The interface that defines the interaction between the Arg and Constraint. + */ +template<class T> +class Constraint +{ + + public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const =0; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const =0; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const =0; + + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } +}; + +} //namespace TCLAP +#endif diff --git a/src/tclap/DocBookOutput.h b/src/tclap/DocBookOutput.h new file mode 100755 index 0000000..d2f1290 --- /dev/null +++ b/src/tclap/DocBookOutput.h @@ -0,0 +1,299 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: DocBookOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_DOCBOOKOUTPUT_H +#define TCLAP_DOCBOOKOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates DocBook output for usage() method for the + * given CmdLine and its Args. + */ +class DocBookOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars( std::string& s, char r, std::string& x ); + void removeChar( std::string& s, char r); + void basename( std::string& s ); + + void printShortArg(Arg* it); + void printLongArg(Arg* it); + + char theDelimiter; +}; + + +inline void DocBookOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void DocBookOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "<?xml version='1.0'?>" << std::endl; + std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl; + std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl; + + std::cout << "<refentry>" << std::endl; + + std::cout << "<refmeta>" << std::endl; + std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl; + std::cout << "<manvolnum>1</manvolnum>" << std::endl; + std::cout << "</refmeta>" << std::endl; + + std::cout << "<refnamediv>" << std::endl; + std::cout << "<refname>" << progName << "</refname>" << std::endl; + std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl; + std::cout << "</refnamediv>" << std::endl; + + std::cout << "<refsynopsisdiv>" << std::endl; + std::cout << "<cmdsynopsis>" << std::endl; + + std::cout << "<command>" << progName << "</command>" << std::endl; + + // xor + for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) + { + std::cout << "<group choice='req'>" << std::endl; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + printShortArg((*it)); + + std::cout << "</group>" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + printShortArg((*it)); + + std::cout << "</cmdsynopsis>" << std::endl; + std::cout << "</refsynopsisdiv>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Description</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Options</title>" << std::endl; + + std::cout << "<variablelist>" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "</variablelist>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "<refsect1>" << std::endl; + std::cout << "<title>Version</title>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << version << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</refsect1>" << std::endl; + + std::cout << "</refentry>" << std::endl; + +} + +inline void DocBookOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); +} + +inline void DocBookOutput::substituteSpecialChars( std::string& s, + char r, + std::string& x ) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + s.insert(p,x); + } +} + +inline void DocBookOutput::removeChar( std::string& s, char r) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + } +} + +inline void DocBookOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void DocBookOutput::printShortArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id,'<',lt); + substituteSpecialChars(id,'>',gt); + removeChar(id,'['); + removeChar(id,']'); + + std::string choice = "opt"; + if ( a->isRequired() ) + choice = "plain"; + + std::cout << "<arg choice='" << choice << '\''; + if ( a->acceptsMultipleValues() ) + std::cout << " rep='repeat'"; + + + std::cout << '>'; + if ( !a->getFlag().empty() ) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</arg>" << std::endl; + +} + +inline void DocBookOutput::printLongArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc,'<',lt); + substituteSpecialChars(desc,'>',gt); + + std::cout << "<varlistentry>" << std::endl; + + if ( !a->getFlag().empty() ) + { + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->flagStartChar() << a->getFlag(); + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + } + + std::cout << "<term>" << std::endl; + std::cout << "<option>"; + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "<replaceable>" << arg << "</replaceable>"; + } + std::cout << "</option>" << std::endl; + std::cout << "</term>" << std::endl; + + std::cout << "<listitem>" << std::endl; + std::cout << "<para>" << std::endl; + std::cout << desc << std::endl; + std::cout << "</para>" << std::endl; + std::cout << "</listitem>" << std::endl; + + std::cout << "</varlistentry>" << std::endl; +} + +} //namespace TCLAP +#endif diff --git a/src/tclap/HelpVisitor.h b/src/tclap/HelpVisitor.h new file mode 100755 index 0000000..2cdb997 --- /dev/null +++ b/src/tclap/HelpVisitor.h @@ -0,0 +1,69 @@ + +/****************************************************************************** + * + * file: HelpVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_HELP_VISITOR_H +#define TCLAP_HELP_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Visitor object that calls the usage method of the given CmdLineOutput + * object for the specified CmdLine object. + */ +class HelpVisitor: public Visitor +{ + protected: + + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } + +}; + +} + +#endif diff --git a/src/tclap/IgnoreRestVisitor.h b/src/tclap/IgnoreRestVisitor.h new file mode 100755 index 0000000..e328649 --- /dev/null +++ b/src/tclap/IgnoreRestVisitor.h @@ -0,0 +1,52 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_IGNORE_REST_VISITOR_H +#define TCLAP_IGNORE_REST_VISITOR_H + +#include <tclap/Visitor.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A Vistor that tells the CmdLine to begin ignoring arguments after + * this one is parsed. + */ +class IgnoreRestVisitor: public Visitor +{ + public: + + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/src/tclap/Makefile.am b/src/tclap/Makefile.am new file mode 100755 index 0000000..0e247bf --- /dev/null +++ b/src/tclap/Makefile.am @@ -0,0 +1,28 @@ + +libtclapincludedir = $(includedir)/tclap + +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + diff --git a/src/tclap/Makefile.in b/src/tclap/Makefile.in new file mode 100755 index 0000000..d4b451f --- /dev/null +++ b/src/tclap/Makefile.in @@ -0,0 +1,387 @@ +# Makefile.in generated by automake 1.9.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = include/tclap +DIST_COMMON = $(libtclapinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ac_cxx_have_long_long.m4 \ + $(top_srcdir)/config/ac_cxx_have_sstream.m4 \ + $(top_srcdir)/config/ac_cxx_have_strstream.m4 \ + $(top_srcdir)/config/ac_cxx_namespaces.m4 \ + $(top_srcdir)/config/bb_enable_doxygen.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libtclapincludedir)" +libtclapincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(libtclapinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOC_FALSE = @DOC_FALSE@ +DOC_TRUE = @DOC_TRUE@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +HAVE_GNU_COMPILERS_FALSE = @HAVE_GNU_COMPILERS_FALSE@ +HAVE_GNU_COMPILERS_TRUE = @HAVE_GNU_COMPILERS_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +libtclapincludedir = $(includedir)/tclap +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/tclap/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/tclap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +uninstall-info-am: +install-libtclapincludeHEADERS: $(libtclapinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libtclapincludedir)" || $(mkdir_p) "$(DESTDIR)$(libtclapincludedir)" + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(libtclapincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + $(libtclapincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +uninstall-libtclapincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libtclapincludedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-libtclapincludeHEADERS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libtclapincludeHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + ctags distclean distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-libtclapincludeHEADERS \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am \ + uninstall-libtclapincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/tclap/MultiArg.h b/src/tclap/MultiArg.h new file mode 100755 index 0000000..460e5cb --- /dev/null +++ b/src/tclap/MultiArg.h @@ -0,0 +1,422 @@ +/****************************************************************************** + * + * file: MultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_ARGUMENT_H +#define TCLAP_MULTIPLE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { +/** + * An argument that allows multiple values of type T to be specified. Very + * similar to a ValueArg, except a vector of values will be returned + * instead of just one. + */ +template<class T> +class MultiArg : public Arg +{ +public: + typedef std::vector<T> container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + +protected: + + /** + * The list of values parsed from the CmdLine. + */ + std::vector<T> _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue( const std::string& val ); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; + +public: + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector<T>& getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); + +}; + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +/** + * + */ +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template<class T> +MultiArg<T>::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +template<class T> +const std::vector<T>& MultiArg<T>::getValue() { return _values; } + +template<class T> +bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + // always take the first one, regardless of start string + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } + else + return false; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; +} + +/** + * + */ +template<class T> +std::string MultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; +} + +/** + * Once we've matched the first value, then the arg is no longer + * required. + */ +template<class T> +bool MultiArg<T>::isRequired() const +{ + if ( _required ) + { + if ( _values.size() > 1 ) + return false; + else + return true; + } + else + return false; + +} + +template<class T> +void MultiArg<T>::_extractValue( const std::string& val ) +{ + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory()); + _values.push_back(tmp); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _values.back() ) ) + throw( CmdLineParseException( "Value '" + val + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +bool MultiArg<T>::allowMore() +{ + bool am = _allowMore; + _allowMore = true; + return am; +} + +template<class T> +void MultiArg<T>::reset() +{ + Arg::reset(); + _values.clear(); +} + +} // namespace TCLAP + +#endif diff --git a/src/tclap/MultiSwitchArg.h b/src/tclap/MultiSwitchArg.h new file mode 100755 index 0000000..8820b64 --- /dev/null +++ b/src/tclap/MultiSwitchArg.h @@ -0,0 +1,216 @@ + +/****************************************************************************** +* +* file: MultiSwitchArg.h +* +* Copyright (c) 2003, Michael E. Smoot . +* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. +* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. +* All rights reverved. +* +* See the file COPYING in the top directory of this distribution for +* more information. +* +* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + + +#ifndef TCLAP_MULTI_SWITCH_ARG_H +#define TCLAP_MULTI_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/SwitchArg.h> + +namespace TCLAP { + +/** +* A multiple switch argument. If the switch is set on the command line, then +* the getValue method will return the number of times the switch appears. +*/ +class MultiSwitchArg : public SwitchArg +{ + protected: + + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + + public: + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init = 0, + Visitor* v = NULL); + + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init = 0, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string& val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string& val) const; + + void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ } + +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ + parser.add( this ); +} + +inline int MultiSwitchArg::getValue() { return _value; } + +inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] )) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + _checkWithVisitor(); + + return true; + } + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + // Check for more in argument and increment value. + while ( combinedSwitchesMatch( args[*i] ) ) + ++_value; + + _checkWithVisitor(); + + return false; + } + else + return false; +} + +inline std::string +MultiSwitchArg::shortID(const std::string& val) const +{ + return Arg::shortID(val) + " ... "; +} + +inline std::string +MultiSwitchArg::longID(const std::string& val) const +{ + return Arg::longID(val) + " (accepted multiple times)"; +} + +inline void +MultiSwitchArg::reset() +{ + MultiSwitchArg::_value = MultiSwitchArg::_default; +} + +////////////////////////////////////////////////////////////////////// +//END MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/OptionalUnlabeledTracker.h b/src/tclap/OptionalUnlabeledTracker.h new file mode 100755 index 0000000..8174c5f --- /dev/null +++ b/src/tclap/OptionalUnlabeledTracker.h @@ -0,0 +1,62 @@ + + +/****************************************************************************** + * + * file: OptionalUnlabeledTracker.h + * + * Copyright (c) 2005, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H +#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H + +#include <string> + +namespace TCLAP { + +class OptionalUnlabeledTracker +{ + + public: + + static void check( bool req, const std::string& argName ); + + static void gotOptional() { alreadyOptionalRef() = true; } + + static bool& alreadyOptional() { return alreadyOptionalRef(); } + + private: + + static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +}; + + +inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) +{ + if ( OptionalUnlabeledTracker::alreadyOptional() ) + throw( SpecificationException( + "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", + argName ) ); + + if ( !req ) + OptionalUnlabeledTracker::gotOptional(); +} + + +} // namespace TCLAP + +#endif diff --git a/src/tclap/StandardTraits.h b/src/tclap/StandardTraits.h new file mode 100755 index 0000000..151b851 --- /dev/null +++ b/src/tclap/StandardTraits.h @@ -0,0 +1,186 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StandardTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_STANDARD_TRAITS_H +#define TCLAP_STANDARD_TRAITS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> // To check for long long +#endif + +namespace TCLAP { + +// ====================================================================== +// Integer types +// ====================================================================== + +/** + * longs have value-like semantics. + */ +template<> +struct ArgTraits<long> { + typedef ValueLike ValueCategory; +}; + +/** + * ints have value-like semantics. + */ +template<> +struct ArgTraits<int> { + typedef ValueLike ValueCategory; +}; + +/** + * shorts have value-like semantics. + */ +template<> +struct ArgTraits<short> { + typedef ValueLike ValueCategory; +}; + +/** + * chars have value-like semantics. + */ +template<> +struct ArgTraits<char> { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * long longs have value-like semantics. + */ +template<> +struct ArgTraits<long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Unsigned integer types +// ====================================================================== + +/** + * unsigned longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned ints have value-like semantics. + */ +template<> +struct ArgTraits<unsigned int> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned shorts have value-like semantics. + */ +template<> +struct ArgTraits<unsigned short> { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned chars have value-like semantics. + */ +template<> +struct ArgTraits<unsigned char> { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * unsigned long longs have value-like semantics. + */ +template<> +struct ArgTraits<unsigned long long> { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Float types +// ====================================================================== + +/** + * floats have value-like semantics. + */ +template<> +struct ArgTraits<float> { + typedef ValueLike ValueCategory; +}; + +/** + * doubles have value-like semantics. + */ +template<> +struct ArgTraits<double> { + typedef ValueLike ValueCategory; +}; + +// ====================================================================== +// Other types +// ====================================================================== + +/** + * bools have value-like semantics. + */ +template<> +struct ArgTraits<bool> { + typedef ValueLike ValueCategory; +}; + +/** + * wchar_ts have value-like semantics. + */ +/* +template<> +struct ArgTraits<wchar_t> { + typedef ValueLike ValueCategory; +}; +*/ + +/** + * Strings have string like argument traits. + */ +template<> +struct ArgTraits<std::string> { + typedef StringLike ValueCategory; +}; + +template<typename T> +void SetString(T &dst, const std::string &src) +{ + dst = src; +} + +} // namespace + +#endif + diff --git a/src/tclap/StdOutput.h b/src/tclap/StdOutput.h new file mode 100755 index 0000000..9ceac0c --- /dev/null +++ b/src/tclap/StdOutput.h @@ -0,0 +1,298 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StdOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_STDCMDLINEOUTPUT_H +#define TCLAP_STDCMDLINEOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <algorithm> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that isolates any output from the CmdLine object so that it + * may be easily modified. + */ +class StdOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const; + +}; + + +inline void StdOutput::version(CmdLineInterface& _cmd) +{ + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + + std::cout << std::endl << progName << " version: " + << version << std::endl << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface& _cmd ) +{ + std::cout << std::endl << "USAGE: " << std::endl << std::endl; + + _shortUsage( _cmd, std::cout ); + + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage( _cmd, std::cout ); + + std::cout << std::endl; + +} + +inline void StdOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + std::string progName = _cmd.getProgramName(); + + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl << std::endl; + + if ( _cmd.hasHelpAndVersion() ) + { + std::cerr << "Brief USAGE: " << std::endl; + + _shortUsage( _cmd, std::cerr ); + + std::cerr << std::endl << "For complete USAGE and HELP type: " + << std::endl << " " << progName << " --help" + << std::endl << std::endl; + } + else + usage(_cmd); + + throw ExitException(1); +} + +inline void +StdOutput::_shortUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + std::string s = progName + " "; + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + s += " {"; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + s += (*it)->shortID() + "|"; + + s[s.length()-1] = '}'; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + s += " " + (*it)->shortID(); + + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast<int>(progName.length()) + 2; + if ( secondLineOffset > 75/2 ) + secondLineOffset = static_cast<int>(75/2); + + spacePrint( os, s, 75, 3, secondLineOffset ); +} + +inline void +StdOutput::_longUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + // first the xor + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++ ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + + if ( it+1 != xorList[i].end() ) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + os << std::endl; + } + + os << std::endl; + + spacePrint( os, message, 75, 3, 0 ); +} + +inline void StdOutput::spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const +{ + int len = static_cast<int>(s.length()); + + if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) + { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while ( start < len ) + { + // find the substring length + // int stringLen = std::min<int>( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min<int>( len - start, allowedLen ); + + // trim the length so it doesn't end in middle of a word + if ( stringLen == allowedLen ) + while ( stringLen >= 0 && + s[stringLen+start] != ' ' && + s[stringLen+start] != ',' && + s[stringLen+start] != '|' ) + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if ( stringLen <= 0 ) + stringLen = allowedLen; + + // check for newlines + for ( int i = 0; i < stringLen; i++ ) + if ( s[start+i] == '\n' ) + stringLen = i+1; + + // print the indent + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + + if ( start == 0 ) + { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start,stringLen) << std::endl; + + // so we don't start a line with a space + while ( s[stringLen+start] == ' ' && start < len ) + start++; + + start += stringLen; + } + } + else + { + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + os << s << std::endl; + } +} + +} //namespace TCLAP +#endif diff --git a/src/tclap/SwitchArg.h b/src/tclap/SwitchArg.h new file mode 100755 index 0000000..dc4952e --- /dev/null +++ b/src/tclap/SwitchArg.h @@ -0,0 +1,228 @@ + +/****************************************************************************** + * + * file: SwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_SWITCH_ARG_H +#define TCLAP_SWITCH_ARG_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A simple switch argument. If the switch is set on the command line, then + * the getValue method will return the opposite of the default value for the + * switch. + */ +class SwitchArg : public Arg +{ + protected: + + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + + public: + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool def = false, + Visitor* v = NULL); + + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool def = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string& combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN SwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default( default_val ) +{ } + +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default(default_val) +{ + parser.add( this ); +} + +inline bool SwitchArg::getValue() { return _value; } + +inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) +{ + // make sure this is actually a combined switch + if ( combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0] ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == + Arg::nameStartString() ) + return false; + + // make sure the delimiter isn't in the string + if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( _flag.length() > 0 && + combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + //combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; +} + + +inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] ) || combinedSwitchesMatch( args[*i] ) ) + { + // If we match on a combined switch, then we want to return false + // so that other switches in the combination will also have a + // chance to match. + bool ret = false; + if ( argMatches( args[*i] ) ) + ret = true; + + if ( _alreadySet || ( !ret && combinedSwitchesMatch( args[*i] ) ) ) + throw(CmdLineParseException("Argument already set!", toString())); + + _alreadySet = true; + + if ( _value == true ) + _value = false; + else + _value = true; + + _checkWithVisitor(); + + return ret; + } + else + return false; +} + +inline void SwitchArg::reset() +{ + Arg::reset(); + _value = _default; +} +////////////////////////////////////////////////////////////////////// +//End SwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/UnlabeledMultiArg.h b/src/tclap/UnlabeledMultiArg.h new file mode 100755 index 0000000..d5e1781 --- /dev/null +++ b/src/tclap/UnlabeledMultiArg.h @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H +#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/MultiArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + +namespace TCLAP { + +/** + * Just like a MultiArg, except that the arguments are unlabeled. Basically, + * this Arg will slurp up everything that hasn't been matched to another + * Arg. + */ +template<class T> +class UnlabeledMultiArg : public MultiArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg<T>::_ignoreable; + using MultiArg<T>::_hasBlanks; + using MultiArg<T>::_extractValue; + using MultiArg<T>::_typeDesc; + using MultiArg<T>::_name; + using MultiArg<T>::_description; + using MultiArg<T>::_alreadySet; + using MultiArg<T>::toString; + + public: + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; +}; + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template<class T> +UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg<T>("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template<class T> +bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled multi arg + + + // always take the first value, regardless of the start string + _extractValue( args[(*i)] ); + + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + + return true; +} + +template<class T> +std::string UnlabeledMultiArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; +} + +template<class T> +std::string UnlabeledMultiArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; +} + +template<class T> +bool UnlabeledMultiArg<T>::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledMultiArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} + +#endif diff --git a/src/tclap/UnlabeledValueArg.h b/src/tclap/UnlabeledValueArg.h new file mode 100755 index 0000000..5721d61 --- /dev/null +++ b/src/tclap/UnlabeledValueArg.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H +#define TCLAP_UNLABELED_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/ValueArg.h> +#include <tclap/OptionalUnlabeledTracker.h> + + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template<class T> +class UnlabeledValueArg : public ValueArg<T> +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg<T>::_ignoreable; + using ValueArg<T>::_hasBlanks; + using ValueArg<T>::_extractValue; + using ValueArg<T>::_typeDesc; + using ValueArg<T>::_name; + using ValueArg<T>::_description; + using ValueArg<T>::_alreadySet; + using ValueArg<T>::toString; + + public: + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list<Arg*>& argList ) const; + +}; + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); + +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Constructor implemenation. + */ +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); +} + +template<class T> +UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg<T>("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Implementation of processArg(). + */ +template<class T> +bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + + if ( _alreadySet ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled arg + + _extractValue( args[*i] ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding longID for specific output. + */ +template<class T> +std::string UnlabeledValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding operator== for specific behavior. + */ +template<class T> +bool UnlabeledValueArg<T>::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template<class T> +void UnlabeledValueArg<T>::addToList( std::list<Arg*>& argList ) const +{ + argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) ); +} + +} +#endif diff --git a/src/tclap/ValueArg.h b/src/tclap/ValueArg.h new file mode 100755 index 0000000..28117f6 --- /dev/null +++ b/src/tclap/ValueArg.h @@ -0,0 +1,411 @@ +/****************************************************************************** + * + * file: ValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VALUE_ARGUMENT_H +#define TCLAP_VALUE_ARGUMENT_H + +#include <string> +#include <vector> + +#include <tclap/Arg.h> +#include <tclap/Constraint.h> + +namespace TCLAP { + +/** + * The basic labeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when the flag/name is matched + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. + */ +template<class T> +class ValueArg : public Arg +{ + protected: + + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint<T>* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue( const std::string& val ); + + public: + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + Visitor* v = NULL); + + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint<T>* constraint, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector<std::string>& args); + + /** + * Returns the value of the argument. + */ + T& getValue() ; + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val = "val") const; + + virtual void reset() ; + +}; + + +/** + * Constructor implementation. + */ +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ + parser.add( this ); +} + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ } + +template<class T> +ValueArg<T>::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint<T>* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ + parser.add( this ); +} + + +/** + * Implementation of getValue(). + */ +template<class T> +T& ValueArg<T>::getValue() { return _value; } + +/** + * Implementation of processArg(). + */ +template<class T> +bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( _alreadySet ) + throw( CmdLineParseException("Argument already set!", toString()) ); + + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + if ( value == "" ) + { + (*i)++; + if ( static_cast<unsigned int>(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } + else + return false; +} + +/** + * Implementation of shortID. + */ +template<class T> +std::string ValueArg<T>::shortID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template<class T> +std::string ValueArg<T>::longID(const std::string& val) const +{ + static_cast<void>(val); // Ignore input, don't warn + return Arg::longID( _typeDesc ); +} + +template<class T> +void ValueArg<T>::_extractValue( const std::string& val ) +{ + try { + ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory()); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _value ) ) + throw( CmdLineParseException( "Value '" + val + + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template<class T> +void ValueArg<T>::reset() +{ + Arg::reset(); + _value = _default; +} + +} // namespace TCLAP + +#endif diff --git a/src/tclap/ValuesConstraint.h b/src/tclap/ValuesConstraint.h new file mode 100755 index 0000000..235939c --- /dev/null +++ b/src/tclap/ValuesConstraint.h @@ -0,0 +1,147 @@ + + +/****************************************************************************** + * + * file: ValuesConstraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_VALUESCONSTRAINT_H +#define TCLAP_VALUESCONSTRAINT_H + +#include <string> +#include <vector> +#include <tclap/Constraint.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#else +#define HAVE_SSTREAM +#endif + +#if defined(HAVE_SSTREAM) +#include <sstream> +#elif defined(HAVE_STRSTREAM) +#include <strstream> +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +namespace TCLAP { + +/** + * A Constraint that constrains the Arg to only those values specified + * in the constraint. + */ +template<class T> +class ValuesConstraint : public Constraint<T> +{ + + public: + + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector<T>& allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const; + + protected: + + /** + * The list of valid values. + */ + std::vector<T> _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; + +}; + +template<class T> +ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed) +: _allowed(allowed) +{ + for ( unsigned int i = 0; i < _allowed.size(); i++ ) + { + +#if defined(HAVE_SSTREAM) + std::ostringstream os; +#elif defined(HAVE_STRSTREAM) + std::ostrstream os; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + + os << _allowed[i]; + + std::string temp( os.str() ); + + if ( i > 0 ) + _typeDesc += "|"; + _typeDesc += temp; + } +} + +template<class T> +bool ValuesConstraint<T>::check( const T& val ) const +{ + if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) + return false; + else + return true; +} + +template<class T> +std::string ValuesConstraint<T>::shortID() const +{ + return _typeDesc; +} + +template<class T> +std::string ValuesConstraint<T>::description() const +{ + return _typeDesc; +} + + +} //namespace TCLAP +#endif + diff --git a/src/tclap/VersionVisitor.h b/src/tclap/VersionVisitor.h new file mode 100755 index 0000000..3e55921 --- /dev/null +++ b/src/tclap/VersionVisitor.h @@ -0,0 +1,74 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: VersionVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VERSION_VISITOR_H +#define TCLAP_VERSION_VISITOR_H + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/Visitor.h> + +namespace TCLAP { + +/** + * A Vistor that will call the version method of the given CmdLineOutput + * for the specified CmdLine object and then exit. + */ +class VersionVisitor: public Visitor +{ + protected: + + /** + * The CmdLine of interest. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } + +}; + +} + +#endif diff --git a/src/tclap/Visitor.h b/src/tclap/Visitor.h new file mode 100755 index 0000000..38ddcbd --- /dev/null +++ b/src/tclap/Visitor.h @@ -0,0 +1,53 @@ + +/****************************************************************************** + * + * file: Visitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VISITOR_H +#define TCLAP_VISITOR_H + +namespace TCLAP { + +/** + * A base class that defines the interface for visitors. + */ +class Visitor +{ + public: + + /** + * Constructor. Does nothing. + */ + Visitor() { } + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() { } + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() { } +}; + +} + +#endif diff --git a/src/tclap/XorHandler.h b/src/tclap/XorHandler.h new file mode 100755 index 0000000..af68943 --- /dev/null +++ b/src/tclap/XorHandler.h @@ -0,0 +1,156 @@ + +/****************************************************************************** + * + * file: XorHandler.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_XORHANDLER_H +#define TCLAP_XORHANDLER_H + +#include <tclap/Arg.h> +#include <string> +#include <vector> +#include <algorithm> +#include <iostream> + +namespace TCLAP { + +/** + * This class handles lists of Arg's that are to be XOR'd on the command + * line. This is used by CmdLine and you shouldn't ever use it. + */ +class XorHandler +{ + protected: + + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector< std::vector<Arg*> > _orList; + + public: + + /** + * Constructor. Does nothing. + */ + XorHandler( ) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add( std::vector<Arg*>& ors ); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check( const Arg* a ); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream& os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains( const Arg* a ); + + std::vector< std::vector<Arg*> >& getXorList(); + +}; + + +////////////////////////////////////////////////////////////////////// +//BEGIN XOR.cpp +////////////////////////////////////////////////////////////////////// +inline void XorHandler::add( std::vector<Arg*>& ors ) +{ + _orList.push_back( ors ); +} + +inline int XorHandler::check( const Arg* a ) +{ + // iterate over each XOR list + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find( _orList[i].begin(), + _orList[i].end(), a ); + if ( ait != _orList[i].end() ) + { + // go through and set each arg that is not a + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) ) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ( (*ait)->allowMore() ) + return 0; + else + return static_cast<int>(_orList[i].size()); + } + } + + if ( a->isRequired() ) + return 1; + else + return 0; +} + +inline bool XorHandler::contains( const Arg* a ) +{ + for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ ) + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a == (*it) ) + return true; + + return false; +} + +inline std::vector< std::vector<Arg*> >& XorHandler::getXorList() +{ + return _orList; +} + + + +////////////////////////////////////////////////////////////////////// +//END XOR.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/tclap/ZshCompletionOutput.h b/src/tclap/ZshCompletionOutput.h new file mode 100755 index 0000000..1ed4381 --- /dev/null +++ b/src/tclap/ZshCompletionOutput.h @@ -0,0 +1,321 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ZshCompletionOutput.h + * + * Copyright (c) 2006, Oliver Kiddle + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H +#define TCLAP_ZSHCOMPLETIONOUTPUT_H + +#include <string> +#include <vector> +#include <list> +#include <iostream> +#include <map> + +#include <tclap/CmdLineInterface.h> +#include <tclap/CmdLineOutput.h> +#include <tclap/XorHandler.h> +#include <tclap/Arg.h> + +namespace TCLAP { + +/** + * A class that generates a Zsh completion function as output from the usage() + * method for the given CmdLine and its Args. + */ +class ZshCompletionOutput : public CmdLineOutput +{ + + public: + + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + void basename( std::string& s ); + void quoteSpecialChars( std::string& s ); + + std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); + void printOption( Arg* it, std::string mutex ); + void printArg( Arg* it ); + + std::map<std::string, std::string> common; + char theDelimiter; +}; + +ZshCompletionOutput::ZshCompletionOutput() +{ + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; +} + +inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) +{ + std::list<Arg*> argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string version = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl << std::endl << + "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << + "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + { + if ( (*it)->shortID().at(0) == '<' ) + printArg((*it)); + else if ( (*it)->getFlag() != "-" ) + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; +} + +inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast<void>(_cmd); // unused + std::cout << e.what() << std::endl; +} + +inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) +{ + size_t idx = s.find_last_of(':'); + while ( idx != std::string::npos ) + { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while ( idx != std::string::npos ) + { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } +} + +inline void ZshCompletionOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void ZshCompletionOutput::printArg(Arg* a) +{ + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if ( a->acceptsMultipleValues() ) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if ( !a->isRequired() ) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map<std::string, std::string>::iterator compArg = common.find(a->getName()); + if ( compArg != common.end() ) + { + std::cout << compArg->second; + } + else + { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; +} + +inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) +{ + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) + { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) + { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') + { + desc.erase(len); + } + if (len) + { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if ( a->getFlag().empty() ) + { + std::cout << name; + } + else + { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if ( theDelimiter == '=' && a->isValueRequired() ) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if ( arg.at(arg.length()-1) == ']' ) + arg.erase(arg.length()-1); + if ( arg.at(arg.length()-1) == ']' ) + { + arg.erase(arg.length()-1); + } + if ( arg.at(0) == '<' ) + { + arg.erase(arg.length()-1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if ( p != std::string::npos ) + { + do + { + arg.replace(p, 1, 1, ' '); + } + while ( (p = arg.find_first_of('|', p)) != std::string::npos ); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } + else + { + std::cout << ':' << arg; + std::map<std::string, std::string>::iterator compArg = common.find(arg); + if ( compArg != common.end() ) + { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; +} + +inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) +{ + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") + { + return "(-)"; + } + + std::ostringstream list; + if ( a->acceptsMultipleValues() ) + { + list << '*'; + } + + for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++) + if ( a == (*it) ) + { + list << '('; + for ( ArgVectorIterator iu = xorList[i].begin(); + iu != xorList[i].end(); + iu++ ) + { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if ( iu != xorList[i].begin() && (notCur || hasFlag) ) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if ( notCur || hasFlag ) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' << + a->nameStartString() << a->getName() << ')'; + } + + return list.str(); +} + +} //namespace TCLAP +#endif |
