7 messages in com.mysql.lists.gui-toolsbk commit - MyCC
FromSent OnAttachments
jor...@mysql.com16 Oct 2002 00:33 
jor...@mysql.com18 Oct 2002 03:40 
jor...@mysql.com20 Oct 2002 20:44 
jor...@mysql.com22 Oct 2002 08:18 
jor...@mysql.com23 Oct 2002 07:00 
jor...@mysql.com26 Oct 2002 08:39 
jor...@mysql.com29 Oct 2002 17:32 
Subject:bk commit - MyCC
From:jor...@mysql.com (jor@mysql.com)
Date:10/26/2002 08:39:26 AM
List:com.mysql.lists.gui-tools

Below is the list of changes that have just been commited into a local MyCC repository of 'jorge'. When 'jorge' does a push, they will be propogaged to the main repository and within 24 hours after the push into the public repository.

ChangeSet 1.107 02/10/26 10:39:45 jor@linux.jorge.mysql.com +21 -0 This push contains all the new features which will be included in 0.8.6 CNullLineEdit.h, CNullLineEdit.cpp: new file CSqlTable.cpp: Added inline insert Added inline delete Fixed a design bug in the way "generateWhereClause()" was implemented. It
returned a QString rather than a char * which made it impossible to edit binary
fields in tables which didn't have primary or unique keys. CMySQL.cpp: Added lastInsertID CUserAdminWindow.cpp: Fixed a bug which didn't parse correctly permissions with wild-cards. Fixed a bug which didn't check the "Global Privileges" item if one user only
had a "USAGE" entry. CQueryWindow.cpp: Several visual enhancements and functionality added CTableWindow.cpp: Fixed a bug which didn't allow "default NULL" nor did it parse it correctly

src/CSqlTable.cpp 1.7 02/10/26 10:37:33 jor@linux.jorge.mysql.com +1 -1

win32/MyCC.pro 1.10 02/10/26 10:07:53 jor@linux.jorge.mysql.com +3 -1

include/CNullLineEdit.h 1.1 02/10/26 10:06:27 jor@linux.jorge.mysql.com +22 -0

include/CNullLineEdit.h 1.0 02/10/26 10:06:27 jor@linux.jorge.mysql.com +0 -0 BitKeeper file /my/mycc/include/CNullLineEdit.h

include/CSqlTableItem.h 1.3 02/10/26 10:06:11 jor@linux.jorge.mysql.com +9 -18

include/CSqlTable.h 1.5 02/10/26 10:06:11 jor@linux.jorge.mysql.com +38 -8

include/config.h 1.20 02/10/26 10:06:10 jor@linux.jorge.mysql.com +1 -0

include/CQueryWindow.h 1.16 02/10/26 10:06:10 jor@linux.jorge.mysql.com +2 -1

include/CMySQLQuery.h 1.16 02/10/26 10:06:10 jor@linux.jorge.mysql.com +1 -1

include/CMySQL.h 1.2 02/10/26 10:06:10 jor@linux.jorge.mysql.com +1 -0

include/CTableWindow.h 1.14 02/10/26 10:06:08 jor@linux.jorge.mysql.com +3 -3

src/CSqlTableItem.cpp 1.3 02/10/26 10:05:54 jor@linux.jorge.mysql.com +34 -68

src/CSqlTable.cpp 1.6 02/10/26 10:04:18 jor@linux.jorge.mysql.com +500 -76 Added inline insert Added inline delete Fixed a design bug in the way "generateWhereClause()" was implemented. It
returned a QString rather than a char * which made it impossible to edit binary
fields in tables which didn't have primary or unique keys.

src/CMySQL.cpp 1.2 02/10/26 10:04:09 jor@linux.jorge.mysql.com +12 -0 Added lastInsertID

src/CUserAdminWindow.cpp 1.28 02/10/26 10:03:22 jor@linux.jorge.mysql.com +35 -2 Fixed a bug which didn't parse correctly permissions with wild-cards. Fixed a bug which didn't check the "Global Privileges" item if one user only
had a "USAGE" entry.

src/CTableSpecific.cpp 1.15 02/10/26 10:03:15 jor@linux.jorge.mysql.com +1 -0

src/CQueryWindow.cpp 1.39 02/10/26 10:03:00 jor@linux.jorge.mysql.com +75 -30 Several visual enhancements and functionality added

src/CMySQLQuery.cpp 1.28 02/10/26 10:02:54 jor@linux.jorge.mysql.com +0 -1

src/CCreditsBox.cpp 1.12 02/10/26 10:02:50 jor@linux.jorge.mysql.com +3 -1

src/CTableWindow.cpp 1.21 02/10/26 10:02:22 jor@linux.jorge.mysql.com +29 -10 Fixed a bug which didn't allow "default NULL" nor did it parse it correctly

src/CNullLineEdit.cpp 1.1 02/10/26 10:02:18 jor@linux.jorge.mysql.com +39 -0

src/CNullLineEdit.cpp 1.0 02/10/26 10:02:18 jor@linux.jorge.mysql.com +0 -0 BitKeeper file /my/mycc/src/CNullLineEdit.cpp

dist/Changelog.txt 1.46 02/10/26 10:01:29 jor@linux.jorge.mysql.com +21 -5

dist/TODO.txt 1.24 02/10/26 10:01:27 jor@linux.jorge.mysql.com +1 -7

# This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: jorge # Host: linux.jorge.mysql.com # Root: /my/mycc

--- 1.1/include/CMySQL.h Wed Oct 16 02:24:45 2002 +++ 1.2/include/CMySQL.h Sat Oct 26 10:06:10 2002 @@ -94,6 +94,7 @@ QString mysqlGetCharsetName() const; ulong mysqlRealEscapeString(const char *from, char *to, uint from_length); ulong mysqlAffectedRows() const; + ulong mysqlInsertID() const; bool mysqlSelectDb(const QString & dbname);

friend class CMySQLQuery; --- New file --- +++ include/CNullLineEdit.h 02/10/26 10:06:27 #ifndef CNULLLINEEDIT_H #define CNULLLINEEDIT_H

#include <qlineedit.h>

class QKeyEvent;

class CNullLineEdit : public QLineEdit { Q_OBJECT public: CNullLineEdit(QWidget * parent, const char * name = 0); bool isNull() const { return is_null; } void setNull(bool b);

private: void keyPressEvent(QKeyEvent * e); bool is_null; int last_key; };

#endif

--- 1.4/include/CSqlTable.h Wed Oct 23 08:58:35 2002 +++ 1.5/include/CSqlTable.h Sat Oct 26 10:06:11 2002 @@ -6,7 +6,7 @@

class CMySQLQuery; class CSqlTableItem; -class CSqlTableItemEditor; +class CNullLineEdit; class CMessagePanel; class QLineEdit; class CHistoryPanel; @@ -20,10 +20,11 @@ bool isReadOnly() const { return is_read_only; } void setHistoryPanel(CHistoryPanel *h) { historyPanel = h; } void addToHistoryPanel(bool b) { add_to_history = b; } - void displayMessages(bool b) { display_messages = b; } + void displayMessages(bool b) { display_messages = b; }

signals: - void progress(); + void progress(int); + void canDelete(bool);

public slots: void refresh(); @@ -33,11 +34,13 @@ void setTableName(const QString &tbl_name) { table_name = tbl_name; } bool exec(const char *, ulong); void copy(int row, int col); + void insertRecord(int row=-1); + void deleteRecord();

protected: void endEdit(int row, int col, bool accept, bool replace); QWidget * beginEdit(int row, int col, bool replace); - QWidget *createEditor(int row, int col, bool initFromCell) const; + QWidget * createEditor(int row, int col, bool initFromCell) const;

protected slots: void ContextMenuRequested(int row, int col, const QPoint &pos); @@ -47,24 +50,51 @@

private slots: void saveCellToFile(CSqlTableItem *table_item); - void loadFromFile(CSqlTableItem *current_item); - void textEditorContentsChanged(const QString &/*value*/, ulong /*length*/,
CSqlTableItem * /*table_item*/); + + void doLoadFromFile(CSqlTableItem *current_item); + void doUpdateFromTextEditor(const QString &/*value*/, ulong /*length*/,
CSqlTableItem * /*table_item*/); + bool doUpdateRecord(CNullLineEdit *editor, CSqlTableItem *current_item); + void doInsertRecord(int row); + void currentChanged(int, int);

