[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/kexi/plugins/queries
From:       Jaroslaw Staniek <js () iidea ! pl>
Date:       2006-10-05 23:01:28
Message-ID: 1160089288.465671.27868.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 592850 by staniek:

Query Designer
- invalid input (e.g. criteria or sorting) now displays a message box with 
  "Correct" and "Discard Changes" buttons
- added support for setting order of columns in Design and SQL views (ORDER BY)
- fields were sometimes added twice

2.0: merged



 M  +143 -39   kexiquerydesignerguieditor.cpp  


--- trunk/koffice/kexi/plugins/queries/kexiquerydesignerguieditor.cpp #592849:592850
@@ -41,6 +41,7 @@
 #include <kexidb/parser/parser.h>
 #include <kexidb/parser/sqlparser.h>
 #include <kexidb/utils.h>
+#include <kexidb/roweditbuffer.h>
 #include <kexiutils/identifier.h>
 #include <kexiproject.h>
 #include <keximainwindow.h>
@@ -70,10 +71,12 @@
 #define COLUMN_ID_TABLE 1
 #define COLUMN_ID_VISIBLE 2
 #ifdef KEXI_NO_QUERY_TOTALS
-# define COLUMN_ID_CRITERIA 3
+# define COLUMN_ID_SORTING 3
+# define COLUMN_ID_CRITERIA 4
 #else
 # define COLUMN_ID_TOTALS 3
-# define COLUMN_ID_CRITERIA 4
+# define COLUMN_ID_SORTING 4
+# define COLUMN_ID_CRITERIA 5
 #endif
 
 /*! @internal */
@@ -116,6 +119,16 @@
 	bool slotTableAdded_enabled : 1;
 };
 
