00001 #include <QtCore/QtDebug>
00002 #include <QtCore/QDataStream>
00003 #include <QtCore/QTextStream>
00004 #include <QtCore/QFile>
00005 #include <QtCore/QByteArray>
00006 #include <QtCore/QString>
00007 #include <QtGui/QFileDialog>
00008 #include <QtGui/QMessageBox>
00009
00010 #include "ACE/ContentEditor.h"
00011
00012
00013 ContentEditor::ContentEditor( QWidget* parent, bool binaryContent, bool readOnly, Qt::WindowFlags f ) :
00014 QDialog( parent, f ),
00015 contentBinary( binaryContent ),
00016 contentReadOnly( readOnly ),
00017 defaultContentType( StringCT ),
00018 currentContentType( StringCT ),
00019 defaultContent( QString() ),
00020 currentContent( QString() ),
00021 modified( false )
00022 {
00023 setupUi( this );
00024 setConnections();
00025 prepareEditor( contentBinary, contentReadOnly );
00026 }
00027
00028 ContentEditor::~ContentEditor()
00029 {
00030 done( 0 );
00031 }
00032
00033 void ContentEditor::setConnections()
00034 {
00035 QObject::connect( pushButton_Browse, SIGNAL( clicked() ), this, SLOT( slotBrowse() ) );
00036 QObject::connect( pushButton_Revert, SIGNAL( clicked() ), this, SLOT( slotRevert() ) );
00037 QObject::connect( pushButton_Export, SIGNAL( clicked() ), this, SLOT( slotExport() ) );
00038 QObject::connect( pushButton_Cancel, SIGNAL( clicked() ), this, SLOT( slotRevert() ) );
00039 QObject::connect( comboBox_ContentType, SIGNAL( activated( int ) ), this, SLOT( slotViewContentAs( int ) ) );
00040 }
00041
00042 QVariant ContentEditor::contents() const
00043 {
00044 if ( modified )
00045 {
00046
00047 if ( contentBinary || contentReadOnly )
00048 {
00049 return currentContent;
00050 }
00051
00052
00053 switch ( currentContentType )
00054 {
00055 case StringCT:
00056 return QVariant( textEdit->toPlainText() );
00057 break;
00058
00059 case HexCT:
00060 return QVariant( QString( QByteArray::fromHex( QByteArray().append( textEdit->toPlainText() ) ) ) );
00061 break;
00062 }
00063 }
00064 return currentContent;
00065 }
00066
00067 bool ContentEditor::isBinary() const
00068 {
00069 return contentBinary;
00070 }
00071
00072 bool ContentEditor::isReadOnly() const
00073 {
00074 return contentReadOnly;
00075 }
00076
00077 bool ContentEditor::isModified() const
00078 {
00079 return modified;
00080 }
00081
00082 QTextEdit* ContentEditor::getEditor()
00083 {
00084 return textEdit;
00085 }
00086
00087 void ContentEditor::prepareEditor( bool enableBinary, bool enableReadOnly )
00088 {
00089 contentBinary = enableBinary;
00090 contentReadOnly = enableReadOnly;
00091 if ( contentBinary )
00092 {
00093 defaultContentType = HexCT;
00094 }
00095 textEdit->setReadOnly( contentReadOnly || contentBinary );
00096 textEdit->setTabChangesFocus( contentReadOnly );
00097 textEdit->setUndoRedoEnabled( !contentReadOnly );
00098 pushButton_Browse->setEnabled( !contentReadOnly );
00099 pushButton_Export->setEnabled( contentReadOnly );
00100 if ( contentReadOnly )
00101 {
00102 textEdit->viewport()->setProperty( "cursor", QVariant( QCursor( Qt::ForbiddenCursor ) ) );
00103 setWindowTitle( trUtf8( "Content Viewer" ) );
00104 pushButton_OK->setFocus();
00105 }
00106 else
00107 {
00108 textEdit->viewport()->setProperty( "cursor", QVariant( QCursor( Qt::IBeamCursor ) ) );
00109 if ( !contentBinary )
00110 {
00111 QObject::connect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) );
00112 }
00113 setWindowTitle( trUtf8( "Content Editor" ) );
00114 textEdit->setFocus();
00115 }
00116 }
00117
00118 void ContentEditor::setContent( QVariant content, ContentType cType, bool defaultValue )
00119 {
00120 bool tcConnectionDisabled( false );
00121 pushButton_Revert->setEnabled( true );
00122 if ( content.isNull() )
00123 {
00124 content = defaultContent;
00125 cType = defaultContentType;
00126 modified = false;
00127 pushButton_Revert->setEnabled( false );
00128 tcConnectionDisabled = QObject::disconnect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) );
00129 }
00130 else if ( defaultValue )
00131 {
00132 defaultContent = content;
00133 defaultContentType = cType;
00134 modified = false;
00135 pushButton_Revert->setEnabled( false );
00136 tcConnectionDisabled = QObject::disconnect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) );
00137 }
00138 comboBox_ContentType->setCurrentIndex( cType );
00139 currentContentType = cType;
00140 currentContent = content;
00141 switch ( cType )
00142 {
00143 case StringCT:
00144 if ( content.canConvert( QVariant::String ) )
00145 {
00146 setCursor( Qt::WaitCursor );
00147 setUpdatesEnabled( false );
00148 textEdit->setPlainText( content.toString() );
00149 setUpdatesEnabled( true );
00150 unsetCursor();
00151 modified = true;
00152 }
00153 else
00154 {
00155 QMessageBox::warning(
00156 this,
00157 trUtf8( "Content Editor display error" ),
00158 trUtf8( "Unable to display content as text." ),
00159 QMessageBox::Ok,
00160 QMessageBox::Ok );
00161 }
00162 break;
00163
00164 case HexCT:
00165 if ( content.canConvert( QVariant::ByteArray ) )
00166 {
00167 QString hstr = QString( content.toByteArray().toHex() );
00168 modified = true;
00169 setCursor( Qt::WaitCursor );
00170 setUpdatesEnabled( false );
00171 textEdit->setPlainText( hstr );
00172 setUpdatesEnabled( true );
00173 unsetCursor();
00174 }
00175 else
00176 {
00177 QMessageBox::warning(
00178 this,
00179 trUtf8( "Content Editor display error" ),
00180 trUtf8( "Unable to display content in hexadecimal." ),
00181 QMessageBox::Ok,
00182 QMessageBox::Ok );
00183 }
00184 break;
00185 }
00186 if ( tcConnectionDisabled )
00187 {
00188 QObject::connect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) );
00189 }
00190 }
00191
00192 void ContentEditor::slotBrowse()
00193 {
00194 browsedFileName = QFileDialog::getOpenFileName( this, trUtf8( "Select file" ) );
00195 if ( browsedFileName.isNull() )
00196 return;
00197 QFile binFile( browsedFileName );
00198 if ( !binFile.open( QIODevice::ReadOnly ) )
00199 {
00200 QMessageBox::critical(
00201 this,
00202 trUtf8( "File IO error!" ),
00203 trUtf8( "There was a problem reading the requested file!" ),
00204 QMessageBox::Ok,
00205 QMessageBox::Ok );
00206 return;
00207 }
00208 QDataStream ds( &binFile );
00209 QByteArray binContent = QByteArray();
00210 binContent.resize( binFile.size() );
00211 ds.readRawData( binContent.data(), binFile.size() );
00212
00213 if ( contentBinary )
00214 setContent( QVariant( binContent ), HexCT, defaultContent.isNull() );
00215 else
00216 setContent( QVariant( binContent ), StringCT, defaultContent.isNull() );
00217 ds.unsetDevice();
00218 binFile.close();
00219 }
00220
00221 void ContentEditor::slotExport()
00222 {
00223 QString fileName = QString();
00224 if ( contentBinary )
00225 {
00226 fileName = QFileDialog::getSaveFileName( this, trUtf8( "Export binary content to file" ) );
00227 }
00228 else
00229 {
00230 fileName = QFileDialog::getSaveFileName( this, trUtf8( "Export string content to file" ) );
00231 }
00232 if ( fileName.isNull() )
00233 return;
00234 QFile exportFile( fileName );
00235 if ( !exportFile.open( QIODevice::WriteOnly ) )
00236 {
00237 QMessageBox::critical(
00238 this,
00239 trUtf8( "File IO error!" ),
00240 trUtf8( "There was a problem writing to the selected file!" ),
00241 QMessageBox::Ok,
00242 QMessageBox::Ok );
00243 return;
00244 }
00245 QDataStream ds( &exportFile );
00246 QByteArray tempBA = contents().toByteArray();
00247 if ( ds.writeRawData( tempBA.constData(), tempBA.size() ) == -1 )
00248 {
00249 QMessageBox::critical(
00250 this,
00251 trUtf8( "File IO error!" ),
00252 trUtf8( "There was a problem writing to the selected file!" ),
00253 QMessageBox::Ok,
00254 QMessageBox::Ok );
00255 }
00256 ds.unsetDevice();
00257 exportFile.close();
00258 }
00259
00260 void ContentEditor::slotRevert()
00261 {
00262 setContent();
00263 }
00264
00265 void ContentEditor::slotViewContentAs( int cType )
00266 {
00267
00268 bool disconnectSuccess( QObject::disconnect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) ) );
00269 setContent( contents(), static_cast<ContentType>( cType ), false );
00270 if ( disconnectSuccess )
00271 QObject::connect( textEdit, SIGNAL( textChanged() ), this, SLOT( slotTextChanged() ) );
00272 }
00273
00274 void ContentEditor::slotTextChanged()
00275 {
00276 modified = !contentReadOnly;
00277 pushButton_Revert->setEnabled( modified );
00278 }
00279