File: CDataSourceNamesFileModel.cpp

package info (click to toggle)
unixodbc 2.2.14p2-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 14,628 kB
  • ctags: 12,533
  • sloc: ansic: 104,243; cpp: 38,571; sh: 15,958; makefile: 2,727; sql: 1
file content (266 lines) | stat: -rw-r--r-- 9,710 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*!
 * \file
 *
 * \author  Peter Harvey <pharvey@peterharvey.org>
 * \author  \sa AUTHORS file
 * \version 2
 * \date    2007
 * \license Copyright unixODBC Project 2007-2008, LGPL
 */
#include <odbcinstext.h>

#include <QtGui>

#include "CDataSourceNamesFileModel.h"

#include "CDriverPrompt.h"
#include "CPropertiesDialog.h"

CDataSourceNamesFileModel::CDataSourceNamesFileModel( QObject *pobjectParent )
    : QDirModel( QStringList( "*.dsn" ), QDir::Files, QDir::Name, pobjectParent )
{
}

CDataSourceNamesFileModel::~CDataSourceNamesFileModel()
{
}

/*! 
 * \brief   Adds a file-based Data Source Name to the specified directory.
 * 
 *          Call this method to invoke a process of interacting with the User
 *          to create a new file-based Data Source Name.
 *
 *          This relies upon the selected driver having a viable setup library. By
 *          viable we mean that it implements ODBCINSTGetProperties. 
 *
 * \todo    Need to look at supporting driver setups which provide their own UI for this.
 *          
 * \param   stringDirectory Input. The directory where we want to create the Data Source Name.
 * 
 * \return  bool
 * \retval  true    It was created.
 * \retval  false   Failed to create it (or User simply cancelled).
 *
 */
bool CDataSourceNamesFileModel::addDataSourceName( const QString &stringDirectory )
{
    QString             stringDriverName;
    HODBCINSTPROPERTY   hFirstProperty  = NULL;

    // ask for a driver...
    {
        CDriverPrompt driverprompt;
        if ( !driverprompt.exec() )
            return false;
        stringDriverName = driverprompt.getFriendlyName();
    }

    // get dsn properties from driver setup...
    if ( ODBCINSTConstructProperties( stringDriverName.toAscii().data(), &hFirstProperty ) != ODBCINST_SUCCESS )
    {
        QMessageBox::warning( 0, tr( "ODBC Administrator" ),  QString( "Could not construct a property list for (%1).\nThis is probably because a viable driver setup library could not be found/used.\nYou may want to try configuring the driver to use a generic setup library." ).arg( stringDriverName ) );
        return false;
    }

    // allow properties to be edited...
    {
        CPropertiesDialog propertiesdialog( 0, hFirstProperty );
        propertiesdialog.setWindowTitle( tr( "Data Source Properties (new)" ) );
        if ( !propertiesdialog.exec() )
        {
            ODBCINSTDestructProperties( &hFirstProperty );
            return false;
        }
    }

    // save properties...
    {
        HODBCINSTPROPERTY   hCurProperty            = NULL;
        QString             stringFileNameAndPath   = QString( "%1/%2.dsn" ).arg( stringDirectory ).arg( hFirstProperty->szValue );

        // create the file with a section called "ODBC"...
        if ( !SQLWriteFileDSN( stringFileNameAndPath.toAscii().data(), "ODBC", NULL, NULL ) )
        {
            CODBCInst::showErrors( 0, QString( "Could not write to (%1)" ).arg( stringFileNameAndPath ) );
            ODBCINSTDestructProperties( &hFirstProperty );
            return false;
        }

        // add all of the properties...
        for ( hCurProperty = hFirstProperty->pNext; hCurProperty != NULL; hCurProperty = hCurProperty->pNext )
        {
            if ( !SQLWriteFileDSN( stringFileNameAndPath.toAscii().data(), "ODBC", hCurProperty->szName, hCurProperty->szValue ) )
            {
                CODBCInst::showErrors( 0, QString( "Could not write to (%1)" ).arg( stringFileNameAndPath ) );
                ODBCINSTDestructProperties( &hFirstProperty );
                return false;
            }
        }
    }

    // free memory used by properties...
    ODBCINSTDestructProperties( &hFirstProperty );

    // refresh file(s) display...
    refresh( index( stringDirectory ) );

    return true;
}

/*! 
 * \brief   Edits Data Source Name specified by modelindex.
 * 
 *          Call this method to invoke a process of interacting with the User
 *          to edit an existing file-based Data Source Name.
 *
 *          This relies upon the selected driver having a viable setup library. By
 *          viable we mean that it implements ODBCINSTGetProperties. 
 *
 * \todo    Need to look at supporting driver setups which provide their own UI for this.
 *          
 * \param   modelindex Input. Index to a viable Data Source Name file.
 * 
 * \return  bool
 * \retval  true    Any changes were saved.
 * \retval  false   Failed to edit or save changes (or User simply cancelled).
 *
 */