+static bool isAsterisk(const QString& tableName, const QString& fieldName)
+{
+	return tableName=="*" || fieldName.endsWith("*");
+}
+
+//! @internal \return true if sorting is allowed for \a fieldName and \a tableName
+static bool sortingAllowed(const QString& fieldName, const QString& tableName) {
+	return ! (fieldName=="*" || (fieldName.isEmpty() && tableName=="*"));
+}
+
 //=========================================================
 
 KexiQueryDesignerGuiEditor::KexiQueryDesignerGuiEditor(
@@ -147,8 +160,9 @@
 	Q3ValueList<int> c;
 	c << COLUMN_ID_COLUMN << COLUMN_ID_TABLE << COLUMN_ID_CRITERIA;
 	if (d->dataTable->tableView()/*sanity*/) {
+		d->dataTable->tableView()->adjustColumnWidthToContents(COLUMN_ID_VISIBLE);
+		d->dataTable->tableView()->adjustColumnWidthToContents(COLUMN_ID_SORTING);
 		d->dataTable->tableView()->maximizeColumnsWidth( c );
-		d->dataTable->tableView()->adjustColumnWidthToContents(COLUMN_ID_VISIBLE);
 		d->dataTable->tableView()->setDropsAtRowEnabled(true);
 		connect(d->dataTable->tableView(), \
SIGNAL(dragOverRow(KexiTableItem*,int,QDragMoveEvent*)),  this, \
SLOT(slotDragOverTableRow(KexiTableItem*,int,QDragMoveEvent*))); @@ -218,15 +232,14 \
@@  d->data->addColumn(col4);
 #endif
 
-/*TODO
-f= new KexiDB::Field(i18n("Sort"), KexiDB::Field::Enum);
+	KexiTableViewColumn *col5 = new KexiTableViewColumn("sort", KexiDB::Field::Enum, \
i18n("Sorting"), +		i18n("Describes a way of sorting for a given field."));
 	QValueVector<QString> sortTypes;
+	sortTypes.append( "" );
 	sortTypes.append( i18n("Ascending") );
 	sortTypes.append( i18n("Descending") );
-	sortTypes.append( i18n("No sorting") );
-	f->setEnumHints(sortTypes);
-	KexiTableViewColumn *col5 = new KexiTableViewColumn(*f);
-	d->data->addColumn(col5);*/
+	col5->field()->setEnumHints(sortTypes);
+	d->data->addColumn(col5);
 
 	KexiTableViewColumn *col6 = new KexiTableViewColumn("criteria", \
KexiDB::Field::Text, i18n("Criteria"),  i18n("Describes the criteria for a given \
field or expression.")); @@ -353,11 +366,13 @@
 		temp->query()->addTable( it.current()->schema()->table() );
 	}
 
-	//add fields
+	//add fields, also build:
+	// -WHERE expression
+	// -ORDER BY list
 	KexiDB::BaseExpr *whereExpr = 0;
-	KexiTableViewData::Iterator it(d->data->iterator());
 	const uint count = qMin(d->data->count(), d->sets->size());
 	bool fieldsFound = false;
+	KexiTableViewData::Iterator it(d->data->iterator());
 	for (uint i=0; i<count && it.current(); ++it, i++) {
 		if (!it.current()->at(COLUMN_ID_TABLE).isNull() && \
it.current()->at(COLUMN_ID_COLUMN).isNull()) {  //show message about missing field \
name, and set focus to that cell @@ -374,6 +389,8 @@
 			QString tableName = (*set)["table"].value().toString().trimmed();
 			QString fieldName = (*set)["field"].value().toString();
 			QString fieldAndTableName = fieldName;
+			KexiDB::Field *currentField = 0; // will be set if this column is a single field
+			KexiDB::QueryColumnInfo* currentColumn = 0;
 			if (!tableName.isEmpty())
 				fieldAndTableName.prepend(tableName+".");
 			bool fieldVisible = (*set)["visible"].value().toBool();
@@ -395,7 +412,7 @@
 				if (whereExpr)
 					whereExpr = new KexiDB::BinaryExpr(KexiDBExpr_Logical, whereExpr, AND, \
criteriaExpr);  else //first expr.
-					whereExpr =	criteriaExpr;
+					whereExpr = criteriaExpr;
 			}
 			if (tableName.isEmpty()) {
 				if ((*set)["isExpression"].value().toBool()==true) {
@@ -424,7 +441,6 @@
 			}
 			else {
 				KexiDB::TableSchema *t = d->conn->tableSchema(tableName);
-//				if (fieldName.find(".*")!=-1) {
 				if (fieldName=="*") {
 					//single-table asterisk: <tablename> + ".*" + number
 					temp->query()->addAsterisk( new KexiDB::QueryAsterisk( temp->query(), t ), \
fieldVisible ); @@ -435,12 +451,13 @@
 						kexipluginswarn << "query designer: NO TABLE '" << \
(*set)["table"].value().toString() << "'" << endl;  continue;
 					}
-					KexiDB::Field *f = t->field( fieldName );
-					if (!f) {
+					currentField = t->field( fieldName );
+					if (!currentField) {
 						kexipluginswarn << "query designer: NO FIELD '" << fieldName << "'" << endl;
 						continue;
 					}
-					temp->query()->addField(f, fieldVisible);
+					temp->query()->addField(currentField, fieldVisible);
+					currentColumn = temp->query()->expandedOrInternalField( \
temp->query()->fieldsExpanded().count() - 1 );  if (fieldVisible)
 						fieldsFound = true;
 					if (!alias.isEmpty())
@@ -475,6 +492,32 @@
 			detailsTable->schema()->table()->field(it.current()->detailsField()) );
 	}
 
+	// Add sorting information (ORDER BY) - we can do that only now once 
+	//  all QueryColumnInfo items are instantiated
+	KexiDB::OrderByColumnList orderByColumns;
+	it = d->data->iterator();
+	for (uint i=0; i<count && it.current(); ++it, i++) {
+		KoProperty::Set *set = d->sets->at(i);
+		if (!set)
+			continue;
+		KexiDB::Field *currentField = temp->query()->field( i );
+		if (!currentField || currentField->isExpression() || \
currentField->isQueryAsterisk()) +//! @todo support expressions here
+			continue;
+//! @todo ok, but not for expresions
+		QString aliasString( (*set)["alias"].value().toString() );
+		KexiDB::QueryColumnInfo *currentColumn = temp->query()->columnInfo( 
+			aliasString.isEmpty() ? currentField->name() : aliasString );
+		QString sortingString( (*set)["sorting"].value().toString() );
+		if (currentField && currentColumn && (sortingString=="ascending" || \
sortingString=="descending")) { +			if (currentColumn->visible)
+				orderByColumns.appendColumn(*currentColumn, sortingString=="ascending");
+			else if (currentColumn->field)
+				orderByColumns.appendField(*currentColumn->field, sortingString=="ascending");
+		}
+	}
+	temp->query()->setOrderByColumnList( orderByColumns );
+
 	temp->query()->debug();
 	temp->registerTableSchemaChanges(temp->query());
 	//TODO?
@@ -769,7 +812,7 @@
 	if (!showFields)
 		return;
 
-	//3. show fields
+	//3. show fields (including * and table.*)
 	uint row_num = 0;
 	KexiDB::Field *field;
 	Q3PtrDict<char> usedCriterias(101); // <-- used criterias will be saved here
@@ -843,7 +886,49 @@
 		}
 	}
 
-	//4. Show fields for unused criterias (with "Visible" column set to false)
+	//4. show ORDER BY information
+	KexiDB::OrderByColumnList &orderByColumns = query->orderByColumnList();
+//	Q3PtrDict<KexiDB::OrderByColumn> orderByDictForFields;
+//	Q3PtrDict<KexiDB::OrderByColumn> orderByDictForColumns;
+	QMap<KexiDB::QueryColumnInfo*,int> columnsOrder( \
query->columnsOrder(false/*!expanded*/) ); +	for \
(KexiDB::OrderByColumn::ListConstIterator orderByColumnsIt( \
orderByColumns.constBegin() ); +		orderByColumnsIt!=orderByColumns.constEnd(); \
++orderByColumnsIt) +	{
+		KexiDB::QueryColumnInfo *column = (*orderByColumnsIt).column();
+		if (column) {
+			//sorting for visible column
+			if (column->visible) {
+				if (columnsOrder.contains(column)) {
+					const int columnPosition = columnsOrder[ column ];
+					KexiTableItem *rowItem = d->data->at( columnPosition );
+					KoProperty::Set *rowPropertySet = d->sets->at( columnPosition );
+					if (rowItem && rowPropertySet) {
+						kexipluginsdbg << \
"KexiQueryDesignerGuiEditor::showFieldsOrRelationsForQueryInternal():\n\t" \
+							"Setting \"" << (*orderByColumnsIt).debugString() << "\" sorting for row #"  \
+							<< columnPosition<< endl; +						//(*rowPropertySet)["sorting"].setValue(
+							//QString((*orderByColumnsIt).ascending() ? "ascending" : "descending") );
+						d->data->clearRowEditBuffer();
+						d->data->updateRowEditBuffer(rowItem, COLUMN_ID_SORTING,
+							(*orderByColumnsIt).ascending() ? 1 : 2); // this will automatically update \
"sorting" property +						                                             // in \
slotBeforeCellChanged() +						d->data->saveRowChanges(*rowItem, true);
+						(*rowPropertySet)["sorting"].clearModifiedFlag(); // this property should look \
"fresh" +//						d->data->rowEditBuffer()->debug();
+					}
+//					query->field(columnPosition);
+				}
+			}
+//				orderByDictForColumns.replace( (void*)(*orderByColumnsIt).column(), \
&(*orderByColumnsIt) ); +	//		else
+		//		orderByDictForFields.replace( (void*)(*orderByColumnsIt).column()->field, \
&(*orderByColumnsIt) ); +		}
+		else if ((*orderByColumnsIt).field()) {//this will be presented as invisible field
+//			orderByDictForFields.replace( (void*)(*orderByColumnsIt).field(), \
&(*orderByColumnsIt) ); +		}
+	}
+
+	//5. Show fields for unused criterias (with "Visible" column set to false)
 	KexiDB::BaseExpr *criteriaArgument; // <-- contains field or table.field
 	for (Q3DictIterator<KexiDB::BaseExpr> it(criterias); (criteriaArgument = \
it.current()); ++it) {  if (usedCriterias[it.current()])
@@ -1277,7 +1362,8 @@
 					alias = fieldId.left(id).trimmed().latin1();
 					if (!KexiUtils::isIdentifier(alias)) {
 						result->success = false;
-						result->column = 0;
+						result->allowToDiscardChanges = true;
+						result->column = colnum;
 						result->msg = i18n("Entered column alias \"%1\" is not a valid identifier.")
 							.arg(alias);
 						result->desc = i18n("Identifiers should start with a letter or '_' \
character"); @@ -1296,7 +1382,8 @@
 				}
 				else {
 					result->success = false;
-					result->column = 0;
+					result->allowToDiscardChanges = true;
+					result->column = colnum;
 					result->msg = i18n("Invalid expression \"%1\"").arg(fieldName);
 					return;
 				}
@@ -1328,10 +1415,15 @@
 				propertySetSwitched();
 			}
 			d->data->updateRowEditBuffer(item, COLUMN_ID_TABLE, QVariant(tableName), \
                false/*!allowSignals*/);
