|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 | Next > |
|
|
BLOB-Editor as DialogHello Flamerobin-Team,
last days i had luck in building flamerobin on my windows-machine. So i tryed to implement a basic BLOB-Editor-Dialog with success. At the moment it is a really basic implementation. (see screenshot.) Only opening (as Text), cancel and save works. It would be great if you can include the Blob-Dialog into FR-codebase. If so, i will go on and implement some options. I think it would be good to add a new treenode to the configuration-dialog (view - preferences). .... |-DataGrid |-BlobDialog (new) .... The Configuration-Page could look like: EDITOR MODE (BINARY/TEXT/RTF/(BITMAP?)) (x) ALWAYS OPEN AS BINARY (x) DATATYPE DETECTION AND ASSOCIATION [x] TEXT [DETECT | BLOB SUB-TYPE ....] [x] RTF (Windows Only) [DETECT | BLOB SUB-TYPE ....] ([x] BITMAPS ?) [DETECT | BLOB SUB-TYPE ....] ([x] JPEG ?) [DETECT | BLOB SUB-TYPE ....] (if nothing above is detected BINARY-EDITOR will be opend) LOAD OPTION (x) INITIALLY LOAD [....X] kb (x) ALWAYS LOAD ALL BLOB DATA PLUGIN OPTION [x] BLOB-EditorPlugin [plugin.BlobEditor] (located in same path as binary.) < next options are only available if BLOB-EditorPlugin is checked > [x] DETECT BLOB-DATA-Type by Plugin Please comment. Thank You. andy ------------------------------------------------------------------------------ The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your production scanning environment may not be a perfect world - but thanks to Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700 Series Scanner you'll get full speed at 300 dpi even with all image processing features enabled. http://p.sf.net/sfu/kodak-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogOn Thu, May 14, 2009 at 9:30 PM, Andreas Maier <andy1.m@...> wrote:
> Hello Flamerobin-Team, Hi Andreas, first of all - Welcome! > last days i had luck in building flamerobin on my windows-machine. > So i tryed to implement a basic BLOB-Editor-Dialog with success. > At the moment it is a really basic implementation. (see screenshot.) > Only opening (as Text), cancel and save works. I like what you started. I don't know if you read our old disussion about this dialog, but I'll write main ideas here: Dialog should have a wxNotebook control with 4 tabs: - text view (wxTextCtrl) - binary view (hexadecimal, using wxStyledTextCtrl in a read-only mode) - image view (for jpg, png, gif, bmp, etc. images, wxPanel with custom OnPaint handler) - HTML view (wxHTML) The idea is also the add more options with a plugin system, but let's leave that for later. As you wrote, we could add a 5-th, Windows-only tab for RTF format. > It would be great if you can include the Blob-Dialog into FR-codebase. If > so, i will go on and implement some options. Of course, but it would be nice to see the code first, to see what's the "qualily" as I would like to allow you to commit it yourself to repository. I assume you handle Subversion well? Anyway, on to the details: I don't think any of these is necessary... > The Configuration-Page could look like: > EDITOR MODE (BINARY/TEXT/RTF/(BITMAP?)) > (x) ALWAYS OPEN AS BINARY Solved by notebook tabs. > (x) DATATYPE DETECTION AND ASSOCIATION > [x] TEXT [DETECT | BLOB SUB-TYPE ....] > [x] RTF (Windows Only) [DETECT | BLOB SUB-TYPE ....] > ([x] BITMAPS ?) [DETECT | BLOB SUB-TYPE ....] > ([x] JPEG ?) [DETECT | BLOB SUB-TYPE ....] The detection is fast anyway so it would always be on. We can also use the blob sub_type information: 0 - binary, 1 - text. > LOAD OPTION > (x) INITIALLY LOAD [....X] kb > (x) ALWAYS LOAD ALL BLOB DATA These we already have for grid, but maybe they need to be separated. We have to think about this one. > PLUGIN OPTION > [x] BLOB-EditorPlugin [plugin.BlobEditor] > (located in same path as binary.) > < next options are only available if BLOB-EditorPlugin is checked > > [x] DETECT BLOB-DATA-Type by Plugin I do not think this should be handled by plugins, at least for basic types. We already have options to load/save blob data to disk, so special file types like images can be edited in specialized tools (ex. Photoshop, Gimp) and saved back to database. Those tools are much better than any plugin we or other FR users could create. For text we would have an editable text box and a Save button (just like in your screenshot). That would also be used to edit HTML (user would edit the raw HTML in "text" tab, and then switch to HTML tab to see the result. For binary, maybe we could use some hex editor. There's MadEdit and wxHexEditor for example: http://wxhexeditor.sourceforge.net/ http://madedit.sourceforge.net/wiki/index.php/Main_Page but GPL license could be a problem. If we don't find something better, maybe we could talk to the authors. -- Milan Babuskov http://www.flamerobin.org ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogMilan Babuskov wrote:
> Of course, but it would be nice to see the code first, to see what's > the "qualily" as I would like to allow you to commit it yourself to > repository. I assume you handle Subversion well? Maybe Andreas could create a patch against SVN trunk and add it to the SF tracker first, before he gets commit access? Thanks -- Michael Hieke ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogHi Andreas,
Andreas Maier wrote: > It would be great if you can include the Blob-Dialog into FR-codebase. > Please comment. It's great that you started this. For the dialog to be included in FR it would need some changes though. In its current form it does not comply with any of the FR target platform's rules for size and positions of controls in dialogs. Maybe you could take the MultilineEnterDialog as an example for how to do it, it is quite similar to your blob editor dialog. Thanks -- Michael Hieke ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogOn Fri, May 15, 2009 at 9:01 AM, Michael Hieke <mghie@...> wrote:
>> Of course, but it would be nice to see the code first, to see what's >> the "qualily" as I would like to allow you to commit it yourself to >> repository. I assume you handle Subversion well? > > Maybe Andreas could create a patch against SVN trunk and add it to the > SF tracker first, before he gets commit access? Of course. One way or the other, we have to see the code first. -- Milan Babuskov http://www.flamerobin.org ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogHi Milan,
Thank you for all response. I will create a patch against SVN trunk an post it. On this weekend i'm not at home. So i will create the patch next monday or Tuesday. I would prefer to post you first a patch an wait for your comment. Milan Babuskov schrieb: > I like what you started. I don't know if you read our old disussion > about this dialog, but I'll write main ideas here: > > Dialog should have a wxNotebook control with 4 tabs: > > - text view (wxTextCtrl) > - binary view (hexadecimal, using wxStyledTextCtrl in a read-only mode) > - image view (for jpg, png, gif, bmp, etc. images, wxPanel with custom > OnPaint handler) > - HTML view (wxHTML) > > The idea is also the add more options with a plugin system, but let's > leave that for later. As you wrote, we could add a 5-th, Windows-only > tab for RTF format. > >> It would be great if you can include the Blob-Dialog into FR-codebase. If >> so, i will go on and implement some options. >> > Of course, but it would be nice to see the code first, to see what's > the "qualily" as I would like to allow you to commit it yourself to > repository. I assume you handle Subversion well? > > Anyway, on to the details: > > I don't think any of these is necessary... > >> The Configuration-Page could look like: >> EDITOR MODE (BINARY/TEXT/RTF/(BITMAP?)) >> (x) ALWAYS OPEN AS BINARY >> > > Solved by notebook tabs. > Yes. >> (x) DATATYPE DETECTION AND ASSOCIATION >> [x] TEXT [DETECT | BLOB SUB-TYPE ....] >> [x] RTF (Windows Only) [DETECT | BLOB SUB-TYPE ....] >> ([x] BITMAPS ?) [DETECT | BLOB SUB-TYPE ....] >> ([x] JPEG ?) [DETECT | BLOB SUB-TYPE ....] >> > > The detection is fast anyway so it would always be on. We can also use > the blob sub_type information: 0 - binary, 1 - text. > > >> LOAD OPTION >> (x) INITIALLY LOAD [....X] kb >> (x) ALWAYS LOAD ALL BLOB DATA >> > > These we already have for grid, but maybe they need to be separated. > We have to think about this one. > Yes. > >> PLUGIN OPTION >> [x] BLOB-EditorPlugin [plugin.BlobEditor] >> (located in same path as binary.) >> < next options are only available if BLOB-EditorPlugin is checked > >> [x] DETECT BLOB-DATA-Type by Plugin >> > > I do not think this should be handled by plugins, at least for basic > types. We already have options to load/save blob data to disk, so > special file types like images can be edited in specialized tools (ex. > Photoshop, Gimp) and saved back to database. Those tools are much > better than any plugin we or other FR users could create. > > For text we would have an editable text box and a Save button (just > like in your screenshot). That would also be used to edit HTML (user > would edit the raw HTML in "text" tab, and then switch to HTML tab to > see the result. > > For binary, maybe we could use some hex editor. There's MadEdit and > wxHexEditor for example: > > http://wxhexeditor.sourceforge.net/ > http://madedit.sourceforge.net/wiki/index.php/Main_Page > > but GPL license could be a problem. If we don't find something better, > maybe we could talk to the authors. Thank you, i will have a look at it. Andy ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogHi Michael,
Michael Hieke schrieb: > It's great that you started this. For the dialog to be included in FR > it would need some changes though. In its current form it does not > comply with any of the FR target platform's rules for size and positions > of controls in dialogs. Maybe you could take the MultilineEnterDialog > as an example for how to do it, it is quite similar to your blob editor > dialog. > Yes ... it was a quick try. I doesnt care about the Dialog-Style. I will have a look into MultilineEnterDialog and change it. Thank You. Andy ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogHi,
i took a look into MultilineEnterDialog and made changes to EditBlobDialog. I think it now catches FR platform-rules. Here is my first patch now ;-). hope it is okay. It includes a BLOB-Editor with the ability to edit text. WxNotebook and other things (Binary, wxHtml, etc.) will follow. At the moment it doesnt care of read-only-transactions and read-only-blobs. I will correct this later. Over weekend i have no intenet-access. So i cant answer before monday. Andy > Hi Michael, > > Michael Hieke schrieb: > >> It's great that you started this. For the dialog to be included in FR >> it would need some changes though. In its current form it does not >> comply with any of the FR target platform's rules for size and positions >> of controls in dialogs. Maybe you could take the MultilineEnterDialog >> as an example for how to do it, it is quite similar to your blob editor >> dialog. >> >> > Yes ... it was a quick try. I doesnt care about the Dialog-Style. I will > have a look into MultilineEnterDialog and change it. > Thank You. > > Andy > Index: gui/CommandIds.h =================================================================== --- gui/CommandIds.h (revision 1852) +++ gui/CommandIds.h (working copy) @@ -62,6 +62,8 @@ DataGrid_Delete_row, DataGrid_FetchAll, DataGrid_CancelFetchAll, + + DataGrid_EditBlob, DataGrid_ExportBlob, DataGrid_ImportBlob, DataGrid_Copy_as_insert, Index: gui/controls/DataGrid.cpp =================================================================== --- gui/controls/DataGrid.cpp (revision 1852) +++ gui/controls/DataGrid.cpp (working copy) @@ -210,6 +210,7 @@ m.Append(Cmds::DataGrid_Save_as_csv, _("Save as CSV file...")); m.AppendSeparator(); + m.Append(Cmds::DataGrid_EditBlob, _("Edit BLOB...")); m.Append(Cmds::DataGrid_ImportBlob, _("Import BLOB from file...")); m.Append(Cmds::DataGrid_ExportBlob, _("Save BLOB to file...")); m.AppendSeparator(); Index: gui/controls/DataGridRows.cpp =================================================================== --- gui/controls/DataGridRows.cpp (revision 1852) +++ gui/controls/DataGridRows.cpp (working copy) @@ -1949,16 +1949,66 @@ return (0 != dynamic_cast<BlobColumnDef *>(columnDefsM[col])); } //----------------------------------------------------------------------------- +IBPP::Blob* DataGridRows::getBlob(unsigned row, unsigned col) +{ + if ((row < 0) || (row >= buffersM.size())) + throw FRError(_("Invalid row index.")); + if ((col < 0) || (col >= columnDefsM.size())) + throw FRError(_("Invalid col index.")); + IBPP::Blob* b0 = buffersM[row]->getBlob(columnDefsM[col]->getIndex()); + if (!b0) + throw FRError(_("BLOB data not valid")); + return b0; +} +//----------------------------------------------------------------------------- +// Creates a Blob (DataGridRowBlob-struct) to save data in DataGridRowsBlob.blob +// Finally the BLOB will be set with setBlob(...) +DataGridRowsBlob DataGridRows::setBlobPrepare(unsigned row, unsigned col) +{ + wxString tn(std2wxIdentifier(statementM->ColumnTable(col + 1), + databaseM->getCharsetConverter())); + wxString cn(std2wxIdentifier(statementM->ColumnName(col + 1), + databaseM->getCharsetConverter())); + + wxString stm = wxT("UPDATE ") + Identifier(tn).getQuoted() + + wxT(" SET ") + Identifier(cn).getQuoted() + + wxT(" = ? WHERE "); + std::map<wxString, UniqueConstraint *>::iterator it = + statementTablesM.find(tn); + if (it == statementTablesM.end() || (*it).second == 0) + throw FRError(_("Blob table not found.")); + + DataGridRowsBlob b; + b.row = row; + b.col = col; + b.st = addWhere((*it).second, stm, tn, buffersM[row]); + b.blob = IBPP::BlobFactory(b.st->DatabasePtr(), b.st->TransactionPtr()); + return b; +} +//----------------------------------------------------------------------------- +void DataGridRows::setBlob(DataGridRowsBlob &b) +{ + b.st->Set(1, b.blob); + b.st->Execute(); // we execute before updating internal storage + + buffersM[b.row]->setBlob(columnDefsM[b.col]->getIndex(), b.blob); + buffersM[b.row]->setFieldNull(b.col, false); + buffersM[b.row]->setFieldNA(b.col, false); + BlobColumnDef *bcd = dynamic_cast<BlobColumnDef *>(columnDefsM[b.col]); + if (!bcd) + throw FRError(_("Not a BLOB column.")); + bcd->reset(buffersM[b.row]); // reset cached blob data +} +//----------------------------------------------------------------------------- void DataGridRows::exportBlobFile(const wxString& filename, unsigned row, unsigned col, ProgressIndicator *pi) { wxFFile fl(filename, wxT("wb+")); if (!fl.IsOpened()) throw FRError(_("Cannot open destination file.")); - IBPP::Blob *b0 = buffersM[row]->getBlob(columnDefsM[col]->getIndex()); - if (!b0) - throw FRError(_("BLOB data not valid")); + IBPP::Blob *b0 = getBlob(row,col); IBPP::Blob b = *b0; + b->Open(); int size; b->Info(&size, 0, 0); @@ -1987,46 +2037,24 @@ if (pi) pi->initProgress(_("Loading..."), fl.Length()); // wxFileOffset - wxString tn(std2wxIdentifier(statementM->ColumnTable(col + 1), - databaseM->getCharsetConverter())); - wxString cn(std2wxIdentifier(statementM->ColumnName(col + 1), - databaseM->getCharsetConverter())); - - wxString stm = wxT("UPDATE ") + Identifier(tn).getQuoted() - + wxT(" SET ") + Identifier(cn).getQuoted() - + wxT(" = ? WHERE "); - std::map<wxString, UniqueConstraint *>::iterator it = - statementTablesM.find(tn); - if (it == statementTablesM.end() || (*it).second == 0) - throw FRError(_("Blob table not found.")); - IBPP::Statement st = addWhere((*it).second, stm, tn, buffersM[row]); - IBPP::Blob b = IBPP::BlobFactory(st->DatabasePtr(), - st->TransactionPtr()); - b->Create(); + DataGridRowsBlob b = setBlobPrepare(row,col); + b.blob->Create(); uint8_t buffer[32768]; while (!fl.Eof()) { size_t len = fl.Read(buffer, 32767); // slow when not 32k if (len < 1 || pi && pi->isCanceled()) break; - b->Write(buffer, len); + b.blob->Write(buffer, len); if (pi) pi->stepProgress(len); } fl.Close(); - b->Close(); + b.blob->Close(); if (pi && pi->isCanceled()) return; - st->Set(1, b); - st->Execute(); // we execute before updating internal storage - buffersM[row]->setBlob(columnDefsM[col]->getIndex(), b); - buffersM[row]->setFieldNull(col, false); - buffersM[row]->setFieldNA(col, false); - BlobColumnDef *bcd = dynamic_cast<BlobColumnDef *>(columnDefsM[col]); - if (!bcd) - throw FRError(_("Not a BLOB column.")); - bcd->reset(buffersM[row]); // reset cached blob data + setBlob(b); } //----------------------------------------------------------------------------- // returns the executed SQL statement Index: gui/controls/DataGridRows.h =================================================================== --- gui/controls/DataGridRows.h (revision 1852) +++ gui/controls/DataGridRows.h (working copy) @@ -77,6 +77,13 @@ bool fieldNA; bool fieldNumeric; }; +struct DataGridRowsBlob +{ + IBPP::Blob blob; + IBPP::Statement st; + unsigned row; + unsigned col; +}; //---------------------------------------------------------------------- class DataGridRows { @@ -126,6 +133,11 @@ ResultsetColumnDef* getColumnDef(unsigned col); void addRow(DataGridRowBuffer* buffer); + + // BLOB-Stuff + IBPP::Blob* getBlob(unsigned row, unsigned col); + DataGridRowsBlob DataGridRows::setBlobPrepare(unsigned row, unsigned col); + void DataGridRows::setBlob(DataGridRowsBlob &b); }; //---------------------------------------------------------------------- #endif Index: gui/controls/DataGridTable.cpp =================================================================== --- gui/controls/DataGridTable.cpp (revision 1852) +++ gui/controls/DataGridTable.cpp (working copy) @@ -742,6 +742,21 @@ fetchAllRowsM = fetchall; } //----------------------------------------------------------------------------- +IBPP::Blob* DataGridTable::getBlob(unsigned row, unsigned col) +{ + return rowsM.getBlob(row,col); +} +//----------------------------------------------------------------------------- +DataGridRowsBlob DataGridTable::setBlobPrepare(unsigned row, unsigned col) +{ + return rowsM.setBlobPrepare(row,col); +} +//----------------------------------------------------------------------------- +void DataGridTable::setBlob(DataGridRowsBlob &b) +{ + rowsM.setBlob(b); +} +//----------------------------------------------------------------------------- void DataGridTable::importBlobFile(const wxString& filename, int row, int col, ProgressIndicator *pi) { Index: gui/controls/DataGridTable.h =================================================================== --- gui/controls/DataGridTable.h (revision 1852) +++ gui/controls/DataGridTable.h (working copy) @@ -118,6 +118,9 @@ virtual void SetValue(int row, int col, const wxString& value); virtual bool DeleteRows(size_t pos, size_t numRows); + IBPP::Blob* getBlob(unsigned row, unsigned col); + DataGridRowsBlob setBlobPrepare(unsigned row, unsigned col); + void setBlob(DataGridRowsBlob &b); // BLOBs can be huge, so we don't use SetValue for that void importBlobFile(const wxString& filename, int row, int col, ProgressIndicator *pi = 0); Index: gui/EditBlobDialog.cpp =================================================================== --- gui/EditBlobDialog.cpp (revision 0) +++ gui/EditBlobDialog.cpp (revision 0) @@ -0,0 +1,166 @@ +/* + Copyright (c) 2004-2009 The FlameRobin Development Team + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + 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. + + + $Id: EditBlobDialog.cpp 1836 2009-05-10 11:22:13Z amaier $ + +*/ + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include <wx/stream.h> +#include "gui/ProgressDialog.h" +#include "gui/EditBlobDialog.h" +#include "gui/StyleGuide.h" + +// Static members +/* maybe later needed if plugin will be implemented +int EditBlobDialog::m_libEditBlobUseCount = 0; +wxDynamicLibrary* EditBlobDialog::m_libEditBlob = NULL; +*/ + +EditBlobDialog::EditBlobDialog(wxWindow* parent, wxString& blobName, IBPP::Blob blob, + DataGridTable* dgt, unsigned row, unsigned col) + :BaseDialog(parent, -1, wxEmptyString) +{ + m_datagridtable = dgt; + m_blobName = blobName; + m_row = row; + m_col = col; + + text_blob = new wxTextCtrl(getControlsPanel(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + button_save = new wxButton(getControlsPanel(), wxID_SAVE, wxT("Save")); + button_cancel = new wxButton(getControlsPanel(), wxID_CANCEL, wxT("Cancel")); + + set_properties(); + do_layout(); + + // Loading BLOB into Editor + blob->Open(); + int size; + blob->Info(&size, 0, 0); + ProgressDialog pd(this,_("")); + pd.initProgress(_("Loading BLOB into editor"), size); + pd.Show(); + #warning "detect binary/text ..." + text_blob->Clear(); + while (!pd.isCanceled()) + { + char buffer[32768]; + int size = blob->Read((void*)buffer, 32767); + if (size < 1) + break; + buffer[size] = '\0'; + text_blob->AppendText(_(buffer)); + pd.stepProgress(size); + } + blob->Close(); + pd.Hide(); +} + +EditBlobDialog::~EditBlobDialog() +{ + /* + // activate later if plugin will be implemented + m_libEditBlobUseCount--; + if (m_libEditBlobUseCount = 0) + { + // TODO unload lib + if (m_libEditBlob) + delete m_libEditBlob; + } + */ +} + +void EditBlobDialog::set_properties() +{ + SetTitle(wxT("Edit BLOB: "+m_blobName)); +} + +void EditBlobDialog::do_layout() +{ + wxBoxSizer* sizerControls = new wxBoxSizer(wxVERTICAL); + text_blob->SetSizeHints(200, 100); + text_blob->SetSize(200, 100); + sizerControls->Add(text_blob, 1, wxEXPAND); + + wxSizer* sizerButtons = styleguide().createButtonSizer(button_save, button_cancel); + + layoutSizers(sizerControls, sizerButtons, true); + + SetSize(620, 400); + Centre(); +} + +void EditBlobDialog::OnClose(wxCloseEvent& event) +{ + // make sure parent window is properly activated again + wxWindow* p = GetParent(); + if (p) + { + p->Enable(); + Hide(); + p->Raise(); + } + Destroy(); +} + +void EditBlobDialog::OnSaveButtonClick(wxCommandEvent& event) +{ + // Save Text into BLOB + wxString txt = text_blob->GetValue(); + + ProgressDialog pd(this, _("Saving BLOB from editor")); + pd.Show(); + DataGridRowsBlob b = m_datagridtable->setBlobPrepare(m_row,m_col); + b.blob->Create(); + b.blob->Write(txt.c_str(),txt.Length()); + b.blob->Close(); + + m_datagridtable->setBlob(b); + pd.Hide(); + + Close(); // close window +} + +void EditBlobDialog::OnCancelButtonClick(wxCommandEvent& event) +{ + Close(); +} + +//! event handling +BEGIN_EVENT_TABLE(EditBlobDialog, BaseDialog) + EVT_BUTTON(wxID_SAVE, EditBlobDialog::OnSaveButtonClick) + EVT_BUTTON(wxID_CANCEL, EditBlobDialog::OnCancelButtonClick) + EVT_CLOSE(EditBlobDialog::OnClose) +END_EVENT_TABLE() Index: gui/EditBlobDialog.h =================================================================== --- gui/EditBlobDialog.h (revision 0) +++ gui/EditBlobDialog.h (revision 0) @@ -0,0 +1,70 @@ +/* + Copyright (c) 2004-2009 The FlameRobin Development Team + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + 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. + + + $Id: EditBlobDialog.h 1836 2009-05-10 11:22:13Z amaier $ + +*/ + +#ifndef FR_EDITBLOBDIALOG_H +#define FR_EDITBLOBDIALOG_H + +#include <wx/wx.h> +#include <wx/image.h> +#include <wx/stream.h> +#include <wx/dynlib.h> + +#include <ibpp.h> + +#include "gui/BaseDialog.h" +#include "controls/DataGridTable.h" + +class EditBlobDialog : public BaseDialog { +public: + EditBlobDialog(wxWindow* parent, wxString& blobName, IBPP::Blob blob, + DataGridTable* dgt, unsigned row, unsigned col); + virtual ~EditBlobDialog(); +private: + DataGridTable *m_datagridtable; + wxString m_blobName; + unsigned m_row; + unsigned m_col; + /* + // activate later if plugin will be implemented + // Dialog-Plugin-lib + static int m_libEditBlobUseCount; + static wxDynamicLibrary* m_libEditBlob; + */ + void set_properties(); + void do_layout(); + // Events + void OnClose(wxCloseEvent& event); + void OnSaveButtonClick(wxCommandEvent& event); + void OnCancelButtonClick(wxCommandEvent& event); +protected: + wxTextCtrl* text_blob; + wxButton* button_save; + wxButton* button_cancel; + DECLARE_EVENT_TABLE() +}; + +#endif // FR_EDITBLOBDIALOG_H Index: gui/ExecuteSqlFrame.cpp =================================================================== --- gui/ExecuteSqlFrame.cpp (revision 1852) +++ gui/ExecuteSqlFrame.cpp (working copy) @@ -45,6 +45,7 @@ #include <wx/fontdlg.h> #include <wx/stopwatch.h> #include <wx/tokenzr.h> +#include <wx/mstream.h> #include <algorithm> #include <map> @@ -66,6 +67,7 @@ #include "gui/ExecuteSql.h" #include "gui/ExecuteSqlFrame.h" #include "gui/InsertDialog.h" +#include "gui/EditBlobDialog.h" #include "gui/StatementHistoryDialog.h" #include "gui/StyleGuide.h" #include "frutils.h" @@ -723,6 +725,7 @@ gridMenu->Append(Cmds::DataGrid_Copy_as_insert, _("Copy &as insert statements")); gridMenu->Append(Cmds::DataGrid_Copy_as_update, _("Copy as &update statements")); gridMenu->AppendSeparator(); + gridMenu->Append(Cmds::DataGrid_EditBlob, _("Edit BLOB")); gridMenu->Append(Cmds::DataGrid_ImportBlob, _("Import BLOB from file...")); gridMenu->Append(Cmds::DataGrid_ExportBlob, _("Save BLOB to file...")); gridMenu->AppendSeparator(); @@ -881,6 +884,7 @@ EVT_MENU(Cmds::DataGrid_Insert_row, ExecuteSqlFrame::OnMenuGridInsertRow) EVT_MENU(Cmds::DataGrid_Delete_row, ExecuteSqlFrame::OnMenuGridDeleteRow) + EVT_MENU(Cmds::DataGrid_EditBlob, ExecuteSqlFrame::OnMenuGridEditBlob) EVT_MENU(Cmds::DataGrid_ImportBlob, ExecuteSqlFrame::OnMenuGridImportBlob) EVT_MENU(Cmds::DataGrid_ExportBlob, ExecuteSqlFrame::OnMenuGridExportBlob) EVT_MENU(Cmds::DataGrid_Copy_as_insert, ExecuteSqlFrame::OnMenuGridCopyAsInsert) @@ -894,6 +898,7 @@ EVT_UPDATE_UI(Cmds::DataGrid_Insert_row, ExecuteSqlFrame::OnMenuUpdateGridInsertRow) EVT_UPDATE_UI(Cmds::DataGrid_Delete_row, ExecuteSqlFrame::OnMenuUpdateGridDeleteRow) + EVT_UPDATE_UI(Cmds::DataGrid_EditBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_ImportBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_ExportBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_Copy_as_insert, ExecuteSqlFrame::OnMenuUpdateGridHasData) @@ -1586,6 +1591,27 @@ dgt->isBlobColumn(grid_data->GetGridCursorCol())); } //----------------------------------------------------------------------------- +void ExecuteSqlFrame::OnMenuGridEditBlob(wxCommandEvent& WXUNUSED(event)) +{ + DataGridTable* dgt = grid_data->getDataGridTable(); + if (!dgt || !grid_data->GetNumberRows()) + return; + unsigned row = grid_data->GetGridCursorRow(); + unsigned col = grid_data->GetGridCursorCol(); + if (!dgt->isBlobColumn(grid_data->GetGridCursorCol())) + throw FRError(_("Not a BLOB column")); + + wxString tableName = dgt->getTableName(); + wxString fieldName = grid_data->GetColLabelValue(grid_data->GetGridCursorCol()); + wxString blobName = tableName + "." + fieldName; + + IBPP::Blob *blob = dgt->getBlob(row,col); + + EditBlobDialog *ebd = new EditBlobDialog(this,blobName,*blob,dgt,row,col); + ebd->Show(); + Disable(); +} +//----------------------------------------------------------------------------- void ExecuteSqlFrame::OnMenuGridExportBlob(wxCommandEvent& WXUNUSED(event)) { DataGridTable* dgt = grid_data->getDataGridTable(); Index: gui/ExecuteSqlFrame.h =================================================================== --- gui/ExecuteSqlFrame.h (revision 1852) +++ gui/ExecuteSqlFrame.h (working copy) @@ -40,6 +40,7 @@ #include "core/Observer.h" #include "core/StringUtils.h" +#include "controls/DataGridTable.h" #include "gui/BaseFrame.h" #include "gui/FindDialog.h" #include "sql/SqlStatement.h" @@ -199,6 +200,7 @@ void OnMenuUpdateGridInsertRow(wxUpdateUIEvent& event); void OnMenuGridDeleteRow(wxCommandEvent& event); void OnMenuUpdateGridDeleteRow(wxUpdateUIEvent& event); + void OnMenuGridEditBlob(wxCommandEvent& event); void OnMenuGridImportBlob(wxCommandEvent& event); void OnMenuGridExportBlob(wxCommandEvent& event); void OnMenuUpdateGridCellIsBlob(wxUpdateUIEvent& event); ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogAndreas Maier wrote:
> i took a look into MultilineEnterDialog and made changes to > EditBlobDialog. I think it now catches FR platform-rules. > Here is my first patch now ;-). hope it is okay. Seems fine from internals point of view. I don't know about the GUI, but I wont bother to try it until wxNotebook is there, beacause you would have to change the layout anyway. > It includes a BLOB-Editor with the ability to edit text. WxNotebook and > other things (Binary, wxHtml, etc.) will follow. Hopefully soon? You could just create a dialog with a notebook and put a single tab in it for start. In that tab, add this editor that you already have. This should be enough for the first step. I'd be willing to merge a patch that does that (if it works correctly, of course) into the HEAD. -- Milan Babuskov http://www.flamerobin.org http://www.guacosoft.com ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as DialogMilan Babuskov schrieb:
>> It includes a BLOB-Editor with the ability to edit text. WxNotebook and >> other things (Binary, wxHtml, etc.) will follow. >> > > Hopefully soon? You could just create a dialog with a notebook and put a > single tab in it for start. In that tab, add this editor that you > already have. This should be enough for the first step. > > I'd be willing to merge a patch that does that (if it works correctly, > of course) into the HEAD. > already added wxNotebook. If my source is stable enogh i will create a patch. I think it will be ready in few days. Andy ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
BLOB-Editor as Dialog - Patch 001Hi,
this patch includes the Blob-Editor: - wxNotebook-tab with binary (readonly) and Text-Editor For layout see screenshot. Tested under Windows XP (32 Bit). If i miss something let me know. Maybe i have to add a "check" if the user switches from Binary to Text to detect ending-0-chars. If not data will lost without warning. I think disabling the Text-tab if blob sub-type is binary would not solve the problem anyway. What about binary data in blob-sub-type text? Does firebird care about blob-sub types. I think no. (Correct me i i'm wrong) So any data could be in any blob-sub type. Personally i would prefer to "chech" data on loading. If a 0 char is detected text-tab will be disabled. Comments? Thank you. andy Index: gui/CommandIds.h =================================================================== --- gui/CommandIds.h (revision 1852) +++ gui/CommandIds.h (working copy) @@ -62,6 +62,8 @@ DataGrid_Delete_row, DataGrid_FetchAll, DataGrid_CancelFetchAll, + + DataGrid_EditBlob, DataGrid_ExportBlob, DataGrid_ImportBlob, DataGrid_Copy_as_insert, Index: gui/controls/DataGrid.cpp =================================================================== --- gui/controls/DataGrid.cpp (revision 1852) +++ gui/controls/DataGrid.cpp (working copy) @@ -210,6 +210,7 @@ m.Append(Cmds::DataGrid_Save_as_csv, _("Save as CSV file...")); m.AppendSeparator(); + m.Append(Cmds::DataGrid_EditBlob, _("Edit BLOB...")); m.Append(Cmds::DataGrid_ImportBlob, _("Import BLOB from file...")); m.Append(Cmds::DataGrid_ExportBlob, _("Save BLOB to file...")); m.AppendSeparator(); Index: gui/controls/DataGridRows.cpp =================================================================== --- gui/controls/DataGridRows.cpp (revision 1852) +++ gui/controls/DataGridRows.cpp (working copy) @@ -1949,16 +1949,66 @@ return (0 != dynamic_cast<BlobColumnDef *>(columnDefsM[col])); } //----------------------------------------------------------------------------- +IBPP::Blob* DataGridRows::getBlob(unsigned row, unsigned col) +{ + if ((row < 0) || (row >= buffersM.size())) + throw FRError(_("Invalid row index.")); + if ((col < 0) || (col >= columnDefsM.size())) + throw FRError(_("Invalid col index.")); + IBPP::Blob* b0 = buffersM[row]->getBlob(columnDefsM[col]->getIndex()); + if (!b0) + throw FRError(_("BLOB data not valid")); + return b0; +} +//----------------------------------------------------------------------------- +// Creates a Blob (DataGridRowBlob-struct) to save data in DataGridRowsBlob.blob +// Finally the BLOB will be set with setBlob(...) +DataGridRowsBlob DataGridRows::setBlobPrepare(unsigned row, unsigned col) +{ + wxString tn(std2wxIdentifier(statementM->ColumnTable(col + 1), + databaseM->getCharsetConverter())); + wxString cn(std2wxIdentifier(statementM->ColumnName(col + 1), + databaseM->getCharsetConverter())); + + wxString stm = wxT("UPDATE ") + Identifier(tn).getQuoted() + + wxT(" SET ") + Identifier(cn).getQuoted() + + wxT(" = ? WHERE "); + std::map<wxString, UniqueConstraint *>::iterator it = + statementTablesM.find(tn); + if (it == statementTablesM.end() || (*it).second == 0) + throw FRError(_("Blob table not found.")); + + DataGridRowsBlob b; + b.row = row; + b.col = col; + b.st = addWhere((*it).second, stm, tn, buffersM[row]); + b.blob = IBPP::BlobFactory(b.st->DatabasePtr(), b.st->TransactionPtr()); + return b; +} +//----------------------------------------------------------------------------- +void DataGridRows::setBlob(DataGridRowsBlob &b) +{ + b.st->Set(1, b.blob); + b.st->Execute(); // we execute before updating internal storage + + buffersM[b.row]->setBlob(columnDefsM[b.col]->getIndex(), b.blob); + buffersM[b.row]->setFieldNull(b.col, false); + buffersM[b.row]->setFieldNA(b.col, false); + BlobColumnDef *bcd = dynamic_cast<BlobColumnDef *>(columnDefsM[b.col]); + if (!bcd) + throw FRError(_("Not a BLOB column.")); + bcd->reset(buffersM[b.row]); // reset cached blob data +} +//----------------------------------------------------------------------------- void DataGridRows::exportBlobFile(const wxString& filename, unsigned row, unsigned col, ProgressIndicator *pi) { wxFFile fl(filename, wxT("wb+")); if (!fl.IsOpened()) throw FRError(_("Cannot open destination file.")); - IBPP::Blob *b0 = buffersM[row]->getBlob(columnDefsM[col]->getIndex()); - if (!b0) - throw FRError(_("BLOB data not valid")); + IBPP::Blob *b0 = getBlob(row,col); IBPP::Blob b = *b0; + b->Open(); int size; b->Info(&size, 0, 0); @@ -1987,46 +2037,24 @@ if (pi) pi->initProgress(_("Loading..."), fl.Length()); // wxFileOffset - wxString tn(std2wxIdentifier(statementM->ColumnTable(col + 1), - databaseM->getCharsetConverter())); - wxString cn(std2wxIdentifier(statementM->ColumnName(col + 1), - databaseM->getCharsetConverter())); - - wxString stm = wxT("UPDATE ") + Identifier(tn).getQuoted() - + wxT(" SET ") + Identifier(cn).getQuoted() - + wxT(" = ? WHERE "); - std::map<wxString, UniqueConstraint *>::iterator it = - statementTablesM.find(tn); - if (it == statementTablesM.end() || (*it).second == 0) - throw FRError(_("Blob table not found.")); - IBPP::Statement st = addWhere((*it).second, stm, tn, buffersM[row]); - IBPP::Blob b = IBPP::BlobFactory(st->DatabasePtr(), - st->TransactionPtr()); - b->Create(); + DataGridRowsBlob b = setBlobPrepare(row,col); + b.blob->Create(); uint8_t buffer[32768]; while (!fl.Eof()) { size_t len = fl.Read(buffer, 32767); // slow when not 32k if (len < 1 || pi && pi->isCanceled()) break; - b->Write(buffer, len); + b.blob->Write(buffer, len); if (pi) pi->stepProgress(len); } fl.Close(); - b->Close(); + b.blob->Close(); if (pi && pi->isCanceled()) return; - st->Set(1, b); - st->Execute(); // we execute before updating internal storage - buffersM[row]->setBlob(columnDefsM[col]->getIndex(), b); - buffersM[row]->setFieldNull(col, false); - buffersM[row]->setFieldNA(col, false); - BlobColumnDef *bcd = dynamic_cast<BlobColumnDef *>(columnDefsM[col]); - if (!bcd) - throw FRError(_("Not a BLOB column.")); - bcd->reset(buffersM[row]); // reset cached blob data + setBlob(b); } //----------------------------------------------------------------------------- // returns the executed SQL statement Index: gui/controls/DataGridRows.h =================================================================== --- gui/controls/DataGridRows.h (revision 1852) +++ gui/controls/DataGridRows.h (working copy) @@ -77,6 +77,13 @@ bool fieldNA; bool fieldNumeric; }; +struct DataGridRowsBlob +{ + IBPP::Blob blob; + IBPP::Statement st; + unsigned row; + unsigned col; +}; //---------------------------------------------------------------------- class DataGridRows { @@ -126,6 +133,11 @@ ResultsetColumnDef* getColumnDef(unsigned col); void addRow(DataGridRowBuffer* buffer); + + // BLOB-Stuff + IBPP::Blob* getBlob(unsigned row, unsigned col); + DataGridRowsBlob DataGridRows::setBlobPrepare(unsigned row, unsigned col); + void DataGridRows::setBlob(DataGridRowsBlob &b); }; //---------------------------------------------------------------------- #endif Index: gui/controls/DataGridTable.cpp =================================================================== --- gui/controls/DataGridTable.cpp (revision 1852) +++ gui/controls/DataGridTable.cpp (working copy) @@ -742,6 +742,21 @@ fetchAllRowsM = fetchall; } //----------------------------------------------------------------------------- +IBPP::Blob* DataGridTable::getBlob(unsigned row, unsigned col) +{ + return rowsM.getBlob(row,col); +} +//----------------------------------------------------------------------------- +DataGridRowsBlob DataGridTable::setBlobPrepare(unsigned row, unsigned col) +{ + return rowsM.setBlobPrepare(row,col); +} +//----------------------------------------------------------------------------- +void DataGridTable::setBlob(DataGridRowsBlob &b) +{ + rowsM.setBlob(b); +} +//----------------------------------------------------------------------------- void DataGridTable::importBlobFile(const wxString& filename, int row, int col, ProgressIndicator *pi) { Index: gui/controls/DataGridTable.h =================================================================== --- gui/controls/DataGridTable.h (revision 1852) +++ gui/controls/DataGridTable.h (working copy) @@ -118,6 +118,9 @@ virtual void SetValue(int row, int col, const wxString& value); virtual bool DeleteRows(size_t pos, size_t numRows); + IBPP::Blob* getBlob(unsigned row, unsigned col); + DataGridRowsBlob setBlobPrepare(unsigned row, unsigned col); + void setBlob(DataGridRowsBlob &b); // BLOBs can be huge, so we don't use SetValue for that void importBlobFile(const wxString& filename, int row, int col, ProgressIndicator *pi = 0); Index: gui/EditBlobDialog.cpp =================================================================== --- gui/EditBlobDialog.cpp (revision 0) +++ gui/EditBlobDialog.cpp (revision 0) @@ -0,0 +1,476 @@ +/* + Copyright (c) 2004-2009 The FlameRobin Development Team + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + 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. + + + $Id: EditBlobDialog.cpp 1836 2009-05-10 11:22:13Z amaier $ + +*/ + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include <wx/stream.h> +#include <wx/mstream.h> +#include "core/FRError.h" +#include "core/StringUtils.h" +#include "gui/ProgressDialog.h" +#include "gui/EditBlobDialog.h" +#include "gui/StyleGuide.h" + +// Static members +/* maybe later needed if plugin will be implemented +int EditBlobDialog::m_libEditBlobUseCount = 0; +wxDynamicLibrary* EditBlobDialog::m_libEditBlob = NULL; +*/ + +EditBlobDialog::EditBlobDialog(wxWindow* parent, wxString& blobName, IBPP::Blob blob, + DataGridTable* dgt, unsigned row, unsigned col) + :BaseDialog(parent, -1, wxEmptyString) +{ + m_running = false; // disable wxNotebookPageChanged-Events + m_datagridtable = dgt; + m_blobName = blobName; + m_row = row; + m_col = col; + m_blob = blob; + + notebook = new wxNotebook(getControlsPanel(), wxID_ANY); + blob_text = new wxStyledTextCtrl(notebook, wxID_ANY); + blob_binary = new wxStyledTextCtrl(notebook, wxID_ANY); + + button_save = new wxButton(getControlsPanel(), wxID_SAVE, wxT("Save")); + button_cancel = new wxButton(getControlsPanel(), wxID_CANCEL, wxT("Cancel")); + + set_properties(); + do_layout(); + + m_running = true; // enable wxNotebookPageChanged-Events +} + +bool EditBlobDialog::Init() +{ + // Loading BLOB into Editor + m_blob->Open(); + frInputBlobStream inpblob(m_blob); + bool res = LoadFromStreamAsBinary(inpblob,wxT("Loading BLOB into editor.")); + m_editormode = Binary; + m_blob->Close(); + + return res; +} + +bool EditBlobDialog::LoadFromStreamAsText(wxInputStream& stream, const wxString& progressTitle) +{ + int toread = stream.GetSize(); + ProgressDialog pd(this,_("")); + pd.initProgress(progressTitle, toread); + pd.Show(); + blob_text->ClearAll(); + + // allocate a buffer of the full size that is needed + // for the text. So we have no troubles with splittet + // multibyte-chars./amaier + //char buffer[toread+1]; + char *buffer = (char*)malloc(toread+1); + if (buffer == NULL) + { + wxMessageBox(wxT("Not enough Memory!"),wxT("ERROR")); + return false; + } + + char* bufptr = buffer; + int readed = 0; + // Load text in 32k-Blocks. + // So we can give the user the ability to cancel. + while ((!pd.isCanceled()) && (readed < toread)) + { + int nextread = std::min(32767,toread - readed); + stream.Read((void*)bufptr, nextread); + int lastread = stream.LastRead(); + if (lastread < 1) + break; + bufptr += lastread; + readed += lastread; + pd.stepProgress(lastread); + } + buffer[readed] = '\0'; + + if (!pd.isCanceled()) + blob_text->SetText(std2wx(buffer)); + + free(buffer); + pd.Hide(); + + return !pd.isCanceled(); +} + +bool EditBlobDialog::LoadFromStreamAsBinary(wxInputStream& stream, const wxString& progressTitle) +{ + int size = stream.GetSize(); + ProgressDialog pd(this,_("")); + pd.initProgress(progressTitle, size); + pd.Show(); + + // set the wxStyledTextControl to ReadOnly = false to modify the text + blob_binary->SetReadOnly(false); + blob_binary->ClearAll(); + int col = 0; + int line = 0; + wxString txtLine = wxT(""); + while (!pd.isCanceled()) + { + char buffer[32768]; + stream.Read((void*)buffer, 32767); + int size = stream.LastRead(); + if (size < 1) + break; + buffer[size] = '\0'; + + int bufpos = 0; + while (bufpos < size) + { + txtLine += wxString::Format( wxT("%02X"), (unsigned char)(buffer[bufpos]) ); + bufpos++; + col++; + + if ((col % 8) == 0) + txtLine += wxT(" "); + if (col >= 32) + { + blob_binary->AddText(txtLine); + blob_binary->AddText(wxT("\n")); + txtLine = wxT(""); + col = 0; + line++; + } + } + pd.stepProgress(size); + } + // add the last line if col > 0 + if (!pd.isCanceled()) + { + if (col > 0) + blob_binary->AppendText(txtLine); + } + blob_binary->SetReadOnly(true); + pd.Hide(); + + return !pd.isCanceled(); +} + +bool EditBlobDialog::SaveToStream(wxOutputStream& stream, const wxString& progressTitle) +{ + ProgressDialog pd(this, progressTitle); //_("Saving Editor-Data")); + pd.Show(); + switch (m_editormode) + { + case Binary : + { + const int maxbufsize = 32768; + char buffer[maxbufsize]; + int bufsize = 0; + wxString txt = blob_binary->GetText(); + int txtpos = 0; + while ((txtpos < txt.Length()) && (!pd.isCanceled())) + { + char ch1 = txt.GetChar(txtpos); + // skip spaces and cr + if ((ch1 == ' ') || (ch1 == 0x0A) || (ch1 == 0x0D)) + { + txtpos++; + continue; + } + char ch2 = txt.GetChar(txtpos+1); + + int dig1 = 0; + int dig2 = 0; + + if (isdigit(ch1)) dig1 = ch1 - '0'; + else if ((ch1 >= 'A') && (ch1 <= 'F')) dig1 = ch1 - 'A' + 10; + else if ((ch1 >= 'a') && (ch1 <= 'f')) dig1 = ch1 - 'a' + 10; + else FRError(wxT("Wrong HEX-value: "+ch1)); + + if (isdigit(ch2)) dig2 = ch2 - '0'; + else if ((ch2 >= 'A') && (ch2 <= 'F')) dig2 = ch2 - 'A' + 10; + else if ((ch2 >= 'a') && (ch2 <= 'f')) dig2 = ch2 - 'a' + 10; + else FRError(wxT("Wrong HEX-value: "+ch2)); + + buffer[bufsize] = dig1*16 + dig2; + + if (bufsize >= maxbufsize-1) + { + stream.Write(buffer,bufsize); + pd.stepProgress(bufsize); + bufsize = 0; + } + else bufsize++; + txtpos += 2; + }; + if (bufsize > 0) + { + stream.Write(buffer,bufsize); + pd.stepProgress(bufsize); + } + } + break; + case Text : + { + std::string txt = wx2std(blob_text->GetText()); + stream.Write(txt.c_str(),txt.length()); + } + break; + default : + FRError(wxT("Unknown editormode!")); + } + pd.Hide(); + + return !pd.isCanceled(); +} + +EditBlobDialog::~EditBlobDialog() +{ + /* + // activate later if plugin will be implemented + m_libEditBlobUseCount--; + if (m_libEditBlobUseCount = 0) + { + // TODO unload lib + if (m_libEditBlob) + delete m_libEditBlob; + } + */ +} + +void EditBlobDialog::set_properties() +{ + SetTitle(wxT("Edit BLOB: "+m_blobName)); + blob_text->SetId(Text); + blob_binary->SetId(Binary); +} + +void EditBlobDialog::do_layout() +{ + wxBoxSizer* sizerControls = new wxBoxSizer(wxVERTICAL); + // *** TEXT-EDIT-LAYOUT *** + blob_text->SetSizeHints(200, 100); + blob_text->SetSize(200, 100); + // fixed-width font (i think it is better for showing) + wxFont ftxt(styleguide().getEditorFontSize(), + wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, + false); + blob_text->StyleSetFont(0,ftxt); + // numbering on text should be usefull + blob_text->SetMarginType(0,wxSTC_MARGIN_NUMBER); + blob_text->SetMarginWidth(0,30); + blob_text->SetMarginWidth(1,0); + blob_text->SetMarginWidth(2,0); + + // *** BINARY-SHOW-LAYOUT *** + blob_binary->SetSizeHints(200, 100); + blob_binary->SetSize(200, 100); + blob_binary->SetReadOnly(true); + // fixed-width font + wxFont fbin(styleguide().getEditorFontSize(), + wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, + false); + blob_binary->StyleSetFont(0,fbin); + // set with of the viewport to avoid "empty" space after each line + blob_binary->SetScrollWidth(600); + // set up a left-margin for numbering lines + // TODO - calc with of dialog to fit excact a binary line without scrolling" + blob_binary->SetMarginType(0,wxSTC_MARGIN_NUMBER); + blob_binary->SetMarginWidth(0,30); + blob_binary->SetMarginWidth(1,0); + blob_binary->SetMarginWidth(2,0); + + notebook->AddPage(blob_binary, wxT("Binary"), false); + notebook->AddPage(blob_text, wxT("Text"), false); + + sizerControls->Add(notebook, 1, wxEXPAND); + + wxSizer* sizerButtons = styleguide().createButtonSizer(button_save, button_cancel); + + layoutSizers(sizerControls, sizerButtons, true); + + SetSize(620, 400); + Centre(); +} + +void EditBlobDialog::OnClose(wxCloseEvent& event) +{ + // make sure parent window is properly activated again + wxWindow* p = GetParent(); + if (p) + { + p->Enable(); + Hide(); + p->Raise(); + } + Destroy(); +} + +void EditBlobDialog::OnSaveButtonClick(wxCommandEvent& event) +{ + // Save Editor-Data into BLOB + DataGridRowsBlob b = m_datagridtable->setBlobPrepare(m_row,m_col); + b.blob->Create(); + frOutputBlobStream bs(b.blob); + SaveToStream(bs,wxT("Saving Data to BLOB")); + b.blob->Close(); + + m_datagridtable->setBlob(b); + + m_running = false; + + // Close window + Close(); +} + +void EditBlobDialog::OnCancelButtonClick(wxCommandEvent& event) +{ + Close(); +} + +void EditBlobDialog::OnNotebookPageChanged(wxNotebookEvent& event) +{ + if (!m_running) + return; + int page = event.GetSelection(); + int oldpage = event.GetOldSelection(); + if ((page < 0) || (oldpage < 0)) + return; + + + int pageId = notebook->GetPage(page)->GetId(); + + wxMemoryOutputStream outBuf(NULL,0); + if (!SaveToStream(outBuf,wxT("Switching editor-mode (Saving)"))) + { + wxMessageBox(wxT("A error occured while switching editor-mode. (Saving)")); + //event.Veto(); + notebook->ChangeSelection(oldpage); + return; + } + + bool loadOk = false; + wxString loadTitle = wxT("Switching editor-mode (Loading)"); + wxMemoryInputStream inBuf(outBuf); + switch (pageId) + { + case Binary : + loadOk = LoadFromStreamAsBinary(inBuf,loadTitle); + break; + case Text : + loadOk = LoadFromStreamAsText(inBuf,loadTitle); + break; + } + if (!loadOk) + { + wxMessageBox(wxT("A error occured while switching editor-mode. (Loading)")); + notebook->ChangeSelection(oldpage); + //event.Veto(); + return; + } + m_editormode = (EditorMode)pageId; +} + +//! event handling +BEGIN_EVENT_TABLE(EditBlobDialog, BaseDialog) + //EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, EditBlobDialog::OnNotebookPageChanged) + EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, EditBlobDialog::OnNotebookPageChanged) + EVT_BUTTON(wxID_SAVE, EditBlobDialog::OnSaveButtonClick) + EVT_BUTTON(wxID_CANCEL, EditBlobDialog::OnCancelButtonClick) + EVT_CLOSE(EditBlobDialog::OnClose) +END_EVENT_TABLE() + + +// Helper-Class for streaming into blob / buffer +// frInputBlobStream +frInputBlobStream::frInputBlobStream(IBPP::Blob blob) + :wxInputStream() +{ + m_blob = blob; + blob->Info(&m_size, 0, 0); +} + +frInputBlobStream::~frInputBlobStream() +{ +} + +size_t frInputBlobStream::OnSysRead(void *buffer, size_t size) +{ + return m_blob->Read(buffer,size); +} + +size_t frInputBlobStream::GetSize() const +{ + return m_size; +} + +// Helper-Class for streaming into blob / buffer +// frOutputBlobStream +frOutputBlobStream::frOutputBlobStream(IBPP::Blob blob) + :wxOutputStream() +{ + m_blob = blob; +} + +frOutputBlobStream::~frOutputBlobStream() +{ +} + +size_t frOutputBlobStream::OnSysWrite(const void *buffer, size_t bufsize) +{ + if (bufsize == 0) + return 0; + + m_blob->Write(buffer,bufsize); + return bufsize; +} + +// Helper-Class +/*int wxFRNotebook::SetSelection(size_t page) +{ + m_newSelection = page; + wxString x = wxString::Format("%i",page); + wxMessageBox(x); + wxNotebook::SetSelection(page); +}*/ + +/*int wxFRNotebook::ChangeSelection(size_t page) +{ + m_newSelection = page; + wxString x = wxString::Format("%i",page); + wxMessageBox(wxT("ChangeSelection")); + wxNotebook::ChangeSelection(page); +}*/ + Index: gui/EditBlobDialog.h =================================================================== --- gui/EditBlobDialog.h (revision 0) +++ gui/EditBlobDialog.h (revision 0) @@ -0,0 +1,259 @@ +/* + Copyright (c) 2004-2009 The FlameRobin Development Team + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + 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. + + + $Id: EditBlobDialog.h 1836 2009-05-10 11:22:13Z amaier $ + +*/ + +#ifndef FR_EDITBLOBDIALOG_H +#define FR_EDITBLOBDIALOG_H + +#include <wx/wx.h> +#include <wx/notebook.h> +#include <wx/stc/stc.h> +#include <wx/image.h> +#include <wx/stream.h> + +#include <ibpp.h> + +#include "gui/BaseDialog.h" +#include "controls/DataGridTable.h" + +// Helper-Class to solve wxNotebookEvent problem +// with PAGE_CHAGING-EVENT under windows +/*class wxFRNotebook : public wxNotebook +{ + public: + int m_newSelection; + //virtual int SetSelection(size_t page); + virtual int ChangeSelection(size_t page); + + wxFRNotebook(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxNotebookNameStr) + : wxNotebook(parent,id,pos,size,style,name) {}; +};*/ + +class EditBlobDialog : public BaseDialog { +public: + EditBlobDialog(wxWindow* parent, wxString& blobName, IBPP::Blob blob, + DataGridTable* dgt, unsigned row, unsigned col); + virtual ~EditBlobDialog(); + bool Init(); +private: + typedef enum EditorMode { Binary = 1, Text = 2 }; + + DataGridTable *m_datagridtable; + wxString m_blobName; + unsigned m_row; + unsigned m_col; + IBPP::Blob m_blob; + EditorMode m_editormode; + bool m_running; + /* + // activate later if plugin will be implemented + // Dialog-Plugin-lib + static int m_libEditBlobUseCount; + static wxDynamicLibrary* m_libEditBlob; + */ + + // Switching Editor-Mode + // B = Binary + // T = Text + // H = HTML + // I = Image (bmp/jpg/...) + // R = RTF (Win only) + // + // o = allowed + // x = not allowed (e.g. makes no sence) + // + // X B T H I R + // B - o o o o + // T o - o x o + // H o o - x x + // I o x x - x + // R o o x x - + + // Loading (Blob/Stream) + bool LoadFromStreamAsBinary(wxInputStream& stream, const wxString& progressTitle); + bool LoadFromStreamAsText(wxInputStream& stream, const wxString& progressTitle); + // Saving (Blob/Stream) + bool SaveToStream(wxOutputStream& stream, const wxString& progressTitle); + + void set_properties(); + void do_layout(); + // Events + void OnClose(wxCloseEvent& event); + void OnSaveButtonClick(wxCommandEvent& event); + void OnCancelButtonClick(wxCommandEvent& event); + void OnNotebookPageChanged(wxNotebookEvent& event); +protected: + wxNotebook* notebook; + wxStyledTextCtrl* blob_text; + wxStyledTextCtrl* blob_binary; + wxButton* button_save; + wxButton* button_cancel; + DECLARE_EVENT_TABLE() +}; + +// Helper-Class for streaming into blob / buffer +class frInputBlobStream : public wxInputStream +{ + public: + frInputBlobStream(IBPP::Blob blob); + virtual ~frInputBlobStream(); + //virtual wxInputStream& Read(void *buffer, size_t size); + virtual size_t GetSize() const; + protected: + virtual size_t OnSysRead(void *buffer, size_t size); + + //x wxStreamError GetLastError() const { return m_lasterror; } + //x virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; } + //x bool operator!() const { return !IsOk(); } + + // reset the stream state + //void Reset() { m_lasterror = wxSTREAM_NO_ERROR; } + + // this doesn't make sense for all streams, always test its return value + //virtual wxFileOffset GetLength() const { return wxInvalidOffset; } + + // returns true if the streams supports seeking to arbitrary offsets + //virtual bool IsSeekable() const { return false; } + //protected: + //virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode); + //virtual wxFileOffset OnSysTell() const; + + //size_t m_lastcount; + //wxStreamError m_lasterror; + + private: + IBPP::Blob m_blob; + int m_size; + /*class WXDLLIMPEXP_BASE wxStreamBase +{ +public: +// - = überschrieben x = nicht überschrieben + + - wxStreamBase(); + - virtual ~wxStreamBase(); + + // error testing + x wxStreamError GetLastError() const { return m_lasterror; } + x virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; } + x bool operator!() const { return !IsOk(); } + + // reset the stream state + void Reset() { m_lasterror = wxSTREAM_NO_ERROR; } + + // this doesn't make sense for all streams, always test its return value + virtual size_t GetSize() const; + virtual wxFileOffset GetLength() const { return wxInvalidOffset; } + + // returns true if the streams supports seeking to arbitrary offsets + virtual bool IsSeekable() const { return false; } + +protected: + virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode); + virtual wxFileOffset OnSysTell() const; + + size_t m_lastcount; + wxStreamError m_lasterror; + + friend class wxStreamBuffer; + + DECLARE_NO_COPY_CLASS(wxStreamBase) +}; +*/ +}; + +class frOutputBlobStream : public wxOutputStream +{ + public: + frOutputBlobStream(IBPP::Blob blob); + virtual ~frOutputBlobStream(); + + //x wxStreamError GetLastError() const { return m_lasterror; } + //x virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; } + //x bool operator!() const { return !IsOk(); } + + // reset the stream state + //void Reset() { m_lasterror = wxSTREAM_NO_ERROR; } + + // this doesn't make sense for all streams, always test its return value + //virtual size_t GetSize() const; + //virtual wxFileOffset GetLength() const { return wxInvalidOffset; } + + // returns true if the streams supports seeking to arbitrary offsets + //virtual bool IsSeekable() const { return false; } + //protected: + //virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode); + //virtual wxFileOffset OnSysTell() const; + + //size_t m_lastcount; + //wxStreamError m_lasterror; + + protected: + virtual size_t OnSysWrite(const void *buffer, size_t bufsize); + private: + IBPP::Blob m_blob; + /*class WXDLLIMPEXP_BASE wxStreamBase +{ +public: +// - = überschrieben x = nicht überschrieben + + - wxStreamBase(); + - virtual ~wxStreamBase(); + + // error testing + x wxStreamError GetLastError() const { return m_lasterror; } + x virtual bool IsOk() const { return GetLastError() == wxSTREAM_NO_ERROR; } + x bool operator!() const { return !IsOk(); } + + // reset the stream state + void Reset() { m_lasterror = wxSTREAM_NO_ERROR; } + + // this doesn't make sense for all streams, always test its return value + virtual size_t GetSize() const; + virtual wxFileOffset GetLength() const { return wxInvalidOffset; } + + // returns true if the streams supports seeking to arbitrary offsets + virtual bool IsSeekable() const { return false; } + +protected: + virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode); + virtual wxFileOffset OnSysTell() const; + + size_t m_lastcount; + wxStreamError m_lasterror; + + friend class wxStreamBuffer; + + DECLARE_NO_COPY_CLASS(wxStreamBase) +}; +*/ +}; + +#endif // FR_EDITBLOBDIALOG_H Index: gui/ExecuteSqlFrame.cpp =================================================================== --- gui/ExecuteSqlFrame.cpp (revision 1852) +++ gui/ExecuteSqlFrame.cpp (working copy) @@ -66,6 +66,7 @@ #include "gui/ExecuteSql.h" #include "gui/ExecuteSqlFrame.h" #include "gui/InsertDialog.h" +#include "gui/EditBlobDialog.h" #include "gui/StatementHistoryDialog.h" #include "gui/StyleGuide.h" #include "frutils.h" @@ -723,6 +724,7 @@ gridMenu->Append(Cmds::DataGrid_Copy_as_insert, _("Copy &as insert statements")); gridMenu->Append(Cmds::DataGrid_Copy_as_update, _("Copy as &update statements")); gridMenu->AppendSeparator(); + gridMenu->Append(Cmds::DataGrid_EditBlob, _("Edit BLOB")); gridMenu->Append(Cmds::DataGrid_ImportBlob, _("Import BLOB from file...")); gridMenu->Append(Cmds::DataGrid_ExportBlob, _("Save BLOB to file...")); gridMenu->AppendSeparator(); @@ -881,6 +883,7 @@ EVT_MENU(Cmds::DataGrid_Insert_row, ExecuteSqlFrame::OnMenuGridInsertRow) EVT_MENU(Cmds::DataGrid_Delete_row, ExecuteSqlFrame::OnMenuGridDeleteRow) + EVT_MENU(Cmds::DataGrid_EditBlob, ExecuteSqlFrame::OnMenuGridEditBlob) EVT_MENU(Cmds::DataGrid_ImportBlob, ExecuteSqlFrame::OnMenuGridImportBlob) EVT_MENU(Cmds::DataGrid_ExportBlob, ExecuteSqlFrame::OnMenuGridExportBlob) EVT_MENU(Cmds::DataGrid_Copy_as_insert, ExecuteSqlFrame::OnMenuGridCopyAsInsert) @@ -894,6 +897,7 @@ EVT_UPDATE_UI(Cmds::DataGrid_Insert_row, ExecuteSqlFrame::OnMenuUpdateGridInsertRow) EVT_UPDATE_UI(Cmds::DataGrid_Delete_row, ExecuteSqlFrame::OnMenuUpdateGridDeleteRow) + EVT_UPDATE_UI(Cmds::DataGrid_EditBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_ImportBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_ExportBlob, ExecuteSqlFrame::OnMenuUpdateGridCellIsBlob) EVT_UPDATE_UI(Cmds::DataGrid_Copy_as_insert, ExecuteSqlFrame::OnMenuUpdateGridHasData) @@ -1586,6 +1590,30 @@ dgt->isBlobColumn(grid_data->GetGridCursorCol())); } //----------------------------------------------------------------------------- +void ExecuteSqlFrame::OnMenuGridEditBlob(wxCommandEvent& WXUNUSED(event)) +{ + DataGridTable* dgt = grid_data->getDataGridTable(); + if (!dgt || !grid_data->GetNumberRows()) + return; + unsigned row = grid_data->GetGridCursorRow(); + unsigned col = grid_data->GetGridCursorCol(); + if (!dgt->isBlobColumn(grid_data->GetGridCursorCol())) + throw FRError(_("Not a BLOB column")); + + wxString tableName = dgt->getTableName(); + wxString fieldName = grid_data->GetColLabelValue(grid_data->GetGridCursorCol()); + wxString blobName = tableName + _(".") + fieldName; + + IBPP::Blob *blob = dgt->getBlob(row,col); + + EditBlobDialog *ebd = new EditBlobDialog(this,blobName,*blob,dgt,row,col); + if (ebd->Init()) + { + ebd->Show(); + Disable(); + } +} +//----------------------------------------------------------------------------- void ExecuteSqlFrame::OnMenuGridExportBlob(wxCommandEvent& WXUNUSED(event)) { DataGridTable* dgt = grid_data->getDataGridTable(); Index: gui/ExecuteSqlFrame.h =================================================================== --- gui/ExecuteSqlFrame.h (revision 1852) +++ gui/ExecuteSqlFrame.h (working copy) @@ -40,6 +40,7 @@ #include "core/Observer.h" #include "core/StringUtils.h" +#include "controls/DataGridTable.h" #include "gui/BaseFrame.h" #include "gui/FindDialog.h" #include "sql/SqlStatement.h" @@ -199,6 +200,7 @@ void OnMenuUpdateGridInsertRow(wxUpdateUIEvent& event); void OnMenuGridDeleteRow(wxCommandEvent& event); void OnMenuUpdateGridDeleteRow(wxUpdateUIEvent& event); + void OnMenuGridEditBlob(wxCommandEvent& event); void OnMenuGridImportBlob(wxCommandEvent& event); void OnMenuGridExportBlob(wxCommandEvent& event); void OnMenuUpdateGridCellIsBlob(wxUpdateUIEvent& event); ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Hi,
Andreas Maier wrote: > this patch includes the Blob-Editor: > - wxNotebook-tab with binary (readonly) and Text-Editor > > For layout see screenshot. > Tested under Windows XP (32 Bit). the screen shot looks really good. As soon as I find the time I will try on Mac OS X and report back. > Personally i would prefer to "chech" data on loading. If a 0 char is > detected text-tab will be disabled. > Comments? I don't know whether that's good. If a BLOB contains UTF-16 characters chances are high that a 0 is found. Actually I don't know at all what to do about character sets in BLOBs... BTW: From a cursory glance over the patch I saw that you used indexed access to a wxString character - that's something we need to avoid if possible. I will post another message regarding this issue. Thanks for your work on this -- Michael Hieke ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://www.creativitycat.com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Andreas Maier wrote:
> this patch includes the Blob-Editor: > - wxNotebook-tab with binary (readonly) and Text-Editor Hi Andreas, Screenshot looks very nice. Few notes about the patch: 1. There are some extra qualifications in DataGridRows. When you're inside class declaration, there's no need for extra qualification. Example: class DataGridRows { ... void DataGridRows::something(); // bad void something(); // good BTW, such code fails to compile on GCC, with error message like this: ../src/gui/controls/DataGridRows.h:139: error: extra qualification 'DataGridRows 2. when adding new files, you should add .cpp and .h file to flamerobin.bkl and use bakefile_gen program to regenerate the makefiles. We currently use Bakefile 0.2.5. Please feel free to ask here if you have any questions/problems regarding these (or any other) issues. > Maybe i have to add a "check" if the user switches from Binary to Text > to detect ending-0-chars. > If not data will lost without warning. I think disabling the Text-tab if > blob sub-type is binary would not solve the problem anyway. Maybe if you made the content read-only. > What about binary data in blob-sub-type text? > Does firebird care about blob-sub > types. I think no. (Correct me i i'm wrong) You are correct. > Personally i would prefer to "chech" data on loading. If a 0 char is > detected text-tab will be disabled. I hope that by "chech" you meant "cache"? Yes, that would be very nice. It seems we need to discuss how will this work. Should we disable tab-switching until changes are saved, or we used shared memory for all tabs to use? BTW, I don't like the idea of disabling, because you cannot copy/paste such text. It would be much better to make it read-only. > Comments? - IMHO, if blob subtype is text, it should open "text" tab initially. - we should add some UI to make blob field NULL I also have some ideas about binary tab: - use 2 different colors for columns, so each byte is clearly separated from the next one. I have no idea if this would slow down wxSTC - needs testing - in binary mode, rows should not have labels: 1, 2, 3, 4, 5, ..., but offset instead: 0, 32, 64, 96, 128, etc. - of course, we will need to allow editing - it is BLOB *editor* after all. In the meantime, control should have silver/gray color to indicate that it is read-only. > Thank you. Thank you Andy. Considering this is your first patch, it is very good. Anyway, I made a few fixes, tested on Linux/Gtk and commited everything to repository so we can all test and comment on it easily. -- Milan Babuskov http://www.flamerobin.org http://www.guacosoft.com ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Hi, >> Personally i would prefer to "chech" data on loading. If a 0 char is >> detected text-tab will be disabled. >> > > I hope that by "chech" you meant "cache"? Yes, that would be very nice. > It seems we need to discuss how will this work. Should we disable > tab-switching until changes are saved, or we used shared memory for all > tabs to use? > > BTW, I don't like the idea of disabling, because you cannot copy/paste > such text. It would be much better to make it read-only. > I don't know ATM how to handle. Yes copy/pasting would be good. But the text will be truncated if you save it back. Maybe i could handle it as follows: 1) Detect characterset of blob / database 2) Check the data according to the detected characterset (UTF8, ...) 3) If no Line-End-Char (or Word or something) is found -> Text can edited -> if the tab gets switched data will be saved to the cache and restored from it If a Line-End-Char (or Word or something) is found -> Text will be read-only -> Maybe i can show a hint to the user. Because it may be curios if sometimes text is read-only and sometimes not. -> if the tab gets switched the data will not saved to the cache - only restored BTW: "cache" mechanism is already implemented. If you edit text and switch to binary the binary field will show the edited text. The current implementation saves and restores the data to/from a memorystream if you switch the tab. > >> Comments? >> > > - IMHO, if blob subtype is text, it should open "text" tab initially. > > - we should add some UI to make blob field NULL > > I also have some ideas about binary tab: > > - use 2 different colors for columns, so each byte is clearly separated > from the next one. I have no idea if this would slow down wxSTC - needs > testing > > - in binary mode, rows should not have labels: 1, 2, 3, 4, 5, ..., but > offset instead: 0, 32, 64, 96, 128, etc. > > - of course, we will need to allow editing - it is BLOB *editor* after > all. In the meantime, control should have silver/gray color to indicate > that it is read-only. > > >> Thank you. >> > > Thank you Andy. Considering this is your first patch, it is very good. > Thank you. Yes, it was my first patch. ;-) > Anyway, I made a few fixes, tested on Linux/Gtk and commited everything > to repository so we can all test and comment on it easily. > Great. Thank you. Andy ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Hi,
Michael Hieke schrieb: > Hi, > > Andreas Maier wrote: > > the screen shot looks really good. As soon as I find the time I will > try on Mac OS X and report back. > > Thank you. >> Personally i would prefer to "chech" data on loading. If a 0 char is >> detected text-tab will be disabled. >> Comments? >> > > I don't know whether that's good. If a BLOB contains UTF-16 characters > chances are high that a 0 is found. Actually I don't know at all what > to do about character sets in BLOBs... > Please see my other post. > BTW: From a cursory glance over the patch I saw that you used indexed > access to a wxString character - that's something we need to avoid if > possible. I will post another message regarding this issue. > Yes, right. Anyway i didn't know how to handle that correct. I know it is a bad to use wxString character because of Multibyte-characters. Sorry, i will correct it. Anyway if have to rework code if we have decided wether or how to handle blob/database character set in text-mode. Andy ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Milan Babuskov schrieb:
> Andreas Maier wrote: > >> this patch includes the Blob-Editor: >> - wxNotebook-tab with binary (readonly) and Text-Editor >> > > Hi Andreas, > > Screenshot looks very nice. Few notes about the patch: > > 1. There are some extra qualifications in DataGridRows. When you're > inside class declaration, there's no need for extra qualification. Example: > > class DataGridRows > { > ... > void DataGridRows::something(); // bad > void something(); // good > > BTW, such code fails to compile on GCC, with error message like this: > > ../src/gui/controls/DataGridRows.h:139: error: extra qualification > 'DataGridRows > > > 2. when adding new files, you should add .cpp and .h file to > flamerobin.bkl and use bakefile_gen program to regenerate the makefiles. > We currently use Bakefile 0.2.5. > > Please feel free to ask here if you have any questions/problems > regarding these (or any other) issues. > I've downloaded and installed bakefile 0.2.5. I will try it tomorrow. BTW. My mainlanguage is delphi. I never worked on a real project in c++ nor wxWidgets. So if i code some crazy line, please be patient. ;-). Andy ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001On Tue, May 26, 2009 at 9:50 PM, Andreas Maier <andy1.m@...> wrote:
>>> Personally i would prefer to "chech" data on loading. If a 0 char is >>> detected text-tab will be disabled. > Ups a typo - i meant "check". Ah, that makes sense now. In my experience, people generally do follow the rules and use sub_type zero for binary data and sub_type one for text. Sometimes they use something else (like -1 or 10 or whatever) to mark special kind of binary data. IMHO, we should follow the simple rule and do what is normally expected. If some users use Firebird in some way that is not "standard", it's their problem. Therefore: - if subtype is 1: text is the default tab and editing in "text" tab is enabled - if subtype is 0: binary is the default tab and editing in "text" tab is disabled Later we can extend this to try to autodetect HTML and Images (JPG, BMP, PNG, etc.) once those tabs are added. > I don't know ATM how to handle. Yes copy/pasting would be good. But the > text will be truncated if you save it back. I meant "copy" in FlameRobin and "paste" in some other application. When control is read-only you cannot paste into it anyway. > Maybe i could handle it as follows: > 1) Detect characterset of blob / database No need for this. All data FR (or any other client for that matter) receives has "connection charset" encoding. > BTW: "cache" mechanism is already implemented. If you edit text and > switch to binary the binary field will show the edited text. I see. Ok. BTW, one more thing I'd like to see is the ability to resize and maximize the dialog. -- Milan Babuskov http://www.flamerobin.org ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001On Tue, May 26, 2009 at 10:28 PM, Andreas Maier <andy1.m@...> wrote:
>> 2. when adding new files, you should add .cpp and .h file to >> flamerobin.bkl and use bakefile_gen program to regenerate the makefiles. >> We currently use Bakefile 0.2.5. >> > I've downloaded and installed bakefile 0.2.5. I will try it tomorrow. Please note that you don't have to add your BlobEditor* files now, because I already did that and re-baked all the makefiles. -- Milan Babuskov http://www.flamerobin.org ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001Milan Babuskov schrieb:
> Please note that you don't have to add your BlobEditor* files now, > because I already did that and re-baked all the makefiles. > > Thank you. ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
|
|
Re: BLOB-Editor as Dialog - Patch 001On Tue, May 26, 2009 at 11:04 PM, Milan Babuskov
<milan.babuskov@...> wrote: > Please note that you don't have to add your BlobEditor* files now, > because I already did that and re-baked all the makefiles. But it looks like I forgot to commit and Michael did that instead. Sorry about that :( -- Milan Babuskov http://www.flamerobin.org ------------------------------------------------------------------------------ Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT is a gathering of tech-side developers & brand creativity professionals. Meet the minds behind Google Creative Lab, Visual Complexity, Processing, & iPhoneDevCamp as they present alongside digital heavyweights like Barbarian Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com _______________________________________________ Flamerobin-devel mailing list Flamerobin-devel@... https://lists.sourceforge.net/lists/listinfo/flamerobin-devel |
| < Prev | 1 - 2 - 3 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |