00001 #include <qwhatsthis.h>
00002 #include <qstringlist.h>
00003 #include <qtimer.h>
00004 #include <qsqldatabase.h>
00005 #include <qsqlrecord.h>
00006
00007 #include <kapplication.h>
00008 #include <kiconloader.h>
00009 #include <klocale.h>
00010 #include <kdevgenericfactory.h>
00011 #include <kdebug.h>
00012 #include <kaction.h>
00013 #include <kparts/part.h>
00014 #include <kdialogbase.h>
00015 #include <ktexteditor/editinterface.h>
00016 #include <kmessagebox.h>
00017
00018 #include "kdevcore.h"
00019 #include "kdevmainwindow.h"
00020 #include "kdevlanguagesupport.h"
00021 #include "kdevpartcontroller.h"
00022 #include "kdevproject.h"
00023 #include "codemodel.h"
00024
00025 #include "sqlsupport_part.h"
00026 #include "sqlconfigwidget.h"
00027 #include "sqlactions.h"
00028 #include "sqloutputwidget.h"
00029 #include "domutil.h"
00030
00031 typedef KDevGenericFactory<SQLSupportPart> SQLSupportFactory;
00032 static const KAboutData data("kdevsqlsupport", I18N_NOOP("Language"), "1.0");
00033 K_EXPORT_COMPONENT_FACTORY( libkdevsqlsupport, SQLSupportFactory( &data ) )
00034
00035 SQLSupportPart::SQLSupportPart( QObject *parent, const char *name, const QStringList& )
00036 : KDevLanguageSupport ( "KDevPart", "kdevpart", parent, name ? name : "SQLSupportPart" )
00037 {
00038 setInstance( SQLSupportFactory::instance() );
00039 setXMLFile( "kdevsqlsupport.rc" );
00040
00041 KAction *action;
00042 action = new KAction( i18n( "&Run" ), "exec", Key_F9, this, SLOT( slotRun() ), actionCollection(), "build_execute" );
00043 action->setToolTip(i18n("Run"));
00044 action->setWhatsThis(i18n("<b>Run</b><p>Executes a SQL script."));
00045
00046 dbAction = new SqlListAction( this, i18n( "&Database Connections" ), 0, this, SLOT(activeConnectionChanged()), actionCollection(), "connection_combo" );
00047
00048 kdDebug( 9000 ) << "Creating SQLSupportPart" << endl;
00049
00050 connect( core(), SIGNAL( projectConfigWidget( KDialogBase* ) ),
00051 this, SLOT( projectConfigWidget( KDialogBase* ) ) );
00052 connect( core(), SIGNAL(projectOpened()), this, SLOT(projectOpened()) );
00053 connect( core(), SIGNAL(projectClosed()), this, SLOT(projectClosed()) );
00054 connect( core(), SIGNAL(languageChanged()), this, SLOT(projectOpened()) );
00055 connect( partController(), SIGNAL( savedFile( const KURL& ) ), this, SLOT( savedFile( const KURL& ) ) );
00056
00057 m_widget = new SqlOutputWidget();
00058 mainWindow()->embedOutputView( m_widget, "SQL", "Output of SQL commands" );
00059 QWhatsThis::add(m_widget, i18n("<b>Output of SQL commands</b><p>This window shows the output of SQL commands being executed. It can display results of SQL \"select\" commands in a table."));
00060 }
00061
00062
00063 SQLSupportPart::~SQLSupportPart()
00064 {
00065 mainWindow()->removeView(m_widget);
00066 delete m_widget;
00067 }
00068
00069 QString SQLSupportPart::cryptStr(const QString& aStr)
00070 {
00071 QString result;
00072 for (unsigned int i = 0; i < aStr.length(); i++)
00073 result += (aStr[i].unicode() < 0x20) ? aStr[i] :
00074 QChar(0x1001F - aStr[i].unicode());
00075 return result;
00076 }
00077
00078 void SQLSupportPart::activeConnectionChanged()
00079 {
00080 updateCatalog();
00081 }
00082
00083 void SQLSupportPart::clearConfig()
00084 {
00085 for ( QStringList::Iterator it = conNames.begin(); it != conNames.end(); ++it ) {
00086 if ( QSqlDatabase::contains( *it ) ) {
00087 QSqlDatabase::database( *it, false )->close();
00088 QSqlDatabase::removeDatabase( *it );
00089 } else {
00090 kdDebug( 9000 ) << "Could not find connection named " << (*it) << endl;
00091 }
00092 }
00093 conNames.clear();
00094
00095 dbAction->refresh();
00096 }
00097
00098 void SQLSupportPart::loadConfig()
00099 {
00100 clearConfig();
00101
00102 QDomDocument* doc = projectDom();
00103
00104 QStringList db;
00105 int i = 0;
00106 QString conName;
00107 while ( true ) {
00108 QStringList sdb = DomUtil::readListEntry( *doc, "kdevsqlsupport/servers/server" + QString::number( i ), "el" );
00109 if ( (int)sdb.size() < 6 )
00110 break;
00111
00112 conName = "KDEVSQLSUPPORT_";
00113 conName += QString::number( i );
00114 conNames << conName;
00115 QSqlDatabase* db = QSqlDatabase::addDatabase( sdb[0], QString( "KDEVSQLSUPPORT_%1" ).arg( i ) );
00116 db->setDatabaseName( sdb[1] );
00117 db->setHostName( sdb[2] );
00118 bool ok;
00119 int port = sdb[3].toInt( &ok );
00120 if ( ok )
00121 db->setPort( port );
00122 db->setUserName( sdb[4] );
00123 db->setPassword( cryptStr( sdb[5] ) );
00124 db->open();
00125
00126 i++;
00127 }
00128
00129 dbAction->refresh();
00130 }
00131
00132 void SQLSupportPart::projectConfigWidget( KDialogBase *dlg )
00133 {
00134 QVBox *vbox = dlg->addVBoxPage( QString( "SQL" ), i18n( "Specify Your Database Connections" ) );
00135 SqlConfigWidget *w = new SqlConfigWidget( (QWidget*)vbox, "SQL config widget" );
00136 w->setProjectDom( projectDom() );
00137 w->loadConfig();
00138 connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00139 connect( w, SIGNAL(newConfigSaved()), this, SLOT(loadConfig()) );
00140 }
00141
00142 void SQLSupportPart::projectOpened()
00143 {
00144 connect( project(), SIGNAL( addedFilesToProject( const QStringList & ) ),
00145 this, SLOT( addedFilesToProject( const QStringList & ) ) );
00146 connect( project(), SIGNAL( removedFilesFromProject( const QStringList & ) ),
00147 this, SLOT( removedFilesFromProject( const QStringList & ) ) );
00148
00149 loadConfig();
00150
00151
00152
00153 QTimer::singleShot( 0, this, SLOT( parse() ) );
00154 }
00155
00156
00157 void SQLSupportPart::projectClosed()
00158 {
00159 clearConfig();
00160 }
00161
00162 void SQLSupportPart::slotRun ()
00163 {
00164 QString cName = dbAction->currentConnectionName();
00165 if ( cName.isEmpty() ) {
00166 KMessageBox::sorry( 0, i18n("Please select a valid database connection.") );
00167 return;
00168 }
00169
00170 KTextEditor::EditInterface* doc = dynamic_cast<KTextEditor::EditInterface*>(partController()->activePart());
00171 if ( !doc )
00172 return;
00173
00174 mainWindow()->raiseView( m_widget );
00175 m_widget->showQuery( cName, doc->text() );
00176 }
00177
00178 #if 0
00179 static QString dbCaption(const QSqlDatabase* db)
00180 {
00181 QString res;
00182 if (!db)
00183 return res;
00184 res = db->driverName();
00185 res += QString::fromLatin1("@");
00186 res += db->hostName();
00187 if (db->port() >= 0)
00188 res += QString::fromLatin1(":") + QString::number(db->port());
00189 return res;
00190 }
00191 #endif
00192
00193 void SQLSupportPart::parse()
00194 {
00195
00196 }
00197
00198 void SQLSupportPart::updateCatalog()
00199 {
00200 if (!project() || !dbAction)
00201 return;
00202
00203 codeModel()->wipeout();
00204
00205 QString curConnection = dbAction->currentConnectionName();
00206 if (curConnection.isEmpty()) {
00207 emit updatedSourceInfo();
00208 return;
00209 }
00210
00211 FileDom dbf = codeModel()->create<FileModel>();
00212 dbf->setName(dbAction->currentConnectionName());
00213 QSqlDatabase *db = QSqlDatabase::database(dbAction->currentConnectionName(), true);
00214
00215
00216 if (db->isOpen()) {
00217 QSqlRecord inf;
00218 QStringList tables = db->tables();
00219 for (QStringList::Iterator it = tables.begin(); it != tables.end(); ++it) {
00220 ClassDom dbc = codeModel()->create<ClassModel>();
00221 dbc->setName(*it);
00222 inf = db->record(*it);
00223 for (int i = 0; i < (int)inf.count(); ++i) {
00224 FunctionDom dbv = codeModel()->create<FunctionModel>();
00225 dbv->setName(inf.fieldName(i));
00226 dbv->setResultType(QVariant::typeToName(inf.field(i)->type()));
00227 dbc->addFunction(dbv);
00228 }
00229 dbf->addClass(dbc);
00230 }
00231 }
00232
00233 codeModel()->addFile(dbf);
00234
00235 emit updatedSourceInfo();
00236 }
00237
00238 void SQLSupportPart::addedFilesToProject( const QStringList &fileList )
00239 {
00240 QStringList::ConstIterator it;
00241
00242 for ( it = fileList.begin(); it != fileList.end(); ++it ) {
00243
00244 }
00245
00246 emit updatedSourceInfo();
00247 }
00248
00249
00250 void SQLSupportPart::removedFilesFromProject( const QStringList &fileList )
00251 {
00252 QStringList::ConstIterator it;
00253
00254 for ( it = fileList.begin(); it != fileList.end(); ++it ) {
00255
00256 }
00257
00258 emit updatedSourceInfo();
00259 }
00260
00261 void SQLSupportPart::savedFile( const KURL &fileName )
00262 {
00263 if ( project() ->allFiles().contains( fileName.path().mid ( project() ->projectDirectory().length() + 1 ) ) ) {
00264
00265
00266 }
00267 }
00268
00269 KDevLanguageSupport::Features SQLSupportPart::features()
00270 {
00271 return Features( Classes | Functions );
00272 }
00273
00274 KMimeType::List SQLSupportPart::mimeTypes( )
00275 {
00276 KMimeType::List list;
00277 KMimeType::Ptr mime = KMimeType::mimeType( "text/plain" );
00278 if( mime )
00279 list << mime;
00280 return list;
00281 }
00282
00283 #include "sqlsupport_part.moc"