|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2004 by Christoph Thielecke *
|
|
|
|
* crissi99@gmx.de *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* 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; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
#include "vpntypesinfodialog.h"
|
|
|
|
#include <tdelistview.h>
|
|
|
|
//#include <tqlistviewitem.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqlistview.h>
|
|
|
|
#include <tqheader.h>
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
@author Christoph Thielecke <crissi99@gmx.de>
|
|
|
|
*/
|
|
|
|
class VpnTypesListViewToolTip : public TQToolTip
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VpnTypesListViewToolTip ( TQListView* parent );
|
|
|
|
protected:
|
|
|
|
void maybeTip ( const TQPoint& p );
|
|
|
|
private:
|
|
|
|
TQListView* listView;
|
|
|
|
public:
|
|
|
|
|
|
|
|
};
|
|
|
|
inline VpnTypesListViewToolTip::VpnTypesListViewToolTip ( TQListView* parent ) : TQToolTip ( parent->viewport() ), listView ( parent ) {}
|
|
|
|
inline void VpnTypesListViewToolTip::maybeTip ( const TQPoint& p )
|
|
|
|
{
|
|
|
|
if ( !listView )
|
|
|
|
return;
|
|
|
|
const TQListViewItem* item = listView->itemAt ( p );
|
|
|
|
if ( !item )
|
|
|
|
return;
|
|
|
|
const TQRect itemRect = listView->itemRect ( item );
|
|
|
|
if ( !itemRect.isValid() )
|
|
|
|
return;
|
|
|
|
const int col = listView->header()->sectionAt ( p.x() );
|
|
|
|
const int row = listView->header()->sectionAt ( p.y() );
|
|
|
|
if ( col == -1 && row == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const TQRect headerRect = listView->header()->sectionRect ( col );
|
|
|
|
if ( !headerRect.isValid() )
|
|
|
|
return;
|
|
|
|
// const TQRect cellRect ( headerRect.left(), itemRect.top(),
|
|
|
|
// headerRect.width(), itemRect.height() );
|
|
|
|
const TQRect cellRect ( headerRect.left(), itemRect.top(), 400, 200 );
|
|
|
|
TQString tipStr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQStringList RequirementsList = TQStringList::split( ",",item->text(2));
|
|
|
|
TQString RequirementsString="<ul>";
|
|
|
|
for ( TQStringList::Iterator it = RequirementsList.begin(); it != RequirementsList.end(); ++it )
|
|
|
|
RequirementsString+="<li>"+*it+"</li>";
|
|
|
|
RequirementsString+="</ul>";
|
|
|
|
|
|
|
|
tipStr = TQString ( "<h2>"+item->text ( 0 )+"</h2><ul><li>"+i18n("Requirements:")+" "+RequirementsString+"</li><li>"+i18n("Comment:")+" "+item->text(3)+"</li></ul>");
|
|
|
|
|
|
|
|
tip ( cellRect, tipStr );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VpnTypesInfoDialog::VpnTypesInfoDialog ( KVpncConfig *GlobalConfig, TQWidget *parent, const char * )
|
|
|
|
:KDialogBase ( parent, "Tool_information", true, "",
|
|
|
|
KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )
|
|
|
|
{
|
|
|
|
main = new ToolsInfoWidgetBase(this);
|
|
|
|
setMainWidget(main);
|
|
|
|
main->InfoListView->setMinimumSize(main->InfoListView->sizeHint());
|
|
|
|
main->InfoListView->removeColumn(6);
|
|
|
|
main->InfoListView->removeColumn(5);
|
|
|
|
main->InfoListView->removeColumn(4);
|
|
|
|
|
|
|
|
main->InfoListView->setColumnText(0,i18n("VPN type"));
|
|
|
|
main->InfoListView->setColumnText(1,i18n("State"));
|
|
|
|
main->InfoListView->setColumnText(2,i18n("Requirements"));
|
|
|
|
main->InfoListView->setColumnText(3,i18n("Comment"));
|
|
|
|
|
|
|
|
main->textLabel1->setText(i18n("The following information about the VPN tyes has been collected:"));
|
|
|
|
|
|
|
|
TQPixmap ok_icon = TDEGlobal::iconLoader()->loadIcon( "button_ok", TDEIcon::NoGroup, 16 );
|
|
|
|
TQPixmap wrong_icon = TDEGlobal::iconLoader()->loadIcon( "button_cancel", TDEIcon::NoGroup, 16 );
|
|
|
|
ToolInfo *tool=0;
|
|
|
|
main->InfoListView->setSorting(1);
|
|
|
|
|
|
|
|
VpnTypesInfoList = new TQPtrList<VpnTypeInfo>();
|
|
|
|
VpnTypesInfoList->setAutoDelete( TRUE ); // the list owns the objects
|
|
|
|
|
|
|
|
VpnTypeInfo *it;
|
|
|
|
|
|
|
|
GlobalConfig->appPointer->setOverrideCursor( TQCursor(TQt::WaitCursor) );
|
|
|
|
|
|
|
|
Utils UtilsInstance(GlobalConfig);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "cisco";
|
|
|
|
it->Name= i18n("Cisco VPN");
|
|
|
|
it->Requirements.append("vpnc / vpnclient");
|
|
|
|
|
|
|
|
bool vpnc_found = UtilsInstance.getToolInfo("vpnc")->found;
|
|
|
|
bool vpnclient_found = UtilsInstance.getToolInfo("vpnclient")->found;
|
|
|
|
|
|
|
|
if (vpnc_found || vpnclient_found)
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vpnc_found && !vpnclient_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("no certificate support");
|
|
|
|
}
|
|
|
|
if (vpnc_found && vpnclient_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("certificate support only with vpnclient (original Cisco client)");
|
|
|
|
}
|
|
|
|
if (vpnc_found )
|
|
|
|
{
|
|
|
|
it->Comment+=", "+i18n("hybrid support only if vpnc compiled with OpenSSL support");
|
|
|
|
}
|
|
|
|
|
|
|
|
TQListViewItem *item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "ipsec";
|
|
|
|
it->Name= i18n("IPsec VPN");
|
|
|
|
it->Requirements.append("Openswan / strongSwan / FreeS/Wan / ipsec-tools");
|
|
|
|
|
|
|
|
bool ipsec_found = UtilsInstance.getToolInfo("ipsec")->found;
|
|
|
|
bool racoon_found = UtilsInstance.getToolInfo("racoon")->found;
|
|
|
|
|
|
|
|
|
|
|
|
if (ipsec_found || racoon_found)
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ipsec_found && ( !UtilsInstance.getToolInfo("ipsec")->Version.contains ( "Openswan" ) && !UtilsInstance.getToolInfo("ipsec")->Version.contains ( "strongswan" ) ))
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("FreeS/WAN detected, please upgrade to Openswan/strongSwan");
|
|
|
|
}
|
|
|
|
if (ipsec_found &&UtilsInstance.getToolInfo("ipsec")->Version.contains ( "Openswan" ) )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("Openswan detected, no smartcard support");
|
|
|
|
}
|
|
|
|
if (ipsec_found &&UtilsInstance.getToolInfo("ipsec")->Version.contains ( "strongswan" ) )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 detected").arg(i18n("strongSwan"));
|
|
|
|
}
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "pptp";
|
|
|
|
it->Name= i18n("Microsoft PPTP VPN");
|
|
|
|
it->Requirements.append("pptpclient");
|
|
|
|
it->Requirements.append("pppd");
|
|
|
|
it->Requirements.append(i18n("MPPE extensions in kernel"));
|
|
|
|
bool pptpd_found = UtilsInstance.getToolInfo("pptp")->found;
|
|
|
|
bool pppd_found = UtilsInstance.getToolInfo("pppd")->found;
|
|
|
|
|
|
|
|
Utils::PppdCapabilities pppdcap = UtilsInstance.checkPppdCapabilities();
|
|
|
|
|
|
|
|
if (pppd_found && pptpd_found && (pppdcap.pppdHasMppeRequiredSupport || pppdcap.pppdHasRequireMppeSupport))
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pptpd_found && !pppd_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("pppd");
|
|
|
|
}
|
|
|
|
if (!pptpd_found && pppd_found)
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("pptpclient");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pptpd_found && !pppd_found)
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 are missing").arg(i18n("pptpclient and pppd"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!it->Comment.isEmpty())
|
|
|
|
it->Comment+=", ";
|
|
|
|
if (!pppdcap.pppdHasMppeRequiredSupport && !pppdcap.pppdHasRequireMppeSupport )
|
|
|
|
it->Comment+=i18n("%1 are missing").arg(i18n("MPPE support"));
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "openvpn";
|
|
|
|
it->Name= i18n("OpenVPN SSL-VPN");
|
|
|
|
it->Requirements.append("openvpn");
|
|
|
|
it->Requirements.append("openssl");
|
|
|
|
|
|
|
|
bool openvpn_found = UtilsInstance.getToolInfo("openvpn")->found;
|
|
|
|
bool openssl_found = UtilsInstance.getToolInfo("openvpn")->found;
|
|
|
|
|
|
|
|
if (openvpn_found && openssl_found)
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!openvpn_found && openssl_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("openvpn");
|
|
|
|
}
|
|
|
|
if (openvpn_found && !openssl_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("openssl");
|
|
|
|
}
|
|
|
|
if (!openvpn_found && !openssl_found)
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 are missing").arg(i18n("openvpn and openssl"));
|
|
|
|
}
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "l2tpd_ipsec";
|
|
|
|
it->Name= i18n("L2TP over IPSec");
|
|
|
|
it->Requirements.append("Openswan / strongSwan / FreeS/Wan / ipsec-tools");
|
|
|
|
it->Requirements.append("l2tpd / xl2tpd / openl2tp");
|
|
|
|
|
|
|
|
ipsec_found = UtilsInstance.getToolInfo("ipsec")->found;
|
|
|
|
racoon_found = UtilsInstance.getToolInfo("racoon")->found;
|
|
|
|
bool l2tpd_found = UtilsInstance.getToolInfo("l2tpd")->found;
|
|
|
|
bool xl2tpd_found = UtilsInstance.getToolInfo("xl2tpd")->found;
|
|
|
|
bool openl2tp_found = UtilsInstance.getToolInfo("openl2tpd")->found;
|
|
|
|
|
|
|
|
|
|
|
|
if ((ipsec_found || racoon_found) && (l2tpd_found || xl2tpd_found || openl2tp_found))
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ipsec_found && ( !UtilsInstance.getToolInfo("ipsec")->Version.contains ( "Openswan" ) && !UtilsInstance.getToolInfo("ipsec")->Version.contains ( "strongswan" ) ))
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("FreeS/WAN detected, please upgrade to Openswan/strongSwan");
|
|
|
|
}
|
|
|
|
if (ipsec_found && UtilsInstance.getToolInfo("ipsec")->Version.contains ( "Openswan" ) )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("Openswan detected, no smartcard support");
|
|
|
|
}
|
|
|
|
if (ipsec_found && UtilsInstance.getToolInfo("ipsec")->Version.contains ( "strongswan" ) )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 detected").arg(i18n("strongSwan"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (l2tpd_found)
|
|
|
|
{
|
|
|
|
it->Comment+=", ";
|
|
|
|
it->Comment+=i18n("%1 detected").arg(i18n("l2tpd"));
|
|
|
|
}
|
|
|
|
if (xl2tpd_found)
|
|
|
|
{
|
|
|
|
it->Comment+=", ";
|
|
|
|
it->Comment+=i18n("%1 detected").arg(i18n("xl2tpd"));
|
|
|
|
}
|
|
|
|
if (openl2tp_found)
|
|
|
|
{
|
|
|
|
it->Comment+=", ";
|
|
|
|
it->Comment+=i18n("%1 detected").arg(i18n("openl2tp"));
|
|
|
|
}
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "vtun";
|
|
|
|
it->Name= i18n("Vtun VPN");
|
|
|
|
it->Requirements.append("vtund");
|
|
|
|
it->Requirements.append("pppd");
|
|
|
|
|
|
|
|
bool vtund_found = UtilsInstance.getToolInfo("vtund")->found;
|
|
|
|
pppd_found = UtilsInstance.getToolInfo("pppd")->found;
|
|
|
|
|
|
|
|
if (vtund_found && pppd_found)
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
it->state=i18n("%1 are missing").arg(i18n("some tools"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vtund_found && !pppd_found)
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("pppd");
|
|
|
|
}
|
|
|
|
if (!vtund_found && pppd_found )
|
|
|
|
{
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("vtun");
|
|
|
|
}
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
it = new VpnTypeInfo();
|
|
|
|
it->VpnType = "ssh";
|
|
|
|
it->Name= i18n("SSH VPN");
|
|
|
|
it->Requirements.append("ssh");
|
|
|
|
it->Requirements.append("ksshaskpass / gnome-ssh-askpass");
|
|
|
|
|
|
|
|
bool ssh_found = UtilsInstance.getToolInfo("ssh")->found;
|
|
|
|
bool ksshaskpass_found = UtilsInstance.getToolInfo("ksshaskpass")->found;
|
|
|
|
bool sshaskpassgnome_found = UtilsInstance.getToolInfo("gnome-ssh-askpass")->found;
|
|
|
|
|
|
|
|
if (ssh_found && (ksshaskpass_found || sshaskpassgnome_found))
|
|
|
|
{
|
|
|
|
it->VpnState=true;
|
|
|
|
it->state=i18n("%1 found").arg(i18n("all tools"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
it->VpnState=false;
|
|
|
|
if (!ssh_found && (ksshaskpass_found || sshaskpassgnome_found) )
|
|
|
|
it->Comment+=i18n("%1 is missing").arg("ssh");
|
|
|
|
else
|
|
|
|
it->Comment+=i18n("%1 is missing").arg(i18n("Password entry tool"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
item = new TQListViewItem(main->InfoListView, it->VpnType,it->state, it->Requirements.join(" "+i18n("and")+" "), it->Comment);
|
|
|
|
if (it->VpnState == true)
|
|
|
|
item->setPixmap(1,ok_icon);
|
|
|
|
else
|
|
|
|
item->setPixmap(1,wrong_icon);
|
|
|
|
|
|
|
|
main->InfoListView->insertItem(item);
|
|
|
|
VpnTypesInfoList->append(it);
|
|
|
|
|
|
|
|
main->InfoListView->setResizeMode(TQListView::NoColumn);
|
|
|
|
// main->InfoListView->setColumnWidthMode(0,TQListView::Manual);
|
|
|
|
// main->InfoListView->setColumnWidthMode(1,TQListView::Manual);
|
|
|
|
// main->InfoListView->setColumnWidthMode(2,TQListView::Manual);
|
|
|
|
// main->InfoListView->setColumnWidthMode(3,TQListView::Maximum);
|
|
|
|
// main->InfoListView->setColumnWidthMode(4,TQListView::Maximum);
|
|
|
|
resize(800,600);
|
|
|
|
|
|
|
|
TQToolTip::remove( main->InfoListView );
|
|
|
|
new VpnTypesListViewToolTip( main->InfoListView );
|
|
|
|
|
|
|
|
GlobalConfig->appPointer->restoreOverrideCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VpnTypesInfoDialog::~VpnTypesInfoDialog()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|