private: + class CDefaultFieldSpecs + { + public: + CDefaultFieldSpecs() + { + default_value = QString::null; + is_null = false; + auto_increment = false; + } + + CDefaultFieldSpecs(const QString &def, bool n, bool a) + : default_value(def), is_null(n), auto_increment(a) + { + } + + QString default_value; + bool is_null; + bool auto_increment; + }; enum update_Type { PRIMARY, UNIQUE, ALL_FIELDS }; CMessagePanel *messagePanel; CHistoryPanel *historyPanel; - int maxColumnLength(uint col) const; - bool itemModified(CSqlTableItemEditor *editor, CSqlTableItem *current_item); + int maxColumnLength(uint col) const; char * getUpdateQuery(const char *new_value, ulong len, CSqlTableItem
*current_item, ulong *length); + char * getInsertQuery(int row, ulong *length); char * getWhereClause(int row, ulong *length); + char * getDeleteQuery(CSqlTableItem *current_item, ulong *length); update_Type update_type; QMap<uint, QString> update_columns; + QMap<uint, CDefaultFieldSpecs> default_fields_map; bool is_read_only; bool add_to_history; bool display_messages; + int inserting_row; QString database_name; QString table_name; + bool force_insert; };

#endif

--- 1.2/include/CSqlTableItem.h Fri Oct 18 05:39:15 2002 +++ 1.3/include/CSqlTableItem.h Sat Oct 26 10:06:11 2002 @@ -2,38 +2,25 @@ #define CQUERYTABLEITEM_H

#include <qtable.h> -#include <qlineedit.h>

class CMySQLQuery; -class QKeyEvent; -class QCString;

#define MAX_FIELD_DISPLAY 384

-class CSqlTableItemEditor : public QLineEdit -{ - Q_OBJECT -public: - CSqlTableItemEditor(QWidget * parent, const char * name = 0); - bool isNull() const { return is_null; } - void setNull(bool b); - -private: - void keyPressEvent(QKeyEvent * e); - bool is_null; - int last_key; -}; - class CSqlTableItem : public QTableItem { public: CSqlTableItem (QTable * table, CMySQLQuery *q, ulong off_set, uint idx,
EditType et=OnTyping); + CSqlTableItem (QTable * table, CMySQLQuery *q, uint idx, EditType
et=OnTyping); + ~CSqlTableItem(); bool isBinary() { return is_binary; } bool isNumber() { return is_number; } bool isNull() { return is_null; } bool isBlob() { return is_blob; } - bool isBigValuet() { return is_big_value; } + bool isBigValue() { return is_big_value; } + bool isNewRecord() { return is_new_record; } + bool isItemInserted() { return is_item_inserted; }

ulong offset() const { return m_offset; } uint index() const { return m_index; } @@ -42,6 +29,7 @@ void setLength(ulong len) { field_length = len; } void setNull(bool b); void setValue(const char *, ulong len); + void setItemInserted(bool b) { is_item_inserted = b; } char * value() const;

CMySQLQuery *query() const { return qry; }; @@ -56,6 +44,7 @@ virtual QString checkValue(const QString &str);

private: + void init(); CMySQLQuery *qry; ulong m_offset; uint m_index; @@ -66,6 +55,8 @@ bool is_null; bool is_number; bool is_blob; + bool is_new_record; + bool is_item_inserted; };

#endif

--- 1.13/include/CTableWindow.h Sun Oct 20 20:54:14 2002 +++ 1.14/include/CTableWindow.h Sat Oct 26 10:06:08 2002 @@ -28,7 +28,7 @@ class QRadioButton; class QButtonGroup; class CMySQL; - +class CNullLineEdit;

class CTableWindowField { @@ -36,7 +36,7 @@ CTableWindowField() { Type = QString::null; - Default = QString::null; + Default = ""; Value = QString::null; FieldName = QString::null; Length = QString::null; @@ -319,7 +319,7 @@ QLabel* TextLabel1; QLabel* TextLabel2; QLabel* TextLabel3; - QLineEdit* Default; + CNullLineEdit* Default; QLineEdit* Value; QLineEdit* Length; QCheckBox* Unsigned;

--- 1.1/src/CMySQL.cpp Wed Oct 16 02:23:44 2002 +++ 1.2/src/CMySQL.cpp Sat Oct 26 10:04:09 2002 @@ -233,6 +233,18 @@ }

/* +mysqlInsertID() is a wrapper for mysql_insert_id(). See the MySQL API
documentation for further information. +*/ +ulong CMySQL::mysqlInsertID() const +{ + if (!isConnected()) + return 0; + else + return mysql_insert_id(mysql); +} + + +/* mysqlSelectDb() is a wrapper for mysql_select_db(). See the MySQL API
documentation for further information. */ bool CMySQL::mysqlSelectDb(const QString & dbname) --- New file --- +++ src/CNullLineEdit.cpp 02/10/26 10:02:18 #include "CNullLineEdit.h" #include <qevent.h>

CNullLineEdit::CNullLineEdit(QWidget * parent, const char * name) : QLineEdit(parent, name), is_null(false) { if (!name) setName("CNullLineEdit"); last_key = 0; }

void CNullLineEdit::setNull(bool b) { is_null = b; if (b && text() != "[NULL]") setText("[NULL]"); }

void CNullLineEdit::keyPressEvent(QKeyEvent * e) { if (last_key == Qt::Key_Control && e->key() == Qt::Key_0 && !isNull()) { setNull(true); last_key = 0; e->ignore(); return; } else { if (e->key() != Qt::Key_Control && isNull()) { setText(QString::null); setNull(false); } last_key = e->key(); QLineEdit::keyPressEvent(e); } }

--- 1.5/src/CSqlTable.cpp Wed Oct 23 08:57:41 2002 +++ 1.7/src/CSqlTable.cpp Sat Oct 26 10:37:33 2002 @@ -8,6 +8,7 @@ #include "config.h" #include "globals.h" #include "panels.h" +#include "CNullLineEdit.h" #include <qfile.h> #include <qdatetime.h> #include <qlineedit.h> @@ -33,6 +34,9 @@ table_name = QString::null; messagePanel = m->messagePanel(); historyPanel = 0; + connect(this, SIGNAL(currentChanged(int, int)), this,
SLOT(currentChanged(int, int))); + inserting_row = -1; + force_insert = false; }

QWidget *CSqlTable::createEditor(int row, int col, bool initFromCell) const @@ -44,14 +48,14 @@ if (isReadOnly() || isRowReadOnly(row) || isColumnReadOnly(col)) return 0;

- CSqlTableItemEditor *e = 0; + CNullLineEdit *e = 0;