-			d->data->updateRowEditBuffer(item, COLUMN_ID_VISIBLE, QVariant(true,1));//visible
+			d->data->updateRowEditBuffer(item, COLUMN_ID_VISIBLE, QVariant(true,1));
 #ifndef KEXI_NO_QUERY_TOTALS
-			d->data->updateRowEditBuffer(item, COLUMN_ID_TOTALS, QVariant(0));//totals
+			d->data->updateRowEditBuffer(item, COLUMN_ID_TOTALS, QVariant(0));
 #endif
+			if (!sortingAllowed(fieldName, tableName)) {
+				// sorting is not available for "*" or "table.*" rows
+//! @todo what about expressions?
+				d->data->updateRowEditBuffer(item, COLUMN_ID_SORTING, QVariant());
+			}
 			//update properties
 			(*set)["field"].setValue(fieldName, saveOldValue);
 			if (isExpression) {
@@ -1399,15 +1491,32 @@
 		setDirty(true);
 	}
 #endif
-	else if (colnum==COLUMN_ID_CRITERIA) {//'criteria'
-//TODO: this is primitive, temporary: reuse SQL parser
+	else if (colnum==COLUMN_ID_SORTING) {
+		KoProperty::Set *set = d->sets->findPropertySetForItem(*item);
+		QString table( set->property("table").value().toString() );
+		QString field( set->property("field").value().toString() );
+		if (newValue.toInt()==0 || sortingAllowed(field, table)) {
+			KoProperty::Property &property = set->property("sorting");
+			QString key( property.listData()->keysAsStringList()[ newValue.toInt() ] );
+			kexipluginsdbg << "new key=" << key << endl;
+			property.setValue(key, true);
+		}
+		else { //show msg: sorting is not available
+			result->success = false;
+			result->allowToDiscardChanges = true;
+			result->column = colnum;
+			result->msg = futureI18n("Could not set sorting for multiple columns (%1)")
+				.arg(table=="*" ? table : (table+".*"));
+		}
+	}
+	else if (colnum==COLUMN_ID_CRITERIA) {
+//! @todo this is primitive, temporary: reuse SQL parser
 		QString operatorStr, argStr;
 		KexiDB::BaseExpr* e = 0;
 		const QString str = newValue.toString().trimmed();
-//		KoProperty::Set &set = *propertySet();
 		int token;
 		QString field, table;
-		KoProperty::Set *set = d->sets->findPropertySetForItem(*item); //*propertySet();
+		KoProperty::Set *set = d->sets->findPropertySetForItem(*item);
 		if (set) {
 			field = (*set)["field"].value().toString();
 			table = (*set)["table"].value().toString();
@@ -1415,13 +1524,14 @@
 		if (!str.isEmpty() && (!set || table=="*" || field.find("*")!=-1)) {
 			//asterisk found! criteria not allowed
 			result->success = false;
-			result->column = 4;
+			result->allowToDiscardChanges = true;
+			result->column = colnum;
 			if (propertySet())
 				result->msg = i18n("Could not set criteria for \"%1\"")
 					.arg(table=="*" ? table : field);
 			else
 				result->msg = i18n("Could not set criteria for empty row");
-			d->dataTable->dataAwareObject()->cancelEditor(); //prevents further editing of \
this cell +			//moved to result->allowToDiscardChanges handler \
//d->dataTable->dataAwareObject()->cancelEditor(); //prevents further editing of this \
cell  }
 		else if (str.isEmpty() || (e = parseExpressionString(str, token, \
true/*allowRelationalOperator*/)))  {
@@ -1442,7 +1552,8 @@
 		}
 		else {
 			result->success = false;
-			result->column = 4;
+			result->allowToDiscardChanges = true;
+			result->column = colnum;
 			result->msg = i18n("Invalid criteria \"%1\"").arg(newValue.toString());
 		}
 	}
@@ -1483,11 +1594,6 @@
 	return d->sets->currentPropertySet();
 }
 
-static bool isAsterisk(const QString& tableName, const QString& fieldName)
-{
-	return tableName=="*" || fieldName.endsWith("*");
-}
-
 void KexiQueryDesignerGuiEditor::updatePropertiesVisibility(KoProperty::Set& set)
 {
 	const bool asterisk = isAsterisk(
@@ -1497,9 +1603,9 @@
 	set["caption"].setVisible( !asterisk );
 #endif
 	set["alias"].setVisible( !asterisk );
-#ifndef KEXI_NO_UNFINISHED
+/*always invisible #ifndef KEXI_NO_UNFINISHED
 	set["sorting"].setVisible( !asterisk );
-#endif
+#endif*/
 	propertySetReloaded(true);
 }
 
@@ -1544,9 +1650,7 @@
 	nlist << i18n("None") << i18n("Ascending") << i18n("Descending");
 	set->addProperty(prop = new KoProperty::Property("sorting",
 		slist, nlist, *slist.at(0), i18n("Sorting")));
-#ifdef KEXI_NO_UNFINISHED
-	prop->setVisible(false);
-#endif
+	//prop->setVisible(false);
 
 	set->addProperty(prop = new KoProperty::Property("criteria", \
QVariant(QString::null)) );  prop->setVisible(false);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic