×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

Enable / disable "Save" button
2

Enable / disable "Save" button

Enable / disable "Save" button

(OP)
I have a grid based on a cursor.
I want to enable/disable the "Save" button if the user modified or revert to the modifications regards to any cursor's records.
I tried to use SYS(2017) function but without any success.

RE: Enable / disable "Save" button

Sys(2017) wouldn't have anything to do with what you say you want to do.

You probably want GetFldState() and Getnextmodified() instead if you're just trying to determine if a cursor is modified.

Can you clarify your question a bit? It's unclear why you need a checksum of the record to determine if something has changed when VFP will tell you that directly.



RE: Enable / disable "Save" button

Rather than having a single button that boths saves and reverts, it would make much more sense to have separate Save and Revert buttons. This makes programming easier and - more importantly - will be easier for the user to understand.

The Revert button merely needs to call TABLEREVERT(). The Save button calls TABLEUPDATE(). This assumes that your cursor is buffered. Both buttons would start out disabled. You would also have an Edit button. When the user clicks Edit, the other two buttons become enabled and the Edit button becomes disabled. When the click the other two buttons, the reverse happens.

Actually, if the grid's underlying data is a cursor rather than a physical table, things are a bit different. You don't need to worry about buffering. The Cancel button would simply close the cursor, so all the edits would disappear. The Save button would copy the contents of the cursor to a physical table. But I can't see any reason for using a cursor in that way.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: Enable / disable "Save" button

Hi,
If the very good advise here given by Mike is still not workable for you, you can also consider to add the class wizbtns.txtbtns or the class wizbtns.picbtns (make sure you have all the pictures available) to your form.
The Wizbtns class can be found in the Home()+Wizards directory.
The use of this class will save you lots of coding and errors, just drop either one on your form.
In general the use of the different wizard classes are not recommended, some have serious errors, but this one is a good exception.
And once you are familiar with it and you use the wizbtns.picbtns you can change the pictures to a more modern UI.
Regards,
Koen

RE: Enable / disable "Save" button

Mike,

I see a good reason for using a cursor, you can query just a few records to edit and the grid scrollbar is fine, in comparison with a table recordsource and a filter.
The cursor could be a view curor, which means TABLEUPDATE() and TABLEREVERT would work, you'd have the typical connection you also have with a DBF directly. And the grid works fine with a view REQUERY.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Enable / disable "Save" button

Point taken, Olaf. But my basic point remains valid. Rather than having a single button which aims to provide two opposing functions (save and revert), make them into separate buttons.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: Enable / disable "Save" button

I wouldn't even know how that would work. Once you disable a button it has no function. So there is no way a save button becoes a revert button when disabled, it won't make sense anyway. In the situation without changes, you don't have anything to save or revert, in situations with changes you have to save or revert. So there is no way to toggle between save and revert. You either need none of these options or both options.

I think the question was more general about how to see a buffer has changes, GetNextModified(0) will tell you, but will also move there. If the return value is 0, there is no modification, though. There is no event about this, that would trigger the buttons to enabled once a modification starts, simply keep them active anyway, that's the easiest solution. Feedback from saving/reverting data, instead of disabling the save or revert buttons.

If you subclassed all controls an easy way to notice changes is to set a changed flag in any interactive/programmatic change event. in these events you may then also cause the buttons to change their state. You can have a property "ismodified" and create an assign method ismodified_assign. You change event code will always set this .T., your save/revert buttons will set this .F., whatever it is can then also become the state of enabled, set by this assign method, so that assign method does not only store the ismodified state, but sets buttons in the correct model. That's a possible solution. Once I thought triggers would be nice for cursors, but then DBC stored procedures run outside of the scope of the current form, you wouldn't cause forms to adapt to the new situation anyway. It's likely for that reason that was never introduced.

Introducing an edit mode, as Mike also suggested, would also introduce a moment to toggle save and revert button active once edit mode begins and let save or revert end this mode, toggling button states.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Enable / disable "Save" button

(OP)
Dear friends,