CSqlTableItem *i = (CSqlTableItem *) item(row, col); if (initFromCell || i && !i->isReplaceable()) { if (i) { - e = (CSqlTableItemEditor *) i->createEditor(); + e = (CNullLineEdit *) i->createEditor(); e->setMaxLength(maxColumnLength(col)); if (i->isNull()) e->setNull(true); @@ -62,7 +66,7 @@

if (!e) { - e = new CSqlTableItemEditor(viewport(), "CSqlTableItemEditor"); + e = new CNullLineEdit(viewport(), "CNullLineEdit"); if (i->isNull()) e->setNull(true); e->setMaxLength(maxColumnLength(col)); @@ -86,7 +90,7 @@ if (itm && cellWidget(itm->row(), itm->col())) return 0; ensureCellVisible(row, col); - CSqlTableItemEditor *e = (CSqlTableItemEditor *) createEditor(row, col,
!replace); + CNullLineEdit *e = (CNullLineEdit *) createEditor(row, col, !replace); if (!e) return 0;

@@ -104,7 +108,7 @@ qDebug("CSqlTable::endEdit(int, int, bool, bool)"); #endif

- CSqlTableItemEditor *editor = (CSqlTableItemEditor *) cellWidget(row, col); + CNullLineEdit *editor = (CNullLineEdit *) cellWidget(row, col); if (!editor) return; editor->setMaxLength(maxColumnLength(col)); @@ -121,12 +125,19 @@ }

CSqlTableItem *i = (CSqlTableItem *) item(row, col); - + bool edit_ok = false; - if (text(row, col) != editor->text() || i->isNull() != editor->isNull()) + QString txt = text(row, col); + bool text_different = false; + if (txt != editor->text() && !(i->isNull() || editor->isNull()) ) + { + if (!(txt.isEmpty() && editor->text().isEmpty())) + text_different = true; + } + + if (text_different || i->isNull() != editor->isNull()) { - edit_ok = itemModified(editor, i); - if (edit_ok) + if (edit_ok = doUpdateRecord(editor, i)) i->setContentFromEditor(editor); }

@@ -147,13 +158,18 @@ viewport()->setFocus(); updateCell(row, col);

- emit valueChanged(row, col); + if (i->isNewRecord() && !i->isItemInserted()) + doInsertRecord(row);

clearCellWidget(row, col); }

bool CSqlTable::exec(const char *sql, ulong length) { +#ifdef DEBUG + qDebug("CSqlTable::exec()"); +#endif + CMySQLQuery *qry = new CMySQLQuery(mysql()->mysql()); qry->setEmitMessages(display_messages); bool b = qry->execRealStaticQuery(sql, length); @@ -164,37 +180,233 @@ return true; }

-bool CSqlTable::itemModified(CSqlTableItemEditor *editor, CSqlTableItem
*current_item) +bool CSqlTable::doUpdateRecord(CNullLineEdit *editor, CSqlTableItem *field) { - ulong query_length; - const char *value = editor->isNull() ? 0 : editor->text().latin1(); - char *sql = getUpdateQuery(value, value ? strlen(value) : 0, current_item,
&query_length); - bool b = exec(sql, query_length); +#ifdef DEBUG + qDebug("CSqlTable::doUpdateRecord()"); +#endif + + if (isBlocked()) + return false; + + setBlocked(true); + bool b = false; + if (!field->isNewRecord() || (field->isNewRecord() &&
field->isItemInserted())) + { + const char *value = editor->isNull() ? 0 : editor->text().latin1(); + ulong query_length; + char *sql = getUpdateQuery(value, value ? strlen(value) : 0, field,
&query_length); + b = exec(sql, query_length); + delete [] sql; + } + else //Item hasn't been inserted into the database + b = true; + if (b) { if (editor->isNull()) - current_item->setNull(true); + field->setNull(true); else - current_item->setValue(editor->text(), editor->text().length()); + field->setValue(editor->text(), editor->text().length()); } - delete [] sql; + setBlocked(false); + return b; }

-void CSqlTable::textEditorContentsChanged(const QString &v, ulong l,
CSqlTableItem *table_item) + +void CSqlTable::doInsertRecord(int row) +{ +#ifdef DEBUG + qDebug("CSqlTable::doInsertRecord()"); +#endif + + if (isBlocked()) + return; + + setBlocked(true); + if ((inserting_row != -1 && row != inserting_row) || force_insert) + { + ulong query_length; + char *sql = getInsertQuery(inserting_row, &query_length); + bool b = exec(sql, query_length); + delete [] sql; + if (b) + { + CSqlTableItem *field; + for (uint i = 0; i < query()->numFields(); i++) + { + field = (CSqlTableItem *) item(inserting_row, i); + field->setItemInserted(true); + if (default_fields_map[i].auto_increment) + { + ulong auto_inc = mysql()->mysql()->mysqlInsertID(); + if (auto_inc != 0) + { + QString a = QString::number(auto_inc); + field->setValue(a, a.length()); + field->setTextFromValue(); + } + } + } + inserting_row = -1; + force_insert = false; + } + } + setBlocked(false); +} + +void CSqlTable::insertRecord(int r) { - ulong query_length; - char *sql = getUpdateQuery(v.latin1(), l, table_item, &query_length); - if (exec(sql, query_length)) +#ifdef DEBUG + qDebug("CSqlTable::insertRecord()"); +#endif + + if (!isVisible() || isReadOnly()) + return; + + if (isBlocked()) + return; + + setBlocked(true); + + if (inserting_row != -1) + { + removeRow(inserting_row); + inserting_row = -1; + } + int row = r == -1 ? currentRow() : r; + if (row < 0) + row = 0; + + insertRows(row); + + CDefaultFieldSpecs field_info; + for (uint i = 0; i < query()->numFields(); i++) + { + CSqlTableItem *item = new CSqlTableItem(this, query(), i); + if (!default_fields_map.empty()) + { + field_info = default_fields_map[i]; + if ((field_info.is_null || field_info.auto_increment) &&
field_info.default_value.isEmpty()) + item->setValue(0, 0); + else + item->setValue(field_info.default_value,
field_info.default_value.length()); + } + else + item->setValue(0, 0); + item->setTextFromValue(); + setItem(row, i, item); + } + ensureCellVisible(row, 0); + setCurrentCell(row, 0); + inserting_row = row; + emit canDelete(true); + force_insert = (numRows() == 1); + setBlocked(false); +} + +void CSqlTable::deleteRecord() +{ +#ifdef DEBUG + qDebug("CSqlTable::deleteRecord()"); +#endif + + if (!isVisible() || isReadOnly() || numRows() < 1) + return; + + if (isBlocked()) + return; + + setBlocked(true); + if (myApp()->confirmCritical()) + if ((QMessageBox::information(0, tr("Confirm Delete"), tr("Are you sure you
want to Delete the selected records ?"), + QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)) + return; + + QMemArray<int> delete_rows(0); + CSqlTableItem *field; + int cnt = 0; + bool ok; + for (int i = 0; i < numRows(); i++) + { + if (isRowSelected(i)) + { + field = (CSqlTableItem *) item(i, 0); + ok = false; + if (!field->isNewRecord() || (field->isNewRecord() &&
field->isItemInserted())) + { + ulong sql_length; + char *sql = getDeleteQuery(field, &sql_length); + ok = exec(sql, sql_length); + delete [] sql; + } + else + ok = true; + if (ok) + { + if (field->isNewRecord() && !field->isItemInserted() && inserting_row
== i) + { + force_insert = false; + inserting_row = -1; + } + delete_rows.resize(++cnt); + delete_rows[cnt - 1] = i; + } + } + } + + if (!delete_rows.isEmpty()) + removeRows(delete_rows); + setBlocked(false); +} + +void CSqlTable::doUpdateFromTextEditor(const QString &v, ulong l, CSqlTableItem
*table_item) +{ +#ifdef DEBUG + qDebug("CSqlTable::doUpdateFromTextEditor()"); +#endif + + if (isBlocked()) + return; + + setBlocked(true); + bool ok = false; + if (!table_item->isNewRecord() || (table_item->isNewRecord() &&
table_item->isItemInserted())) + { + ulong query_length; + char *sql = getUpdateQuery(v.latin1(), l, table_item, &query_length); + if (exec(sql, query_length)) + ok = true; + delete [] sql; + } + else + ok = true; + + setBlocked(false); + if (ok) { table_item->setValue(v, l); table_item->setTextFromValue(); + if (table_item->isNewRecord() && !table_item->isItemInserted()) + { + force_insert = true; + doInsertRecord(table_item->row()); + } } - delete [] sql; }

-void CSqlTable::loadFromFile(CSqlTableItem *current_item) +void CSqlTable::doLoadFromFile(CSqlTableItem *field) { +#ifdef DEBUG + qDebug("CSqlTable::doLoadFromFile()"); +#endif + + if (isBlocked()) + return; + + setBlocked(true); + bool unblocked = false; QString s = QFileDialog::getOpenFileName(QString::null, tr("All Files(*.*)"),
0, tr("Load from File"), tr("Choose a file")); if (!s.isNull()) { @@ -210,38 +422,136 @@ QFileInfo fi(s); ulong len = fi.size(); char *data; - if (data = new char [len +1]) + if ((data = new char [len +1])) { ts.readRawBytes(data, len); data[len] = 0; - ulong query_length; - char *sql = getUpdateQuery(data, len, current_item, &query_length); - - bool a = add_to_history; - add_to_history = false; //Don't add the query to the history file + bool ok = false; + if (!field->isNewRecord() || (field->isNewRecord() &&
field->isItemInserted())) + { + ulong query_length; + char *sql = getUpdateQuery(data, len, field, &query_length); + + bool a = add_to_history; + add_to_history = false; //Don't add the query to the history file + + if (exec(sql, query_length)) + ok = true; + add_to_history = a; //restore the original "Add to History"
settings. + delete [] sql; + } + else + ok = true;