bool CDataSourceNamesFileModel::editDataSourceName( const QModelIndex &modelindex )
{
    HODBCINSTPROPERTY   hFirstProperty  = NULL;
    char                szDriver[FILENAME_MAX];
    QFileInfo           fileinfo        = fileInfo( modelindex );

    // find out which driver the DSN is using...
    szDriver[0] = '\0';
    if ( !SQLReadFileDSN( fileinfo.absoluteFilePath().toAscii().data(), "ODBC", "DRIVER", szDriver, FILENAME_MAX, NULL ) || strlen( szDriver ) < 1 )
    {
        // the driver is not specified in the DSN file so perhaps we are simply a reference to a regular DSN...
        // \note me thinks this is creative use of the DSN property with limited practical use
        char szDsn[FILENAME_MAX];

        szDsn[0] = '\0';
        if ( SQLReadFileDSN( fileinfo.absoluteFilePath().toAscii().data(), "ODBC", "DSN", szDsn, FILENAME_MAX, NULL ) && strlen( szDsn ) >= 1 )
        {
            UWORD n;
            SQLGetConfigMode( &n ); 
            SQLSetConfigMode( ODBC_BOTH_DSN );
            SQLGetPrivateProfileString( szDsn, "Driver", "", szDriver, sizeof( szDriver ), "odbc.ini" );
            SQLSetConfigMode( n );

            if ( strlen( szDriver ) < 1 )
            {
                CODBCInst::showErrors( 0, tr( "Unable to extract driver from FILE DSN" ) );
                return false;
            }
        }
        else
        {
            CODBCInst::showErrors( 0, tr( "Unable to extract driver from FILE DSN" ) );
            return false;
        }
    }

    // get properties from drivers setup library...
    if ( ODBCINSTConstructProperties( szDriver, &hFirstProperty ) != ODBCINST_SUCCESS )
    {
        CODBCInst::showErrors( 0, QString( "Could not construct a property list for (%1)" ).arg( szDriver ) );
        return false;
    }

    // apply property values from file to properties list...
    {
        // set the name property value...
        ODBCINSTSetProperty( hFirstProperty, "Name", fileinfo.baseName().toAscii().data() );

        // set other property values...
        for ( HODBCINSTPROPERTY hCurProperty = hFirstProperty->pNext; hCurProperty != NULL; hCurProperty = hCurProperty->pNext )
        {
            char szAttr[ 256 ];

            szAttr[ 0 ] = '\0';
            if ( SQLReadFileDSN( fileinfo.absoluteFilePath().toAscii().data(), "ODBC", hCurProperty->szName, szAttr, sizeof( szAttr ), NULL ))
            {
                ODBCINSTSetProperty( hFirstProperty, hCurProperty->szName, szAttr );
            }
        }
    }

    // present properties for editing...
    {
        CPropertiesDialog propertiesdialog( 0, hFirstProperty );
        propertiesdialog.setWindowTitle( "Data Source Properties (edit)" );
        if ( !propertiesdialog.exec() )
        {
            ODBCINSTDestructProperties( &hFirstProperty );
            return false;
        }
    }

    // save changes...
    {
        if ( !SQLWriteFileDSN( fileinfo.absoluteFilePath().toAscii().data(), "ODBC", NULL, NULL ) )
        {
            CODBCInst::showErrors( 0, QString( "Could not write to (%1)" ).arg( fileinfo.absoluteFilePath() ) );
            ODBCINSTDestructProperties( &hFirstProperty );
            return false;
        }
    
        for ( HODBCINSTPROPERTY hCurProperty = hFirstProperty->pNext; hCurProperty != NULL; hCurProperty = hCurProperty->pNext )
        {
            if ( !SQLWriteFileDSN( fileinfo.absoluteFilePath().toAscii().data(), "ODBC", hCurProperty->szName, hCurProperty->szValue ))
            {
                CODBCInst::showErrors( 0, QString( "Could not write to file DSN (%1)" ).arg( fileinfo.absoluteFilePath() ) );
                ODBCINSTDestructProperties( &hFirstProperty );
                return false;
            }
        }
    }

    // free memory used by properties list...
    ODBCINSTDestructProperties( &hFirstProperty );

    // refresh file(s) display in case we have created a new file (if Name was changed)...
    refresh( index( fileinfo.absolutePath() ) );

    return true;
}

/*! 
 * \brief   Deletes Data Source Name specified by modelindex.
 * 
 *          Call this method to permantly remove the Data Source Name file.
 *
 *          This relies upon the selected driver having a viable setup library. By
 *          viable we mean that it implements ODBCINSTGetProperties. 
 *
 * \todo    Need to look at supporting driver setups which provide their own UI for this.
 *          
 * \param   modelindex Input. Index to a viable Data Source Name file.
 * 
 * \return  bool
 * \retval  true    File deleted.
 * \retval  false   Failed delete file - probably a privs issue.
 *
 */
bool CDataSourceNamesFileModel::deleteDataSourceName( const QModelIndex &modelindex )
{
    // \todo we want to refresh with the current root but doing it this way undermines the usefullness of the model
    QString stringRoot = fileInfo( modelindex ).absolutePath();

    // delete the file...
    if ( unlink( filePath( modelindex ).toAscii().data() ) )
    {
        QMessageBox::critical( 0, tr( "ODBC Administrator" ), QString( "Unable to unlink %1" ).arg( filePath( modelindex ) ) );
        return false;
    }

    // refresh file(s) display...
    refresh( index( stringRoot ) );

    return true;
}