I have a master report with 4 subreports in its details section. I want to display the page number range (for example 1- 2) of all the subreports in the Master report title section. I tried using subreport return value but it works only when I have 1 subreport not if there are more than 1 subreport
Here is the solution
Step1 : Create variables of any type inside each of the SubReport and the set the calculation, Increment Type and Reset Type to None. No need to specify the Expression as well Initial Value Expression
Step 2 : Create variables of String type inside the Master Report to hold the value of page number (eg. 1-2) and set the Calculation as System.
Step 3 : Add the variables created in Step2 on the Master Report Title section and set the evaluation time as Report.
Step 4 : Create scriptlet and set the page number in that
public class PageScriptlet extends JRDefaultScriptlet {
private static int mgmtReportPages;
private static int balanceSheetReportPages;
private static int incomeStmtReportPages;
private static int addInfoReportPages;
private static final String MGMT_REPORT_PAGENUM = "mgmtReportPageNum";
private static final String INCOME_STMT_PAGENUM = "incomeStmtPageNum";
private static final String BALANCE_SHEET_PAGENUM = "balanceSheetPageNum";
private static final String ADDINFO_PAGENUM = "addInfoPageNum";
private static final String MGMT_REPORT_INDEX = "mgmtReportIndex";
private static final String INCOMESTMT_INDEX = "incomeStmtIndex";
private static final String BALANCESHEET_INDEX = "balanceSheetIndex";
private static final String NOTES_INDEX = "notesIndex";
private static final String SIGNATURE_INDEX = "signatureIndex";
private static Integer firstPage = 2;
public PageScriptlet() {
super ();
}
#Override
public void afterPageInit() throws JRScriptletException{
Map<String, JRFillVariable> variablesMap = this.variablesMap;
if(variablesMap.containsKey(MGMT_REPORT_INDEX)){
Integer lastPage = mgmtReportPages+1;
String index = null;
if(firstPage == lastPage){
index = String.valueOf(firstPage);
}else{
index = String.valueOf(firstPage)+"-"+String.valueOf(lastPage);
}
this.setVariableValue(MGMT_REPORT_INDEX, index);
}
if(variablesMap.containsKey(INCOMESTMT_INDEX)){
Integer firstPage = mgmtReportPages + 2;
Integer lastPage = incomeStmtReportPages;
String index = null;
if(firstPage == lastPage){
index = String.valueOf(firstPage);
}else{
index = String.valueOf(firstPage)+"-"+String.valueOf(lastPage);
}
this.setVariableValue(INCOMESTMT_INDEX, index);
}
if(variablesMap.containsKey(BALANCESHEET_INDEX)){
Integer firstPage = incomeStmtReportPages+1;
Integer lastPage = balanceSheetReportPages;
String index = null;
if(firstPage == lastPage){
index = String.valueOf(firstPage);
}else{
index = String.valueOf(firstPage)+"-"+String.valueOf(lastPage);
}
this.setVariableValue(BALANCESHEET_INDEX, index);
}
if(variablesMap.containsKey(NOTES_INDEX)){
Integer firstPage = balanceSheetReportPages + 1;
Integer lastPage = addInfoReportPages;
String index = null;
if(firstPage == lastPage){
index = String.valueOf(firstPage);
}else{
index = String.valueOf(firstPage)+"-"+String.valueOf(lastPage);
}
this.setVariableValue(NOTES_INDEX, index);
}
if(variablesMap.containsKey(SIGNATURE_INDEX)){
Integer lastPage = addInfoReportPages;
String index = String.valueOf(lastPage);
this.setVariableValue(SIGNATURE_INDEX, index);
}
}
#Override
public void beforePageInit() throws JRScriptletException{
Map<String, JRFillVariable> variablesMap = this.variablesMap;
Integer pageNumber = (Integer)this.getVariableValue("PAGE_NUMBER");
if(variablesMap.containsKey(MGMT_REPORT_PAGENUM)){
mgmtReportPages = pageNumber == null ? 1 : pageNumber + 1;
}
if(variablesMap.containsKey(INCOME_STMT_PAGENUM)){
incomeStmtReportPages = pageNumber == null ? mgmtReportPages + 2 : incomeStmtReportPages + 1;
}
if(variablesMap.containsKey(BALANCE_SHEET_PAGENUM)){
balanceSheetReportPages = pageNumber == null ? incomeStmtReportPages + 1 : balanceSheetReportPages + 1;
}
if(variablesMap.containsKey(ADDINFO_PAGENUM)){
addInfoReportPages = pageNumber == null ? balanceSheetReportPages+1 : addInfoReportPages + 1;
}
}
}
Related
I'm upgrading some legacy to target Android Q, and of course this code stop working:
String[] PROJECTION_BUCKET = {MediaStore.Images.ImageColumns.BUCKET_ID,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATA,
"COUNT(" + MediaStore.Images.ImageColumns._ID + ") AS COUNT",
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.MediaColumns._ID};
String BUCKET_GROUP_BY = " 1) and " + BUCKET_WHERE.toString() + " GROUP BY 1,(2";
cur = context.getContentResolver().query(images, PROJECTION_BUCKET,
BUCKET_GROUP_BY, null, BUCKET_ORDER_BY);
android.database.sqlite.SQLiteException: near "GROUP": syntax error (code 1 SQLITE_ERROR[1])
Here it supposed to obtain list of images with album name, date, count of pictures - one image for each album, so we can create album picker screen without querying all pictures and loop through it to create albums.
Is it possible to group query results with contentResolver since SQL queries stoped work?
(I know that ImageColumns.DATA and "COUNT() AS COUNT" are deprecated too, but this is a question about GROUP BY)
(There is a way to query albums and separately query photo, to obtain photo uri for album cover, but i want to avoid overheads)
Unfortunately Group By is no longer supported in Android 10 and above, neither any aggregated functions such as COUNT. This is by design and there is no workaround.
The solution is what you are actually trying to avoid, which is to query, iterate, and get metrics.
To get you started you can use the next snipped, which will resolve the buckets (albums), and the amount of records in each one.
I haven't added code to resolve the thumbnails, but is easy. You must perform a query for each bucket Id from all the Album instances, and use the image from the first record.
public final class AlbumQuery
{
#NonNull
public static HashMap<String, AlbumQuery.Album> get(#NonNull final Context context)
{
final HashMap<String, AlbumQuery.Album> output = new HashMap<>();
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
final String[] projection = {MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.BUCKET_ID};
try (final Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null))
{
if ((cursor != null) && (cursor.moveToFirst() == true))
{
final int columnBucketName = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
final int columnBucketId = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_ID);
do
{
final String bucketId = cursor.getString(columnBucketId);
final String bucketName = cursor.getString(columnBucketName);
if (output.containsKey(bucketId) == false)
{
final int count = AlbumQuery.getCount(context, contentUri, bucketId);
final AlbumQuery.Album album = new AlbumQuery.Album(bucketId, bucketName, count);
output.put(bucketId, album);
}
} while (cursor.moveToNext());
}
}
return output;
}
private static int getCount(#NonNull final Context context, #NonNull final Uri contentUri, #NonNull final String bucketId)
{
try (final Cursor cursor = context.getContentResolver().query(contentUri,
null, MediaStore.Images.Media.BUCKET_ID + "=?", new String[]{bucketId}, null))
{
return ((cursor == null) || (cursor.moveToFirst() == false)) ? 0 : cursor.getCount();
}
}
public static final class Album
{
#NonNull
public final String buckedId;
#NonNull
public final String bucketName;
public final int count;
Album(#NonNull final String bucketId, #NonNull final String bucketName, final int count)
{
this.buckedId = bucketId;
this.bucketName = bucketName;
this.count = count;
}
}
}
This is a more efficient(not perfect) way to do that.
I am doing it for videos, but doing so is the same for images to. just change MediaStore.Video.Media.X to MediaStore.Images.Media.X
public class QUtils {
/*created by Nasib June 6, 2020*/
#RequiresApi(api = Build.VERSION_CODES.Q)
public static ArrayList<FolderHolder> loadListOfFolders(Context context) {
ArrayList<FolderHolder> allFolders = new ArrayList<>();//list that we need
HashMap<Long, String> folders = new HashMap<>(); //hashmap to track(no duplicates) folders by using their ids
String[] projection = {MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATE_ADDED};
ContentResolver CR = context.getContentResolver();
Uri root = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
Cursor c = CR.query(root, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " desc");
if (c != null && c.moveToFirst()) {
int folderIdIndex = c.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_ID);
int folderNameIndex = c.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
int thumbIdIndex = c.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
int dateAddedIndex = c.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_ADDED);
do {
Long folderId = c.getLong(folderIdIndex);
if (folders.containsKey(folderId) == false) { //proceed only if the folder data has not been inserted already :)
long thumbId = c.getLong(thumbIdIndex);
String folderName = c.getString(folderNameIndex);
String dateAdded = c.getString(dateAddedIndex);
Uri thumbPath = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, thumbId);
folders.put(folderId, folderName);
allFolders.add(new FolderHolder(String.valueOf(thumbPath), folderName, dateAdded));
}
} while (c.moveToNext());
c.close(); //close cursor
folders.clear(); //clear the hashmap becuase it's no more useful
}
return allFolders;
}
}
FolderHolder model class
public class FolderHolder {
private String folderName;
public long dateAdded;
private String thumbnailPath;
public long folderId;
public void setPath(String thumbnailPath) {
this.thumbnailPath = thumbnailPath;
}
public String getthumbnailPath() {
return thumbnailPath;
}
public FolderHolder(long folderId, String thumbnailPath, String folderName, long dateAdded) {
this.folderId = folderId;
this.folderName = folderName;
this.thumbnailPath = thumbnailPath;
this.dateAdded = dateAdded;
}
public String getFolderName() {
return folderName;
}
}
GROUP_BY supporting in case of using Bundle:
val bundle = Bundle().apply {
putString(
ContentResolver.QUERY_ARG_SQL_SORT_ORDER,
"${MediaStore.MediaColumns.DATE_MODIFIED} DESC"
)
putString(
ContentResolver.QUERY_ARG_SQL_GROUP_BY,
MediaStore.Images.ImageColumns.BUCKET_ID
)
}
contentResolver.query(
uri,
arrayOf(
MediaStore.Images.ImageColumns.BUCKET_ID,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATA
),
bundle,
null
)
I need help creating a predicate to use with Spring data and querydsl. I'm in the process of converting Daos to Repositorys. And I came across one that has a dynamic query in it. I can create a predicate from a list, but I'm lost at how to create a a dynamic predicate from a map. Here is the code from the DaoImpl that I'm converting from:
public Set<String> getDocumentsByDocumentAssociation(Map.Entry<String,String>[] associations) {
String queryStr = "SELECT da FROM DocumentExternalAssocEntity as da WHERE";
StringBuilder sb = new StringBuilder(queryStr);
//loop through inputs. for first loop, skip appending the OR statements. Append OR for all others
for ( int i = 0; i < associations.length; i++ ){
if ( i > 0 ) {
sb.append(" OR");
}
String whereString = " (da.associationtype = :docAssocType" + i + " AND da.associationvalue = :docAssocValue" + i + ")";
sb.append(whereString);
}
//query when previous loop is done appending
final Query query = em.createQuery(sb.toString());
for( int i = 0; i < associations.length; i++ ) {
query.setParameter("docAssocType" + i, associations[i].getKey());
query.setParameter("docAssocValue" + i, associations[i].getValue());
}
And here is the relevant generated class:
private static final long serialVersionUID = 1971644089L;
public static final QDocumentExternalAssocEntity documentExternalAssocEntity = new QDocumentExternalAssocEntity("documentExternalAssocEntity");
public final StringPath associationtype = createString("associationtype");
public final StringPath associationvalue = createString("associationvalue");
Thanks, and let me know if you need any additional info
This should do it:
BooleanExpression expr = null;
for ( int i = 0; i < associations.length; i++ ){
BooleanExpression innerExpr =
documentExternalAssocEntity.associationtype.eq(associations[i].getKey())
.and(documentExternalAssocEntity.associationvalue.eq(associations[i].getValue()))
if (expr == null) {
expr = innerExpr;
} else {
expr = expr.or(innerExpr);
}
}
I have some question regarding Android programming. More specific, I have a ListView where every single row is containg five widgets and each trigger event. I have created custom adapter and defined events handler for every widgets in the getView method. Everything works fine, however the code looks quite long, unreadable and nasty because of all these event handlers inside. Is there any better design? Maybe Creating event handlers outside the getView method or something else?
greetings
According to suggestion I posted part of the source code. As you can see I have created few event handlers outside the getView method and two inside. I really do not know which design is better.
public class ListViewAdapter extends ArrayAdapter<HourReport> {
private static Activity context;
private int resourcecId;
private TextView fromTime;
private TextView toTime;
private TextView total;
private HourReport rowModelBean;
private HourReport rowBean;
private CheckBox billable;
private ArrayList<HourReport> list;
private HourReportCatalog catalog;
private Map<Integer, Integer>selectedItems;
private Map<Integer, Integer>selectedRoles;
public ListViewAdapter(Activity context, int resourcecId,
ArrayList<HourReport> list, HourReportCatalog catalog) {
super(context, resourcecId, list);
this.catalog = catalog;
ListViewAdapter.context = context;
this.resourcecId = resourcecId;
this.list = list;
selectedItems = new HashMap<Integer, Integer>();
selectedRoles = new HashMap<Integer, Integer>();
}
// event handler for delete button "-"
private OnClickListener delete = new OnClickListener() {
#Override
public void onClick(View deletBtnF) {
int myPosition = (Integer) deletBtnF.getTag();
HourReport r = list.remove(myPosition);
selectedItems.put(myPosition, 0);
selectedRoles.put(myPosition, 0);
r.setTimeFinished(null);
r.setTimeStarted(null);
r.setTaks(null);
r.setTotal(0.0);
r.setBillable(false);
r.setEngagementContractID(0);
list.add(myPosition, r);
notifyDataSetChanged();
if (r.getDateCreated() != null) {
Log.e("Listview adapter", "inside the if statement");
Long id = r.getHourReportID();
Log.e("", "date created" + r.getDateCreated());
catalog.deleteHourReport(r);
r.setDateCreated(null);
}
}
};
// event handler for textView which is responsible for defining dateFrom
Calendar c = Calendar.getInstance();
OnClickListener onClickLisOnDateFrom = new OnClickListener() {
#Override
public void onClick(View editField) {
Integer position1 = (Integer) editField.getTag();
TableRow parent = (TableRow) editField.getParent();
fromTime = (TextView) parent.findViewById(R.id.viewTextFrom);
total = (TextView) parent.findViewById(R.id.textViewShowsTotal);
rowBean = getModel(position1);
TimePickerDialog.OnTimeSetListener timeListener1 = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minutes = c.get(Calendar.MINUTE);
String time = hour + ":" + minutes;
fromTime.setText(time);
setTimeFieldFrom(time);
String totalTime = totalHourCalculator();
total.setText(totalTime);
}
};
new TimePickerDialog(context, timeListener1,
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), true)
.show();
}
};
// event handler for textView which is responsible for defining dateTo
private OnClickListener onClickLisOnDateTo = new OnClickListener() {
#Override
public void onClick(View editField) {
Integer position1 = (Integer) editField.getTag();
Log.e("ListView - Timer ", "position: " + position1);
TableRow parent = (TableRow) editField.getParent();
toTime = (TextView) parent.findViewById(R.id.viewTextFrom);
total = (TextView) parent.findViewById(R.id.textViewShowsTotal);
rowBean = getModel(position1);
TimePickerDialog.OnTimeSetListener timeListener2 = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minutes = c.get(Calendar.MINUTE);
String time = hour + ":" + minutes;
toTime.setText(time);
setTimeFieldTo(time);
String totalTime = totalHourCalculator();
total.setText(totalTime);
}
};
new TimePickerDialog(context, timeListener2,
c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), true)
.show();
}
};
// event handler for check box
private OnClickListener checkBoxListener = new OnClickListener() {
#Override
public void onClick(View checkBox) {
Integer num = (Integer) checkBox.getTag();
rowBean = getModel(num);
if (rowBean.isBillable()) {
rowBean.setBillable(false);
} else {
rowBean.setBillable(true);
}
}
};
#Override
public View getView( int position, View convertView, ViewGroup parent) {
getHourReportList();
TextView deleteBtnV = null;
View row = convertView;
Spinner taskSpinner, roleSpinner;
TextView addReport;
final ViewHolder viewHolder;
if (row == null) {
LayoutInflater layoutInflater = context.getLayoutInflater();
row = layoutInflater.inflate(resourcecId, parent, false);
viewHolder = new ViewHolder(row);
fromTime = viewHolder.getFromTime();
deleteBtnV = viewHolder.getDeleteBtnVView();
deleteBtnV.setOnClickListener(delete);
billable = viewHolder.getCheckBox();
addReport = viewHolder.getAddButtonView();
// event handler for the button "+" which adds extra row
addReport.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Integer myPosition = (Integer) view.getTag();
HourReport report = list.get(myPosition);
HourReport nReport = new HourReport();
nReport.setClaimDate(report.getClaimDate());
nReport.setEmployeeID(report.getEmployeeID());
nReport.setBillable(false);
nReport.setEngagementContractID(0);
list.add(myPosition + 1, nReport);
notifyDataSetChanged();
}
});
viewHolder.adapter = new SpinerAdapter(context);
taskSpinner = viewHolder.getSpinnerTask();
roleSpinner = viewHolder.getSpinnerRole();
//event handler for the spinner
taskSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View spin,
int selected, long arg3) {
Spinner spinner = (Spinner) spin.getParent();
Integer myPosition = (Integer) spinner.getTag();
viewHolder.adapter.setSelected(selected);
String task = viewHolder.adapter.getSelectcetdTask();
long engmId = viewHolder.adapter.getSelectedTaskID();
rowBean = getModel(myPosition);
rowBean.setTaks(task);
rowBean.setEngagementContractID(engmId);
selectedItems.put(myPosition, selected);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
////event handler for the spinner
roleSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View spin,
int selectedRole, long arg3) {
Spinner spinner = (Spinner) spin.getParent();
Integer myPosition = (Integer) spinner.getTag();
selectedRoles.put(myPosition, selectedRole);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
fromTime = viewHolder.getFromTime();
toTime = viewHolder.getToTime();
fromTime.setOnClickListener(onClickLisOnDateFrom);
toTime.setOnClickListener(onClickLisOnDateTo);
billable.setOnClickListener(checkBoxListener);
row.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) row.getTag();
fromTime = viewHolder.getFromTime();
toTime = viewHolder.getToTime();
taskSpinner = viewHolder.getSpinnerTask();
roleSpinner = viewHolder.getSpinnerRole();
total = viewHolder.getTotal();
billable = viewHolder.getCheckBox();
TextView date = viewHolder.getDate();
deleteBtnV = viewHolder.getDeleteBtnVView();
addReport = viewHolder.getAddButtonView();
}
HourReport model = getModel(position);
Integer selection = 0;
if (selectedItems.get(position) != null) {
selection = selectedItems.get(position);
}
int selectionR = 0;
if (selectedRoles.get(position) != null) {
selectionR = selectedRoles.get(position);
}
viewHolder.getFromTime().setText(
parseDateToString(model.getTimeStarted()));
viewHolder.getToTime().setText(
parseDateToString(model.getTimeFinished()));
viewHolder.getTotal().setText(
convertDoubleTotToStringTot(model.getTotal()));
viewHolder.getDate().setText(
parseDateToStringDDate(model.getClaimDate()));
viewHolder.getCheckBox().setChecked(model.isBillable());
Log.e("", "tag " + selection + " date " + model.getClaimDate());
viewHolder.taskSpinner.setSelection(selection);
viewHolder.roleSpinner.setSelection(selectionR);
fromTime.setTag(Integer.valueOf(position));
toTime.setTag(Integer.valueOf(position));
taskSpinner.setTag(Integer.valueOf(position));
roleSpinner.setTag(Integer.valueOf(position));
billable.setTag(Integer.valueOf(position));
deleteBtnV.setTag(Integer.valueOf(position));
addReport.setTag(Integer.valueOf(position));
return row;
}![here you have screen shoot of single row][1]
Create a single instance of OnClickListener (for example as an inner class) and assign this instance to every widget. If you need to know which row this widget belongs to, you can call setTag("pos", position) on that widget. By doing this you will be able to get position by calling view.getTag("pos") in onClick(View view) method of the listener. Hope this helps.
I'm trying to do a simple query of my database, where a unique Identification number is stored for a PendingIntent. To allow me to cancel a notification set by AlarmManager if needed.
The insertion of a value works fine, but I am unable to overcome the error:
java.lang.IllegalArgumentException: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters.
Database structure:
public class DBAdapter {
private static final String TAG = "DBAdapter";
public static final String KEY_ROWID = "_id";
public static final String TASK = "task";
public static final String NOTIFICATION = "notification";
public static final int COL_ROWID = 0;
public static final int COL_TASK = 1;
public static final int COL_NOTIFICATION = 2;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, TASK, NOTIFICATION};
// DB info: it's name, and the table.
public static final String DATABASE_NAME = "TaskDB";
public static final String DATABASE_TABLE = "CurrentTasks";
public static final int DATABASE_VERSION = 3;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key, "
+ TASK + " text not null, "
+ NOTIFICATION + " integer"
+ ");";
Now I have created a method to extract the notification ID from the database as needed, using the following code:
public int getNotifID(long notifID){
String[] x = {ALL_KEYS[2]};
String[]args = new String[]{NOTIFICATION};
String where = NOTIFICATION + "=" + notifID;
int y = 0;
//String select = "SELECT "+NOTIFICATION+" FROM "+DATABASE_TABLE+" WHERE "+notifID+"="+NOTIFICATION;
//Cursor c = db.rawQuery(select,new String[]{});
Cursor c = db.query(true,DATABASE_TABLE,x,Long.toString(notifID),args,null,null,null,null,null);
if (c!= null && c.moveToFirst()){
y = c.getInt(COL_NOTIFICATION);
}
return y;
}
As you can see I have attempted to do this both with a rawQuery and a regular query, but with no success.
Rewrite your raw query to:
String select = "SELECT "+NOTIFICATION+" FROM "+DATABASE_TABLE+" WHERE "+NOTIFICATION+"=?";
Cursor c = db.rawQuery(select,new String[]{""+notifId});
if(c!=null && c.getCount()>0) {
c.moveToFirst();
}
c.close();
In GWT 2.5 RC CellTableBuilder API was introduced but there are no comprehensive documentation available yet. Is there any tutorial\example of implementing on-demand custom row building with CellTableBuilder? The only example I've found so far was this one http://showcase2.jlabanca-testing.appspot.com/#!CwCustomDataGrid but it is quite confusing for me.
So, my goal is to create extra row containing widget that provides details about clicked row in a table.
I've found suitable solution for this problem. Here is the code sample:
public class CustomCellTableBuilder extends AbstractCellTableBuilder<Object>{
//here go fields, ctor etc.
//ids of elements which details we are going to show
private Set elements;
#Override
protected void buildRowImpl(Object rowValue, int absRowIndex){
//building main rows logic
if(elements.contains(absRowIndex)){
buildExtraRow(absRowIndex, rowValue);
elements.add(absRowIndex);
}
}
private void buildExtraRow(int index, Object rowValue){
TableRowBuilder row = startRow();
TableCellBuilder td = row.startTD().colSpan(getColumns().size());
DivBuilder div = td.startDiv();
Widget widget = new Widget();
//update widget state and appearance here depending on rowValue
div.html(SafeHtmlUtils.fromTrustedString(widget.getElement().getInnerHTML()));
div.end();
td.endTD();
row.endTR();
}}
It should be mentioned, that when you handle some event which leads to appearance of extra row, you should invoke redrawRaw(rowIndex) on CellTable which is attached to TableBuilder. And before this call it is necessary to add target row ID to elements Set.
Hope this was helpful.
I have created this class for expanding rows in GWT. It takes a column that you want to expand and replaces it with a place holder that can have 2 states.
I use it like this:
PlaceHolderColumn<Notification, SafeHtml> placeholder = new PlaceHolderColumn<Notification, SafeHtml>(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(Notification object) {
return SafeHtmlUtils.fromSafeConstant(getSelected() ? "<i class=\"glyphicon glyphicon-chevron-down\"></i>"
: "<i class=\"glyphicon glyphicon-chevron-right\"></i>");
}
};
notificationsTable.setTableBuilder(new ExpandableCellTableBuilder<Notification, SafeHtml>(notificationsTable, columnBody, placeholder));
I have access to glyphicon so I use those instead of the default placeholder column which is +/-
< Image here... but for lack of reputation :( >
columnBody in the above code sample is just a standard column that will span the width of the table. The place holder will be displayed in its place in whatever position columnBody was configured to sit at.
Hope that helps someone :)
public class ExpandableCellTableBuilder<T, U> extends AbstractCellTableBuilder<T> {
private Column<T, U> expandColumn = null;
private PlaceHolderColumn<T, ?> placeholderColumn = null;
private final String evenRowStyle;
private final String oddRowStyle;
private final String selectedRowStyle;
private final String cellStyle;
private final String evenCellStyle;
private final String oddCellStyle;
private final String firstColumnStyle;
private final String lastColumnStyle;
private final String selectedCellStyle;
public static class ExpandMultiSelectionModel<T> extends AbstractSelectionModel<T> {
Map<Object, T> selected = new HashMap<Object, T>();
/**
* #param keyProvider
*/
public ExpandMultiSelectionModel(ProvidesKey<T> keyProvider) {
super(keyProvider);
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.view.client.SelectionModel#isSelected(java.lang.Object)
*/
#Override
public boolean isSelected(T object) {
return isKeySelected(getKey(object));
}
protected boolean isKeySelected(Object key) {
return selected.get(key) != null;
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.view.client.SelectionModel#setSelected(java.lang.Object, boolean)
*/
#Override
public void setSelected(T object, boolean selected) {
Object key = getKey(object);
if (isKeySelected(key)) {
this.selected.remove(key);
} else {
this.selected.put(key, object);
}
scheduleSelectionChangeEvent();
}
}
public static abstract class PlaceHolderColumn<T, C> extends Column<T, C> {
private boolean isSelected;
/**
* #param cell
*/
public PlaceHolderColumn(Cell<C> cell) {
super(cell);
}
protected boolean getSelected() {
return isSelected;
}
}
private int expandColumnIndex;
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn) {
this(cellTable, expandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), null);
}
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, SelectionModel<T> selectionModel) {
this(cellTable, exandColumn, selectionModel, null);
}
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, PlaceHolderColumn<T, ?> placeHolder) {
this(cellTable, exandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), placeHolder);
}
/**
* #param cellTable
* #param columnBody
*/
public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn, SelectionModel<T> selectionModel,
PlaceHolderColumn<T, ?> placeHolder) {
super(cellTable);
this.expandColumn = expandColumn;
this.cellTable.setSelectionModel(selectionModel);
if (placeHolder == null) {
this.placeholderColumn = new PlaceHolderColumn<T, String>(new TextCell()) {
#Override
public String getValue(T object) {
return getSelected() ? "-" : "+";
}
};
} else {
this.placeholderColumn = placeHolder;
}
// Cache styles for faster access.
Style style = cellTable.getResources().style();
evenRowStyle = style.evenRow();
oddRowStyle = style.oddRow();
selectedRowStyle = " " + style.selectedRow();
cellStyle = style.cell();
evenCellStyle = " " + style.evenRowCell();
oddCellStyle = " " + style.oddRowCell();
firstColumnStyle = " " + style.firstColumn();
lastColumnStyle = " " + style.lastColumn();
selectedCellStyle = " " + style.selectedRowCell();
}
/*
* (non-Javadoc)
*
* #see com.google.gwt.user.cellview.client.AbstractCellTableBuilder#buildRowImpl(java.lang.Object, int)
*/
#Override
protected void buildRowImpl(T rowValue, int absRowIndex) {
// Calculate the row styles.
SelectionModel<? super T> selectionModel = cellTable.getSelectionModel();
final boolean isSelected = (selectionModel == null || rowValue == null) ? false : selectionModel.isSelected(rowValue);
boolean isEven = absRowIndex % 2 == 0;
StringBuilder trClasses = new StringBuilder(isEven ? evenRowStyle : oddRowStyle);
if (isSelected) {
trClasses.append(selectedRowStyle);
}
// Add custom row styles.
RowStyles<T> rowStyles = cellTable.getRowStyles();
if (rowStyles != null) {
String extraRowStyles = rowStyles.getStyleNames(rowValue, absRowIndex);
if (extraRowStyles != null) {
trClasses.append(" ").append(extraRowStyles);
}
}
// Build the row.
TableRowBuilder tr = startRow();
tr.className(trClasses.toString());
// Build the columns.
int columnCount = cellTable.getColumnCount();
for (int curColumn = 0; curColumn < columnCount; curColumn++) {
Column<T, ?> column = cellTable.getColumn(curColumn);
if (column == expandColumn) {
expandColumnIndex = curColumn;
column = placeholderColumn;
placeholderColumn.isSelected = isSelected;
}
// Create the cell styles.
StringBuilder tdClasses = new StringBuilder(cellStyle);
tdClasses.append(isEven ? evenCellStyle : oddCellStyle);
if (curColumn == 0) {
tdClasses.append(firstColumnStyle);
}
if (isSelected) {
tdClasses.append(selectedCellStyle);
}
// The first and last column could be the same column.
if (curColumn == columnCount - 1) {
tdClasses.append(lastColumnStyle);
}
// Add class names specific to the cell.
Context context = new Context(absRowIndex, curColumn, cellTable.getValueKey(rowValue));
String cellStyles = column.getCellStyleNames(context, rowValue);
if (cellStyles != null) {
tdClasses.append(" " + cellStyles);
}
// Build the cell.
HorizontalAlignmentConstant hAlign = column.getHorizontalAlignment();
VerticalAlignmentConstant vAlign = column.getVerticalAlignment();
TableCellBuilder td = tr.startTD();
td.className(tdClasses.toString());
if (hAlign != null) {
td.align(hAlign.getTextAlignString());
}
if (vAlign != null) {
td.vAlign(vAlign.getVerticalAlignString());
}
// Add the inner div.
DivBuilder div = td.startDiv();
div.style().outlineStyle(OutlineStyle.NONE).endStyle();
// Render the cell into the div.
renderCell(div, context, column, rowValue);
// End the cell.
div.endDiv();
td.endTD();
}
// End the row.
tr.endTR();
if (isSelected) {
buildExpandedRow(rowValue, absRowIndex, columnCount, trClasses, isEven, isSelected);
}
}
/**
* #param trClasses
*
*/
private void buildExpandedRow(T rowValue, int absRowIndex, int columnCount, StringBuilder trClasses, boolean isEven, boolean isSelected) {
TableRowBuilder tr = startRow();
tr.className(trClasses.toString());
Column<T, ?> column = expandColumn;
// Create the cell styles.
StringBuilder tdClasses = new StringBuilder(cellStyle);
tdClasses.append(isEven ? evenCellStyle : oddCellStyle);
tdClasses.append(firstColumnStyle);
if (isSelected) {
tdClasses.append(selectedCellStyle);
}
tdClasses.append(lastColumnStyle);
// Add class names specific to the cell.
Context context = new Context(absRowIndex, expandColumnIndex, cellTable.getValueKey(rowValue));
String cellStyles = column.getCellStyleNames(context, rowValue);
if (cellStyles != null) {
tdClasses.append(" " + cellStyles);
}
// Build the cell.
HorizontalAlignmentConstant hAlign = column.getHorizontalAlignment();
VerticalAlignmentConstant vAlign = column.getVerticalAlignment();
TableCellBuilder td = tr.startTD();
td.colSpan(columnCount);
td.className(tdClasses.toString());
if (hAlign != null) {
td.align(hAlign.getTextAlignString());
}
if (vAlign != null) {
td.vAlign(vAlign.getVerticalAlignString());
}
// Add the inner div.
DivBuilder div = td.startDiv();
div.style().outlineStyle(OutlineStyle.NONE).endStyle();
// Render the cell into the div.
renderCell(div, context, column, rowValue);
// End the cell.
div.endDiv();
td.endTD();
// End the row.
tr.endTR();
}