- if (exec(sql, query_length)) + if (ok) { - current_item->setValue(data, len); - current_item->setTextFromValue(); + field->setValue(data, len); + field->setTextFromValue(); + if (field->isNewRecord() && !field->isItemInserted()) + { + setBlocked(false); + unblocked = true; + force_insert = true; + doInsertRecord(field->row()); + } } - delete [] sql; + delete [] data; - add_to_history = a; //restore the original "Add to History" settings. } else mysql()->showMessage(CRITICAL, tr("There is not enough memory to open
the file")); file.close(); } } + if (!unblocked) + setBlocked(false); +} + +char * CSqlTable::getInsertQuery(int row, ulong *length) +{ +#ifdef DEBUG + qDebug("CSqlTable::getInsertQuery()"); +#endif + + QString s = "INSERT INTO " + mysql()->mysql()->quote(table_name) + "\n ("; + uint i; + ulong len = 0; + CSqlTableItem *field; + for (i = 0; i < query()->numFields(); i++) + { + s += mysql()->mysql()->quote(query()->fields(i).name); + field = (CSqlTableItem *) item(row, i); + + if (field->isNull()) + len += 4; + else + if (field->isNumber()) + len += field->length() + 2; + else + len += field->length() * 2 + 3; + + if (i < query()->numFields() - 1) + { + s += ", "; + len += 2; + } + } + s += ")\nVALUES ("; + + len+=s.length() + 2; + + char *insert = new char[len + 1]; + char *end = insert; + end = strmov(end, s.latin1()); + + for (i = 0; i < query()->numFields(); i++) + { + field = (CSqlTableItem *) item(row, i); + if (field->isNull()) + end = strmov(end, "NULL"); + else + if (field->isNumber()) + { + *end++ = '\''; + memcpy(end, field->value(), field->length()); + end += field->length(); + *end++ = '\''; + } + else + { + char * value = new char[field->length() * 2 + 3]; + char *v = value; + *v++ = '\''; + ulong value_length =
mysql()->mysql()->mysqlRealEscapeString(field->value(), v, field->length()); + v += value_length; + *v++ = '\''; + value_length += 2; + memcpy(end, value, value_length); + end += value_length; + delete [] value; + } + + if (i < query()->numFields() - 1) + { + *end++ = ','; + *end++ = ' '; + } + } + *end++ = ')'; + *end = 0; + *length = end - insert; + return insert; }

-char * CSqlTable::getUpdateQuery(const char *new_value, ulong len,
CSqlTableItem *current_item, ulong *length) +char * CSqlTable::getUpdateQuery(const char *new_value, ulong len,
CSqlTableItem *field, ulong *length) { +#ifdef DEBUG + qDebug("CSqlTable::getUpdateQuery()"); +#endif + QString s = "UPDATE " + mysql()->mysql()->quote(table_name) + "\nSET " + - mysql()->mysql()->quote(query()->fields(current_item->index()).name) + "="; + mysql()->mysql()->quote(query()->fields(field->index()).name) + "=";

- ulong l = s.length() + 1; char *value; char *v = 0; ulong value_length = 0; @@ -254,7 +564,7 @@ } else { - if (current_item->isNumber()) + if (field->isNumber()) { value_length = len + 2; value = new char[len + 3]; @@ -275,25 +585,49 @@ } }

- l += value_length + 1; ulong where_length; - char *where = getWhereClause(current_item->row(), &where_length); - l += where_length + 1; - char *sql = new char[l]; - char *q = sql; - q = strmov(q, s.latin1()); - memcpy(q, value, value_length); - q += value_length; - memcpy(q, where, where_length); - *(q + where_length) = 0; - *length = l; - delete [] value; + char *where = getWhereClause(field->row(), &where_length); + char *sql = new char[s.length() + where_length + value_length + 1]; + char *end = sql; + end = strmov(end, s.latin1()); + memcpy(end, value, value_length); + end += value_length; + delete [] value; + memcpy(end, where, where_length); delete [] where; + end += where_length; + *end = 0; + *length = end - sql; return sql; }

+char * CSqlTable::getDeleteQuery(CSqlTableItem *field, ulong *length) +{ +#ifdef DEBUG + qDebug("CSqlTable::getDeleteQuery()"); +#endif + + QString s = "DELETE FROM " + mysql()->mysql()->quote(table_name); + ulong where_length; + char *where = getWhereClause(field->row(), &where_length); + char *delete_sql = new char[s.length() + where_length + 1]; + char *end = delete_sql; + memcpy(end, s.latin1(), s.length()); + end += s.length(); + memcpy(end, where, where_length); + end += where_length; + delete [] where; + *end = 0; + *length = end - delete_sql; + return delete_sql; +} + char * CSqlTable::getWhereClause(int row, ulong *length) -{ +{ +#ifdef DEBUG + qDebug("CSqlTable::getWhereClause()"); +#endif + ulong len_tmp = 0; CSqlTableItem *field; QMap<uint, QString>::Iterator it; @@ -370,16 +704,20 @@ *length = end_ptr - where; return where; } - - + void CSqlTable::refresh() { +#ifdef DEBUG + qDebug("CSqlTable::refresh()"); +#endif + if (isBlocked()) return; reset(); setCaption(realParent()->caption()); m_cancel = false; update_columns.clear(); + default_fields_map.clear(); bool is_pk = false; bool is_unique = false; if (!query()->isResultNull()) @@ -395,19 +733,16 @@ for (uint j = 0; j < num_fields; j++) { if (IS_PRI_KEY(query()->fields(j).flags)) + { is_pk = true; + break; + } else if (!is_pk && IS_UNI_KEY(query()->fields(j).flags)) is_unique = true; }

- if (is_pk) - update_type = PRIMARY; - else - if (is_unique) - update_type = UNIQUE; - else - update_type = ALL_FIELDS; + update_type = is_pk ? PRIMARY : is_unique ? UNIQUE : ALL_FIELDS;

for (uint i = 0; i < num_fields; i++) { @@ -417,12 +752,6 @@ if (update_type == PRIMARY) update_columns.insert(i,
mysql()->mysql()->quote(query()->fields(i).name)); } - else if (IS_MUL_KEY(query()->fields(i).flags)) - { - icon = mulIcon; - if (update_type == ALL_FIELDS) - update_columns.insert(i,
mysql()->mysql()->quote(query()->fields(i).name)); - } else if (IS_UNI_KEY(query()->fields(i).flags)) { icon = uniIcon; @@ -431,7 +760,7 @@ } else { - icon = nothingIcon; + icon = IS_MUL_KEY(query()->fields(i).flags) ? mulIcon : nothingIcon; if (update_type == ALL_FIELDS) update_columns.insert(i,
mysql()->mysql()->quote(query()->fields(i).name)); } @@ -451,17 +780,26 @@ } } qApp->processEvents(); - + int current_p; + int last_p=0; ulong z = 0; + int tmp_num_rows = num_rows > 0 ? num_rows : 1; while (query()->next()) { if (m_cancel) break; for (uint i = 0; i < num_fields; i++) setItem(z, i, new CSqlTableItem(this, query(), z, i)); - emit progress(); + + current_p = ((uint) (z * 100 / tmp_num_rows)); + if (current_p % 5 == 0 && current_p != last_p) + { + last_p = current_p; + emit progress(current_p); + } z++; } + emit progress(100); setBlocked(false); emit refreshed(); } @@ -469,15 +807,23 @@