First off all I want to ask you all to excuse me about my silence into last two days. I had a specially event into family (actually was my niece's christening) so I must keep away from my computer.

Second I must tell you that english is not my native language so I am afraid that you didn't understand my problem.
So, I have a form, a grid and a "Save" button on it (initially "Disabled"). In grid I have some columns with CheckBox inside.

The requirements is that when it change the values of one or more checkbox's from one or more records, the state of the "Save" button to be change from "Enabled" to "Disabled" or from "Disabled" to "Enabled".

In other words, if I change the values for Check1 or Check2, the state for "Save" will be "Enabled" and if I change back the values to the initial, the state will be again "Disabled".

So, I mind that for achievement of the requirements, I must calculate a CheckSum for each record and store it. When I click onto one CheckBox, I calculate again the CheckSum and compare it with the initial one.

With my ideas and your help, now, I have the following solution. It works, but I wonder if there is another solution maybe more simple.

In the Init method of the Form:

CODE -->

lcRecordSource = "Select ... SPACE(32) as CheckSum, .F. as WasModified ";
	+ "FROM ... ";
	+ "INNER Join ... ";
	+ "WHERE ... = ";
	+ "INTO Cursor Temp Readwrite"

Thisform.Grid1.RecordSource = lcRecordSource

If _Tally <> 0
	Select Temp
	Locate
	Do While Not Eof()
		lcCheckSum = Sys(2017, "CheckSum, WasModified", 1, 1)
		Replace Temp.CheckSum With lcCheckSum
		Skip
	Enddo
	Locate
Endif 

In the Grid1.Column3.Check1.Click and so on:

CODE -->

lcCheckSum = Sys(2017, "CheckSum, WasModified", 1, 1)
If lcCheckSum  <> Temp.CheckSum
	Replace Temp.WasModified With .T.
Else
	Replace Temp.WasModified With .F.
Endif

Thisform.Refresh 

In the Refresh method of the Form:

CODE -->

Select WasModified From Temp Where Temp.WasModified = .T. Into Cursor crWasModified

If _Tally = 0
	Thisform.commandgroup1.Save.Enabled = .F.
Else
	Thisform.commandgroup1.Save.Enabled = .T.
Endif

Select Temp 

RE: Enable / disable "Save" button

Eugen,

First, no need to apologise. It was the weekend, and dealing with VFP issues is not the highest priority.

So, it seems that your problem comes down to this: you need to know if a record has been edited. If so, then calculating the checksum is not the normal way to do that. It is much easier to use the GETNEXTMODIFIED() function. Pass itr zero as the first parameter, and the cursor's alias as the second parameter. If the function returns a value greater than zero, it means the cursor has been edited.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: Enable / disable "Save" button

I second Mike if you look into our earlier answers not just GETNEXTMODIFIED but also the concept of buffering changes is mentioned. VFP has its own ways of knowing about the changes, namely the buffer. So it all boils down to using that concept instead of computing checksums.

Of course, that concept works too, but you're reimplementing something already existing.

There's one caveat with the way VFPs own modification detection works, even if you change values back to their old value, that doesn't automatically revert the field state to unmodified. Your checksum mechanism would detect that ignoring the very small risk you can get the same checksum from two changes, checksums or hashes are actually designed to avoid that, but simpler checksums as crc16 only have a low set of checksum values making it possible in the long run.

For that reason alone VFPs own field state mechanism is better, even though it lacks detecting a reverted value, especially that of boolean fields can occur very often.

What you would need to check is OLDVAL(alias.field) vs alias.field value and if that's the same you can use SetFldState to override VFPs evaluation of that as modification. VFP indeed only detects that there was some change and once there was it doesn't automatically revert this to detect that as unchanged in net effect.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Enable / disable "Save" button

A little more detail about the instruments you have at hand, for the extreme cases like two (or more) users editing the same record.

If your user session has loaded some data it memorizes this as OLDVAL() values, another user editing data from the same initial state and already saving his changes earlier can store a value you can read via CURVAL() if the underlying alias is the central DBF file. In case you use the view that's less important to know, as reverting the field state already means VFPs TABLEUPDATE will skip this field when generating its UPDATE SQL statement and not overwrite the already committed change.

But caution, if you store CURVAL(alias.field) into alias.field to load that committed change, that will still mean that field state is changed and saved and causes an update conflict, even though it saves the already saved value. So it's important you just notice no change from OLDVAL(alias.field) to alias.field (which by the way is the buffered changed value). If that's the same but different to CURVAL(alias.field) it will only be saved and revert the saved change, if that field state remains at changed. You can even have a totally different value than OLDVAL() and CURVAL() in the buffer, as soon as you signal to VFP via SETFLDSTATE() this field should be handled as unchanged, it will not be written back.

Overall look into buffering, starting with SET MULTILOCKS ON, CURSORSETPROP("Buffering",...), TABLEUPDATE(), TABLEREVERT(), OLDVAL(), CURVAL(), GETFLDSTATE(), SETFLDSTATE(), GETNEXTMODIFIED() and some more.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close