void CSqlTable::openTextEditor(CSqlTableItem *table_item) { +#ifdef DEBUG + qDebug("CSqlTable::openTextEditor()"); +#endif + CTextFieldEditor *t = new CTextFieldEditor(table_item, isReadOnly()); connect(this, SIGNAL(about_to_close()), t, SLOT(close())); connect(t, SIGNAL(message(ushort, const QString &)), mysql()->messagePanel(),
SLOT(message(ushort, const QString &))); - connect(t, SIGNAL(contentsChanged(const QString &, ulong, CSqlTableItem *)),
this, SLOT(textEditorContentsChanged(const QString &, ulong, CSqlTableItem *))); + connect(t, SIGNAL(contentsChanged(const QString &, ulong, CSqlTableItem *)),
this, SLOT(doUpdateFromTextEditor(const QString &, ulong, CSqlTableItem *))); myShowWindow(t); }

void CSqlTable::openImageViewer(CSqlTableItem *table_item) { +#ifdef DEBUG + qDebug("CSqlTable::openImageViewer()"); +#endif + CImageViewer *t = new CImageViewer(table_item, true); //TODO .. Need to
change this connect(this, SIGNAL(about_to_close()), t, SLOT(close())); connect(t, SIGNAL(message(ushort, const QString &)), mysql()->messagePanel(),
SLOT(message(ushort, const QString &))); @@ -486,6 +832,10 @@

void CSqlTable::DoubleClicked(int row, int col, int button, const QPoint &) { +#ifdef DEBUG + qDebug("CSqlTable::DoubleClicked()"); +#endif + if (button == Qt::LeftButton) { switch (query()->fields(col).type) @@ -514,10 +864,26 @@

void CSqlTable::ContextMenuRequested(int row, int col, const QPoint &pos) { +#ifdef DEBUG + qDebug("CSqlTable::ContextMenuRequested()"); +#endif + if (isBlocked()) return;

+ int num_cols = numCols(); + int num_rows = numRows(); + QPopupMenu *menu = new QPopupMenu(); + + menu->insertItem(getPixmapIcon("insertRowIcon"), tr("&Insert Record"),
MENU_INSERT); + menu->setItemEnabled (MENU_INSERT, !isReadOnly()); + + menu->insertItem(getPixmapIcon("deleteRowIcon"), tr("&Delete Record"),
MENU_DELETE); + menu->setItemEnabled (MENU_DELETE, !isReadOnly() && num_rows > 0 && num_cols
> 0); + + menu->insertSeparator(); + QPopupMenu *open_menu = new QPopupMenu();

CSqlTableItem *table_item = (CSqlTableItem *) item(currentRow(),
currentColumn()); @@ -544,16 +910,16 @@ menu->insertSeparator();

menu->insertItem(getPixmapIcon("copyIcon"), tr("&Copy"), MENU_COPY); - menu->setItemEnabled(MENU_COPY, numCols() > 0 && numRows() > 0); + menu->setItemEnabled(MENU_COPY, num_cols > 0 && num_rows > 0);

menu->insertSeparator(); menu->insertItem(getPixmapIcon("saveGridResultsIcon"), tr("Save &Results"),
MENU_SAVE); - menu->setItemEnabled(MENU_SAVE, numCols() > 0); + menu->setItemEnabled(MENU_SAVE, num_cols > 0);

menu->insertSeparator();

menu->insertItem(getPixmapIcon("clearGridIcon"), tr("C&lear Grid"),
MENU_CLEAR_GRID); - menu->setItemEnabled(MENU_CLEAR_GRID, numCols() > 0); + menu->setItemEnabled(MENU_CLEAR_GRID, num_cols > 0);

int res = menu->exec(pos); delete open_menu; @@ -561,6 +927,14 @@

switch (res) { + case MENU_INSERT: + insertRecord(row); + break; + + case MENU_DELETE: + deleteRecord(); + break; + case MENU_OPEN_TEXT: openTextEditor(table_item); break; @@ -578,7 +952,7 @@ break;

case MENU_LOAD: - loadFromFile(table_item); + doLoadFromFile(table_item); break;

case MENU_SAVE: @@ -594,7 +968,10 @@ void CSqlTable::copy(int row, int col) { #ifndef QT_NO_CLIPBOARD - +#ifdef DEBUG + qDebug("CSqlTable::copy()"); +#endif + CSqlTableItem *field; if (currentSelection() == -1) { @@ -646,6 +1023,10 @@

void CSqlTable::saveCellToFile(CSqlTableItem *table_item) { +#ifdef DEBUG + qDebug("CSqlTable::saveCellToFile()"); +#endif + if (table_item == 0) return ; QString tmp, ext = QString::null; @@ -661,17 +1042,29 @@

void CSqlTable::reset() { +#ifdef DEBUG + qDebug("CSqlTable::reset()"); +#endif + CQueryTable::reset(); database_name = QString::null; table_name = QString::null; + force_insert = false; + inserting_row = -1; setReadOnly(true); }

void CSqlTable::setReadOnly(bool b) { +#ifdef DEBUG + qDebug("CSqlTable::setReadOnly()"); +#endif + is_read_only = b; bool ro = true; + default_fields_map.clear(); if (query()) + { if (!b && !query()->isResultNull() && query()->numFields() > 0) { ro = false; @@ -690,16 +1083,47 @@ break; } } + + if (!table_name.isEmpty()) + { + CMySQLQuery *qry = new CMySQLQuery(mysql()->mysql()); + qry->setEmitMessages(false); + uint i = 0; + if (qry->exec("SHOW FIELDS FROM " +
mysql()->mysql()->quote(table_name))) + while (qry->next()) + { + CDefaultFieldSpecs field; + field.default_value = qry->row(4); + field.is_null = !QString(qry->row(2)).isEmpty(); + field.auto_increment = !QString(qry->row(5)).isEmpty(); + default_fields_map[i] = field; + i++; + } + delete qry; + } } - + } CQueryTable::setReadOnly(ro); }

int CSqlTable::maxColumnLength(uint col) const { +#ifdef DEBUG + qDebug("CSqlTable::maxColumnLength()"); +#endif + uint max = query()->fields(col).length; if (max > MAX_FIELD_DISPLAY) max = MAX_FIELD_DISPLAY; return max; }

+void CSqlTable::currentChanged(int row, int) +{ +#ifdef DEBUG + qDebug("CSqlTable::currentChanged()"); +#endif + + if ((inserting_row != -1 && row != inserting_row) || force_insert) + doInsertRecord(row); +}

--- 1.2/src/CSqlTableItem.cpp Fri Oct 18 05:37:54 2002 +++ 1.3/src/CSqlTableItem.cpp Sat Oct 26 10:05:54 2002 @@ -1,84 +1,57 @@ #include "CSqlTableItem.h" #include "CMySQLQuery.h" -#include <qevent.h> -#include <qpalette.h> +#include "CNullLineEdit.h"

#include "globals.h" //for debugging #include "config.h" //for debugging

-CSqlTableItemEditor::CSqlTableItemEditor(QWidget * parent, const char * name) -: QLineEdit(parent, name), is_null(false) -{ -#ifdef DEBUG - qDebug("CSqlTableItemEditor::CSqlTableItemEditor(QWidget *, const char *)"); -#endif - - if (!name) - setName("CSqlTableItemEditor"); - last_key = 0; -} - -void CSqlTableItemEditor::setNull(bool b) +CSqlTableItem::CSqlTableItem(QTable * table, CMySQLQuery *q, ulong off_set,
uint idx, EditType et) +: QTableItem(table, et, QString::null), qry(q), m_offset(off_set), m_index(idx) { #ifdef DEBUG - qDebug("CSqlTableItemEditor::setNull(%s)", debug_string(booltostr(b))); + qDebug("CSqlTableItem::CSqlTableItem(QTable *, CMySQLQuery *, ulong, uint,
EditType)"); #endif

- is_null = b; - if (b && text() != "[NULL]") - setText("[NULL]"); -} - -void CSqlTableItemEditor::keyPressEvent(QKeyEvent * e) -{ -#ifdef DEBUG - qDebug("CSqlTableItemEditor::keyPressEvent(%d) - isNull: %s", e->key(),
debug_string(booltostr(isNull()))); -#endif + init(); + is_item_inserted = true; + is_null = !query()->row(index()); + is_new_record = false; + field_length = query()->fieldLength(index());

- if (last_key == Qt::Key_Control && e->key() == Qt::Key_0 && !isNull()) + if (!is_null) { - setNull(true); - last_key = 0; - e->ignore(); - return; + m_value = new char [field_length + 1]; + memcpy(m_value, query()->row(index()), field_length + 1); + setTextFromValue(); } else { - if (e->key() != Qt::Key_Control && isNull()) - { -#ifdef DEBUG - qDebug("CSqlTableItemEditor::keyPressEvent(QKeyEvent *) - e->key() !=
Qt::Key_Control && isNull()"); -#endif - - setText(QString::null); - setNull(false); - } - last_key = e->key(); - QLineEdit::keyPressEvent(e); - } + m_value = 0; + setText("[NULL]"); + } }

-CSqlTableItem::CSqlTableItem(QTable * table, CMySQLQuery *q, ulong off_set,
uint idx, EditType et) -: QTableItem(table, et, QString::null), qry(q), m_offset(off_set), m_index(idx) +CSqlTableItem::CSqlTableItem(QTable * table, CMySQLQuery *q, uint idx, EditType
et) +: QTableItem(table, et, QString::null), qry(q), m_index(idx) { #ifdef DEBUG - qDebug("CSqlTableItem::CSqlTableItem(QTable *, CMySQLQuery *, ulong, uint,
EditType)"); + qDebug("CSqlTableItem::CSqlTableItem(QTable *, CMySQLQuery *, uint,
EditType)"); #endif

+ init(); + m_value = 0; + is_item_inserted = false; + is_new_record = true; + is_null = true; + field_length = 0; +} + +void CSqlTableItem::init() +{ setWordWrap(true); - flags = query()->fields(index()).flags; - is_null = !query()->row(index()); + flags = query()->fields(index()).flags; is_number = flags & NUM_FLAG; - is_binary = IS_BINARY_FIELD(flags); - field_length = query()->fieldLength(index()); - if (!is_null) - { - m_value = new char [field_length + 1]; - memcpy(m_value, query()->row(index()), field_length + 1); - } - else - m_value = 0; - + is_binary = IS_BINARY_FIELD(flags); switch (query()->fields(index()).type) { case FIELD_TYPE_TINY_BLOB: @@ -90,12 +63,7 @@ default: is_blob = false; break; - } - - if (is_null) - setText("[NULL]"); - else - setTextFromValue(); + } }

CSqlTableItem::~CSqlTableItem() @@ -136,10 +104,7 @@ void CSqlTableItem::setTextFromValue() { if (isNull()) - { setText("[NULL]"); - return; - } else if (length() <= MAX_FIELD_DISPLAY && !is_blob) { @@ -161,6 +126,7 @@ QTableItem::setText(str); delete [] str; } + table()->updateCell(row(), col()); }

QString CSqlTableItem::checkValue(const QString &str) @@ -198,7 +164,7 @@ qDebug("CSqlTableItem::createEditor()"); #endif

- CSqlTableItemEditor *e = new CSqlTableItemEditor(table()->viewport(),
"CSqlTableItemEditor"); + CNullLineEdit *e = new CNullLineEdit(table()->viewport()); e->setFrame(false); e->setText(text()); return e;

--- 1.20/src/CTableWindow.cpp Sun Oct 20 20:53:34 2002 +++ 1.21/src/CTableWindow.cpp Sat Oct 26 10:02:22 2002 @@ -7,6 +7,7 @@ #include "CMySQLQuery.h" #include "CMySQL.h" #include "CHotKeyEditorDialog.h" +#include "CNullLineEdit.h" #include <qregexp.h> #include <qvariant.h> #include <qtable.h> @@ -899,7 +900,7 @@

CFieldPropertiesLayout->addWidget(TextLabel3, 2, 0);

- Default = new QLineEdit(this, "Default"); + Default = new CNullLineEdit(this, "Default"); QWhatsThis::add(Default, trUtf8("Default value for the Field."));

CFieldPropertiesLayout->addMultiCellWidget(Default, 1, 1, 1, 4); @@ -1068,7 +1069,7 @@ currentField->Binary = false; currentField->ZeroFill = false; currentField->AutoIncrement = false; - currentField->Default = QString::null; + currentField->Default = ""; currentField->Value = QString::null; } else @@ -1090,7 +1091,7 @@ bool b = (type != "timestamp"); Default->setEnabled(b); if (!b) - currentField->Default = QString::null; + currentField->Default = ""; } skip = false; } @@ -1099,7 +1100,8 @@ { if (currentField == 0 || skip) return; - currentField->Default = s; + + currentField->Default = Default->isNull() ? QString::null : s; }

void CFieldProperties::setValue(const QString &s) @@ -1160,7 +1162,13 @@ currentField = f; setFieldType(currentField->Type); skip = true; - Default->setText(currentField->Default); + if (currentField->Default.isNull()) + Default->setNull(true); + else + { + Default->setNull(false); + Default->setText(currentField->Default); + } Value->setText(currentField->Value); Length->setText(currentField->Length); Unsigned->setChecked(currentField->Unsigned); @@ -1198,7 +1206,6 @@ fields->horizontalHeader()->setLabel(0, tr("Field Name"), 210); fields->horizontalHeader()->setLabel(1, tr("Allow NULL")); fields->horizontalHeader()->setLabel(2, tr("Data Type")); -

CTableWindowLayout->addWidget(fields, 0, 0);

@@ -1644,10 +1651,17 @@

if (!skipDefault) { - sql += "DEFAULT '"; - if (!field->Default.isEmpty()) - sql +=
mysql->mysql()->codec()->fromUnicode(mysql->mysql()->escape(field->Default)); - sql += "' "; + sql += "DEFAULT "; + + if (field->Default.isNull()) + sql += "NULL "; + else + { + sql += "'"; + if (!field->Default.isEmpty()) + sql +=
mysql->mysql()->codec()->fromUnicode(mysql->mysql()->escape(field->Default)); + sql += "' "; + } }

if (field->AutoIncrement) @@ -2033,6 +2047,11 @@ f->Default = f->Default.left(f->Default.findRev('\'')); f->Default = f->Default.replace(dblQuoteRegExp, "'"); } + else + if (line.find("default NULL", 0, false) != -1) + f->Default = QString::null; + else + f->Default = ""; line = line.lower(); f->Unsigned = (line.find("unsigned") != -1); f->ZeroFill = (line.find("zerofill") != -1);

--- 1.23/dist/TODO.txt Fri Oct 18 05:37:15 2002 +++ 1.24/dist/TODO.txt Sat Oct 26 10:01:27 2002 @@ -29,8 +29,6 @@

*Automatically restore open database connections

- *Inplace INSERT / DELETE capabilities to CSqlTable - *Add SSL support for MySQL 4

*Add REQUIRE to CUserAdminWindow @@ -76,9 +74,6 @@

*MySQLMulti Wrapper

- *Make each CDatabaseTreeItem descendant display something in the - WidgetStack when clicked. - *Need option "Hide Disconnected Items" for CDatabaseTree

@@ -90,5 +85,4 @@ KNOWN BUGS ========== *Sound not working in Linux ... It can only be enabled when QT is compiled
with - the NAS option. It would be nice if QT didn't depend on it ! - + the NAS option. It would be nice if QT didn't depend on it. \ No newline at end of file

--- 1.45/dist/Changelog.txt Wed Oct 23 08:58:46 2002 +++ 1.46/dist/Changelog.txt Sat Oct 26 10:01:29 2002 @@ -1,4 +1,4 @@ -Changes for 0.8.5-alpha +Changes for 0.8.6-alpha ----------------------- Disabled HTML rendering in the text editor.

@@ -20,21 +20,37 @@

One can now copy selections instead of cell-values in the Results Panel.

- Double-Clicking in a readOnlyColumn (Results Panel) now opens up the default
editor + Double-Clicking in a read-Only-Column (Results Panel) now opens up the
default editor .. that is ImageViewer for BLOB fields and the Text Editor for TEXT fields.

Fixed a bug in the Query Window which allowed queries other than "SELECT *
FROM Tbl" to be edited.

- Fixed a bug in the Explain Panel that displayed the panel's context menu and
the - default QDockWindow context after the main menu was closed. + Fixed a bug in the Explain Panel that displayed a QDockWindow menu when the
panel's + context-menu was closed.

Enhanced the way copy works in the Query Window

Added several visual enhancements to the Query Window

- When the "Silent" option is now selected in the Query Window Options, no
queries will + When the "Silent" option is now selected in 'Query Window Options', no
queries will be appended to the Sql Debug Panel. + + Fixed a non critical bug in the function that generates the UPDATE queries
for the + Results Panel. + + Added inline inserting capabilities to the Results Panel. + + Added inline deleting capabilities to the Results Panel. + + Fixed a couple of non-critical bugs in the way the privileges where parsed in
the + User Administration Window + + Fixed a bug in the Create & Alter Table window which didn't support NULL
defaults and + also didn't parse "DEFAULT NULL" correctly; One can now specify a NULL
default by + pressing CTRL + 0 (same as for inline editing). + + MyCC 0.8.6 binaries are now compiled with Qt 3.0.6

Important Notes for 0.8.5-alpha

--- 1.15/include/CMySQLQuery.h Fri Oct 18 05:39:12 2002 +++ 1.16/include/CMySQLQuery.h Sat Oct 26 10:06:10 2002 @@ -96,7 +96,7 @@ ulong len; bool res; }; - + CMySQL *m_mysql; MYSQL_RES *mysql_res; MYSQL_ROW mysql_row;

--- 1.15/include/CQueryWindow.h Wed Oct 23 08:58:33 2002 +++ 1.16/include/CQueryWindow.h Sat Oct 26 10:06:10 2002 @@ -61,7 +61,6 @@ void setBusy(bool); void cancel(); void copy(); - void query_progress();

private slots: void viewMenuAboutToShow(); @@ -134,6 +133,8 @@ CAction *viewResultsPanelAction; CAction *editCopyAction; CAction *editCutAction; + CAction *queryDeleteRecordAction; + CAction *queryInsertRecordAction; QPopupMenu * queryTypesMenu; QPopupMenu *saveTypesMenu; int query_type;

--- 1.19/include/config.h Sat Oct 19 01:19:00 2002 +++ 1.20/include/config.h Sat Oct 26 10:06:10 2002 @@ -69,6 +69,7 @@ #define MENU_SHOW_INNODB_STATUS 145 #define MENU_SAVE_INNODB_STATUS 146 #define MENU_SAVE_TO_FILE 147 +#define MENU_INSERT 148

#define ANALYZE_TABLE 500 #define CHECK_TABLE 501

--- 1.11/src/CCreditsBox.cpp Mon Oct 21 01:03:30 2002 +++ 1.12/src/CCreditsBox.cpp Sat Oct 26 10:02:50 2002 @@ -23,10 +23,12 @@ TextLabel3_2->setFrameShadow( QLabel::Sunken ); TextLabel3_2->setText(tr(" Volker Hilsheimer<br>\n" "Trolltech Support Team<br>\n" + "Tarmo Järvalt<br>\n" "Lenz Grimmer<br>\n" "Alexander Keremidarski<br>\n" "Matt Wagner<br>\n" - "Tom Basil<br>" ) ); + "Tom Basil<br>\n" + "And many others<br>") ); TextLabel3_2->setAlignment( int( QLabel::AlignTop ) ); QWhatsThis::add( TextLabel3_2,tr("People who contributed indirectly to this
development." ) );

--- 1.27/src/CMySQLQuery.cpp Tue Oct 22 10:11:07 2002 +++ 1.28/src/CMySQLQuery.cpp Sat Oct 26 10:02:54 2002 @@ -36,7 +36,6 @@ res = (mysql_real_query(m_mysql, qry, len) == 0); }

- CMySQLQuery::CMySQLQuery(CMySQL *m) : QObject(0, "CMySQLQuery") {

--- 1.38/src/CQueryWindow.cpp Wed Oct 23 08:55:33 2002 +++ 1.39/src/CQueryWindow.cpp Sat Oct 26 10:03:00 2002 @@ -27,8 +27,6 @@

#define PROCESS_EVENT 35

-static ulong progress = 0; - CQueryWindow::CExplainPanel::CExplainPanel(QWidget * parent, CMySQLQuery *q,
CMySQLServer *m) : CQueryTable(parent, q, m, "CExplainPanel") { @@ -122,6 +120,7 @@ progress_bar = new CProgressBar(statusBar()); progress_bar->setPercentageVisible(false); progress_bar->setFrameShape(QFrame::NoFrame); + progress_bar->setTotalSteps(100);

statusBar()->addWidget(executing_query_label, 0, true); statusBar()->addWidget(progress_bar, 0, true); @@ -173,7 +172,7 @@ results_table->setRealParent(this); connect (this, SIGNAL(about_to_close()), results_table,
SLOT(aboutToClose())); columns_window = new CTableFieldChooser(0, results_table,
"CQueryTableColumnsWindow", QDockWindow::InDock); - connect(results_table, SIGNAL(refreshed()), columns_window, SLOT(refresh())); + connect(results_table, SIGNAL(refreshed()), columns_window, SLOT(refresh()));

columns_window->setCaption("[" + m->connectionName() + "] " + tr("Query
Columns"));

@@ -283,6 +282,21 @@ queryCancelAction->setParentMenuText(tr("Query")); connect(queryCancelAction, SIGNAL(activated()), this, SLOT(cancel()));

+ queryInsertRecordAction = new CAction(tr("Insert Record"),
getPixmapIcon("insertRowIcon"), + tr("&Insert Record"), Qt::CTRL + Qt::Key_I, this,
"queryInsertRecordAction"); + queryInsertRecordAction->setParentMenuText(tr("Query")); + connect(queryInsertRecordAction, SIGNAL(activated()), results_table,
SLOT(insertRecord())); + QAccel *insertRecordAccel = new QAccel(this); + insertRecordAccel->connectItem(insertRecordAccel->insertItem(Key_Insert),
results_table, SLOT(insertRecord())); + + queryDeleteRecordAction = new CAction(tr("Delete Record"),
getPixmapIcon("deleteRowIcon"), + tr("&Delete Record"), Qt::CTRL + Qt::Key_D, this, "queryDeleteRowAction"); + queryDeleteRecordAction->setParentMenuText(tr("Query")); + connect(queryDeleteRecordAction, SIGNAL(activated()), results_table,
SLOT(deleteRecord())); + QAccel *deleteRecordAccel = new QAccel(this); + deleteRecordAccel->connectItem(deleteRecordAccel->insertItem(Qt::Key_Delete),
results_table, SLOT(deleteRecord())); + connect(results_table, SIGNAL(canDelete(bool)), queryDeleteRecordAction,
SLOT(setEnabled(bool))); + optionsGeneralAction = new CAction(tr("General options for the Query
Window"), getPixmapIcon("hammerIcon"), tr("&Query Window Options"), Qt::CTRL + Qt::Key_Q, this,
"optionsGeneralAction"); optionsGeneralAction->setParentMenuText(tr("Options")); @@ -383,10 +397,23 @@ queryTypeButton->setTextLabel(tr("Query Type"), true); queryTypeButton->setPopupDelay(0);

+ queryToolBar->addSeparator(); + queryMenu->insertSeparator(); + + queryInsertRecordAction->addTo(queryToolBar); + queryInsertRecordAction->addTo(queryMenu); + + queryDeleteRecordAction->addTo(queryToolBar); + queryDeleteRecordAction->addTo(queryMenu); + + optionsGeneralAction->addTo(optionsMenu);

editUndoAction->setEnabled(false); editRedoAction->setEnabled(false); + queryDeleteRecordAction->setEnabled(false); + queryInsertRecordAction->setEnabled(false); + connect(query_editor, SIGNAL(selectionChanged()), this,
SLOT(selectionChanged())); connect(results_table, SIGNAL(selectionChanged()), this,
SLOT(selectionChanged()));

@@ -452,11 +479,6 @@ delete explain_query; }

-void CQueryWindow::query_progress() -{ - progress_bar->setProgress(++progress); -} - void CQueryWindow::generalOptions() { CQueryWindowOptionsDialog *w = new
CQueryWindowOptionsDialog(myApp()->workSpace(), mysql()); @@ -474,9 +496,9 @@ results_table->displayMessages(opt.silent); mysql()->enableSqlDebugMessages(opt.silent); if (!opt.silent) - results_table->disconnect(SIGNAL(progress())); + results_table->disconnect(SIGNAL(progress(int))); else - connect(results_table, SIGNAL(progress()), this, SLOT(query_progress())); + connect(results_table, SIGNAL(progress(int)), progress_bar,
SLOT(setProgress(int))); force = opt.force;

CMySQLQuery *qry = new CMySQLQuery(mysql()->mysql()); @@ -594,15 +616,14 @@ qDebug("CQueryWindow::selectionChanged()"); #endif

- bool s; + bool s = false; if (query_editor->hasFocus()) - s = query_editor->hasSelectedText(); + s = query_editor->hasSelectedText() && query_editor->isVisible(); else if (results_table->hasFocus()) - s = results_table->numSelections() > 0; - else - s = false; - editCutAction->setEnabled(query_editor->hasFocus() ? s : false); + s = results_table->numSelections() > 0 && results_table->isVisible(); + + editCutAction->setEnabled(s && query_editor->hasFocus()); editCopyAction->setEnabled(s); }

@@ -674,8 +695,13 @@ #ifdef DEBUG qDebug("CQueryWindow::sqlPanelAction()"); #endif - - showSqlPanel(!query_editor->isVisible()); + + showSqlPanel(!query_editor->isVisible()); + selectionChanged(); + editRedoAction->setEnabled(query_editor->isVisible() &&
query_editor->isRedoAvailable()); + editUndoAction->setEnabled(query_editor->isVisible() &&
query_editor->isUndoAvailable()); + editEraseAction->setEnabled(query_editor->isVisible()); + editPasteAction->setEnabled(query_editor->isVisible() &&
query_editor->isVisible()); }

void CQueryWindow::resultsPanelAction() @@ -685,6 +711,16 @@ #endif

showResultsPanel(!results_table->isVisible()); + if (results_table->isVisible()) + { + queryDeleteRecordAction->setEnabled(!results_table->isReadOnly()); + queryInsertRecordAction->setEnabled(!results_table->isReadOnly()); + } + else + { + queryDeleteRecordAction->setEnabled(false); + queryInsertRecordAction->setEnabled(false); + } }

void CQueryWindow::setBusy(bool b) @@ -703,13 +739,18 @@ saveTypesMenu->setEnabled(ena); fileOpenAction->setEnabled(ena); queryExecuteAction->setEnabled(ena); - editPasteAction->setEnabled(ena); - editRedoAction->setEnabled(ena); - editUndoAction->setEnabled(ena); - editEraseAction->setEnabled(ena); - fileCloseAction->setEnabled(ena); - editCopyAction->setEnabled(ena); - editCutAction->setEnabled(ena); + editPasteAction->setEnabled(ena && query_editor->isVisible()); + editRedoAction->setEnabled(ena && query_editor->isVisible() &&
query_editor->isRedoAvailable()); + editUndoAction->setEnabled(ena && query_editor->isVisible() &&
query_editor->isUndoAvailable()); + editEraseAction->setEnabled(ena && query_editor->isVisible()); + fileCloseAction->setEnabled(ena); + if (!ena) + { + editCopyAction->setEnabled(false); + editCutAction->setEnabled(false); + } + else + selectionChanged();

enableQueryTypes(ena && !default_table.isEmpty());

@@ -792,7 +833,8 @@ setBusy(true); executing_query_label->setEnabled(true); read_only_label->setEnabled(true); - progress = 0; + queryDeleteRecordAction->setEnabled(false); + queryInsertRecordAction->setEnabled(false); for (ulong i = 0; i < qry.length(); i++) { if (do_cancel) @@ -870,7 +912,6 @@ if (query_ok && !do_cancel) { results_table->setQuery(query); - progress_bar->setTotalSteps(query->numRows()); results_table->refresh(); bool exp_ok = false; if (queryType == "select") @@ -887,8 +928,11 @@ results_table->setTableName(default_table); results_table->setDatabaseName(default_database); last_query = last_query.simplifyWhiteSpace().lower(); - results_table->setReadOnly(default_database.isEmpty() ||
!last_query.startsWith("select * from")); - read_only_label->setEnabled(results_table->isReadOnly()); + bool ro = default_database.isEmpty() ||
!last_query.startsWith("select * from"); + results_table->setReadOnly(ro); + read_only_label->setEnabled(ro); + queryDeleteRecordAction->setEnabled(!ro && query->numRows() > 0); + queryInsertRecordAction->setEnabled(!ro); query_type = SQL_ALL_ROWS; } else @@ -903,7 +947,6 @@ setWindowCaption(); setBusy(false); progress_bar->setProgress(0); - progress = 0; if (do_cancel) { cancel(); @@ -946,6 +989,8 @@ setBusy(true); results_table->reset(); query->freeResult(); + queryDeleteRecordAction->setEnabled(false); + queryInsertRecordAction->setEnabled(false); do_cancel = false; setBusy(false); }

--- 1.14/src/CTableSpecific.cpp Wed Oct 16 02:23:28 2002 +++ 1.15/src/CTableSpecific.cpp Sat Oct 26 10:03:15 2002 @@ -171,6 +171,7 @@ w->setFocus(); w->raise(); myShowWindow(w); + qApp->processEvents(); if (query_type != SQL_QUERY && myApp()->retrieveAllRecordsFromTable()) w->executeQuery(); }

--- 1.27/src/CUserAdminWindow.cpp Wed Oct 16 02:23:29 2002 +++ 1.28/src/CUserAdminWindow.cpp Sat Oct 26 10:03:22 2002 @@ -453,11 +453,36 @@

CGrantItem *CUserAdminWindow::findItem(const QString &db, const QString &tbl) { + QString tmp_db; + QString tmp_tbl; + bool db_wild = false; + bool tbl_wild = false; + + if (db.endsWith("%")) + { + tmp_db = db.left(db.length() - 2); + db_wild = true; + } + else + tmp_db = db; + + if (tbl.endsWith("%")) + { + tmp_tbl = tbl.left(tbl.length() - 2); + tbl_wild = true; + } + else + tmp_tbl = tbl; + QListViewItemIterator it(databaseListView); + bool ok = false; for (; it.current(); ++it) { CGrantItem *i = (CGrantItem *) it.current(); - if (i->databaseName() == db && i->tableName() == tbl) + ok = db_wild ? i->databaseName().startsWith(tmp_db) : i->databaseName() ==
db; + ok &= tbl_wild ? i->tableName().startsWith(tmp_tbl) : i->tableName() ==
tbl; + + if (ok) return i; } return 0; @@ -477,6 +502,14 @@ bool withGrant; int p; int p2; + CGrantItem *item; + if (qry->numRows() == 0) // has USAGE ... check the "Global Privileges"
option ... + { + item = findItem("*", "*"); + if (item != 0) + item->setOn(true); + } + else while (qry->next()) { privs = QString::null; @@ -511,7 +544,7 @@ if (line.find("WITH GRANT OPTION") != -1) withGrant = true;

- CGrantItem *item = findItem(dbname, table); + item = findItem(dbname, table); if (item != 0) { item->setOn(true);

--- 1.9/win32/MyCC.pro Wed Oct 16 02:23:16 2002 +++ 1.10/win32/MyCC.pro Sat Oct 26 10:07:53 2002 @@ -45,6 +45,7 @@ src/CMySQLQuery.cpp \ src/CMySQLServer.cpp \ src/CMyWindow.cpp \ + src/CNullLineEdit.cpp \ src/CProperties.cpp \ src/CQueryTable.cpp \ src/CQueryWindow.cpp \ @@ -110,6 +111,7 @@ include/CMySQLQuery.h \ include/CMySQLServer.h \ include/CMyWindow.h \ + include/CNullLineEdit.h \ include/config.h \ include/CProperties.h \ include/CQueryTable.h \ @@ -152,4 +154,4 @@ include/icons.h \ include/panels.h \ include/resource.h \ - include/shared_menus.h \ No newline at end of file + include/shared_menus.h