I have a remote database mysql, connected to the application (C++ Builder 6) using ADOConnection, and DBGrid, which is displayed data (ADOConnection-ADOTable-Dataset-DBGrid).
ADOTable by default can not be edited; by clicking on the button "Edit", I write "readonly = false", and edit data.
After editing the line (for example, the cursor moved to the line above), I need to prompt the user ("Save changes? Y / N"), and when you select "No", to undo the changes.
On request there is no problem. The question is how I should undo the changes (preferably still on the client, ie ADOTable or DBGrid)?
Okay, got it myself. Three weeks of headache, and five rows of code.
if (DataSet->State == dsEdit || DataSet->State == dsInsert){
int res = MessageBox(Handle, "Save changes?", "Confirm", MB_YESNO);
if (res == IDNO){
DataSet->Cancel();
Abort();
}
}
Also, if we click on other field, and select "No", cursor would not move. But that's not a problem for now.
Related
In this instance I am not "stuck" but looking for some 'guidance' on how to perform a GUI layout mechanism that makes sense and easy to construct. I am using a TreeControl that visually "matches" Winamp's options/preferences dialog for all the settings and program options.
TO BE CLEAR: This is not something I've ever attempted and looking for user input to help me get across the finish line.
I have 6 items in the 'tree' (the 'parent') and 5 'subitems'. I have it fully constructed and I can get the data from whatever node is selected (which I'll post below images).
I am using a "do.Modal dialog" and, when I click on the tree node, I want the right side of the dialog to update to the needed controls for that node function. The execution of controls through "show" and "hide" to me seems pretty easy. The issue I have is the how to do the visual "static" controls in the resource editor when each "node paged" controls may or may not sit on top of each other visually during design time. During run time, when each node is selected on the nodes controls will be active but during design time, I may have controls sitting on top of each other and will be a logistical nightmare trying to sort out their positions etc.
How do I resolve that aspect of building it? I think of it as a select: 'node' show: 'option page controls' so I get the logic; I'm just wondering if I should have separate "popup" pages and call those … or deal with the controls directly. Does that makes sense?
I've done some searching on how to do this, but the examples are all over the place and I figured asking here makes the most sense. I'm sure there are multiple ways to do this, I'm just looking for the shortest path and easiest to maintain and possibly expand on the options in the future.
The examples of the dialog and the source code I'm using:
Here is the initialization code:
BOOL CSettingsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
HTREEITEM hParent, hToolbars, hColorScheme, hTabStyles, hPowerUser,
hResetApp;
//HTREEITEM hCompany, hLevel, hLevelNext; // Used in core example, not needed here
hParent = m_TreeCtrl.InsertItem((L"Preferences"), TVI_ROOT);
hToolbars = m_TreeCtrl.InsertItem((L"Toolbars"), hParent);
hColorScheme = m_TreeCtrl.InsertItem((L"Color Scheme"), hParent);
hTabStyles = m_TreeCtrl.InsertItem((L"Tab Styles"), hParent);
hPowerUser = m_TreeCtrl.InsertItem((L"Power User"), hParent);
hResetApp= m_TreeCtrl.InsertItem((L"Reset All Options"), hParent);
m_TreeCtrl.Expand(hParent, TVE_EXPAND);
m_TreeCtrl.SelectItem(hParent);
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Preferences Settings"));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
Here is the dialog framework that I'm starting from scratch with just to arrive here:
void CSettingsDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
//LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
//SetDlgItemInt(IDC_TXT_TREE1, m_TreeCtrl.GetItemData(pNMTreeView->itemNew.hItem));
//*pResult = 0;
HTREEITEM sel = m_TreeCtrl.GetSelectedItem();
CPoint point;
CString str;
GetCursorPos(&point);
m_TreeCtrl.ScreenToClient(&point);
UINT flags = 0;
HTREEITEM hitItem = m_TreeCtrl.HitTest(point, &flags);
if (hitItem && sel != hitItem)
{
sel = hitItem;
m_TreeCtrl.SelectItem(sel);
str = m_TreeCtrl.GetItemText(sel);
//MessageBox((LPCTSTR)str); // Just to verify.
}
if (str == "Preferences")
{
this->SetWindowText(_T("Preferences Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Preferences Settings"));
}
if (str == "Toolbars")
{
this->SetWindowText(_T("Toolbars Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Toolbars Settings"));
}
if (str == "Color Scheme")
{
this->SetWindowText(_T("Color Scheme"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Color Scheme Settings"));
}
if (str == "Tab Styles")
{
this->SetWindowText(_T("Tab Styles Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Tab Styles Settings"));
}
if (str == "Power User")
{
this->SetWindowText(_T("Power User Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Power User Settings"));
}
if (str == "Reset All Options")
{
this->SetWindowText(_T("Reset All Settings"));
GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T("Reset All Settings"));
}
*pResult = 0;
}
So as shown, you can see that I have the ability to change the static caption to the "active" page node that is selected from the tree. I'm looking to solve the best way to handle the GUI elements that will go on the right side....
Some controls for example will be:
Color scheme Node: 5 check boxes for theme changing
Toolbars Node: Radio button for Docked or Floating
Power User Node: Checkbox to disable user warning within program operation
Tab Styles Node: Radio buttons to select flat, 3d, whatever.
and when the user "selects" whatever it writes it to the registry and then I call the function to read the data blah blah blah...
So that is where I'm at. Does anyone have any suggestions on a course of action, so I don't paint myself into a corner?
Although I can't actually speak for how the authors of the "Winamp" software implemented their UI, I would suggest that you consider using a property sheet for your case, where each set of controls can be implemented as separate property pages, each of which will be defined (both in the resource script and in the C++ code) in ways very similar to individual modal dialog boxes.
The 'classic' property sheet has a horizontal row of tabs (normally, at the top of the sheet) to select each page, as shown in the sample below. Indeed, some sources/platforms refer to a property sheet as a "tabbed dialog".
However, the new(ish) CMFCPropertySheet class allows you to replace that tab control with one of several other options, which will show as separate 'panes' (on the left-hand side of the sheet). To use one of these alternative styles, call the SetLook() member function in your constructor override with the CMFCPropertySheet::PropSheetLook_Tree enum value. The example shown in the link is not exactly what you have shown in your question, but the CMFCPropertySheet and CMFCPropertyPage classes allow many, many customizations to their appearance and style.
I have never actually used the PropSheetLook_Tree style, but the image below shows "one I made earlier" with the PropSheetLook_OutlookBar style.
I have multiple File Browser Item fields on one page of Application in Oracle Apex.
What happens: When I miss any Item for which validation error fires, I want to hold that file to the browser but I usually loose it if I get that validation error. Is there a solution for the same like other Items fields hold previous value except File Browser Item field. Please see below ss:
Anshul,
APEX 4.2 is very old and no longer supported. A later (or preferably latest) version of APEX will behave differently as Dan explained above.
Can you import your application into apex.oracle.com (which is running APEX 20.1) and you will probably see better results. Based on this you can hopefully use it as justification to upgrade your environment.
Regards,
David
Go to your page-level attributes and a function like the following in the Function and Global Variable Declaration:
function validateItems(request) {
var $file1 = $('#P68_FILE_1');
var $file2 = $('#P68_FILE_2');
var errorsFound = false;
if ($file1.val() === '') {
errorsFound = true;
// Show item in error state
}
if ($file2.val() === '') {
errorsFound = true;
// Show item in error state
}
if (!errorsFound) {
// I think doSubmit was the name of the function back then. If not, try apex.submit
doSubmit(request);
} else {
// Show error message at top of page, I'll use a generic alert for now
alert('You must select a file for each file selector.');
}
}
Then, right-click the Create button and select Create a Dynamic Action. Set the name of the Dynamic Action to Create button clicked.
For the Action, set Type to Execute JavaScript Code. Enter the following JS in code:
validateItems('CREATE');
Finally, ensure that Fire on Initialization is disabled.
Repeat the process for the Save button, but change the request value passed to validateItems to SAVE.
Created an report with checkbox using apex_item and when checked more than one check box i will display alert message "not to check more than one checkbox with ok button " after clicking ok it should be unchecked . please find my JavaScript code that displays alert message
if($("input[type=checkbox]:checked").length > 1)
{
var msg = alert('You are not allowed to select more than one employee');
}
It's best to use the APEX JavaScript APIs for this type of thing. You can find them here: https://apex.oracle.com/jsapi
If you're getting started with JavaScript and APEX, you may find these slides useful: https://www.slideshare.net/DanielMcGhan/getting-started-with-javascript-for-apex-developers
Here's a solution that should work for you (just change the name of the item to match yours):
var cbItem = apex.item('P1_CHECKBOX');
if (cbItem.getValue().length > 1) {
alert('You are not allowed to select more than one employee');
cbItem.setValue(); // Passing nothing to clear the value
}
TLDR:
I have the ref of my tabs
#ViewChild('tabsPage') tabRef: Tabs;
I need to get the nav stack of the current tab, check if it can go back and do go back if needed.
Full story:
I have a tabs page which I arrive from another page with a custom animation.
The behavior of my tabs when the user presses the hardware back button must be as follow:
If the user is in the tab 0, go back with custom animation;
If the user isn't in the tab 0, go to tab 0;
If the user has navigated in the current tab, go back in the nav stack of that tab.
Trying to achieve that behavior, I used this code in my tab root page, inside of ionViewDidEnter():
if (this.tabRef.getSelected().index == 0) {
this.navCtrl.pop({
animation: 'nav-shrink'
, direction: 'back'
})
} else {
this.tabRef.select(0);
}
The problem is: when I have navigated in another tab, the back button won't go back in the tab (from the detail to the list, for instance), it will go back to the tab 0 at once.
ionViewWillLeave() isn't called when I navigate further in any tab, so i can't deregister the backButtonAction.
The solution would be to check if the current tab can go back, so, instead of going to tab 0 or going back from the tabs page with a custom animation, I would just nav.pop() the current tab.
https://ionicframework.com/docs/v2/api/navigation/NavController/
canGoBack()
Returns true if there’s a valid previous page that we can pop back to. Otherwise returns false.
Apparently, the Tab itself is the NavController. So I solved my problem this way:
if (this.tabRef.getSelected().canGoBack()) {
this.tabRef.getSelected().pop();
} else if (this.tabRef.getSelected().index == 0) {
this.navCtrl.pop({
animation: 'nav-shrink'
, direction: 'back'
})
} else {
this.tabRef.select(0);
}
I am trying to implement a saveui pipeline processor in Sitecore 6. Basically I have created a custom processor that presents the user with a popup message depending on which fields they may have changed on the item and what the new data is. If they made certain changes then they are presented with a popup asking them if they want to continue. If they answer no then the pipeline is aborted. That is all working. However I noticed that when you abort the pipeline all Sitecore seems to do is not save. All of the changes that the user made to the content item are still there in the UI. If you navigate away from the item in Sitecore, it will prompt you if you want to save the changes. Is there some way that I can get the Sitecore UI to cancel all of the changes and revert all of the fields back to their initial values? Aborting the pipeline is good because I don't want to save, but I also want to cancel the save in the UI too. Does anyone know how to do this?
Sample Code:
public class CustomSaveProcessor
{
public void Process(SaveArgs args)
{
Sitecore.Diagnostics.Assert.ArgumentNotNull(args, "args");
if(args.Items == null)
{ return; }
if(args.IsPostback)
{
if(args.Parameters["runContext"] == "firstQuestion")
{
if((args.Result == null) || (args.Result == "null") || (args.Result == "no") || (args.Result == "cancel"))
{
args.AbortPipeline();
//Should there be something here to tell the Sitecore UI to reset the values?
return;
}
else
{
//User has answered first question Yes
//This means they want to save the changes to the item
//We also want to ask a second question that effects other content items
SheerResponse.YesNoCancel("Do you want to also modify other items?", "300px", "200px");
args.Parameters["runContext"] = "secondQuestion";
args.WaitForPostBack();
}
}
else
{
if(args.Result == "yes")
{
//This is the answer to second question
//Custom code here to modify other content items
}
//We are completely done now.
return;
}
}
else
{
//Ask the user the first question
SheerResponse.YesNoCancel("Are you sure you want to proceed?", "300px", "200px");
args.Parameters["runContext"] = "firstQuestion";
args.WaitForPostback();
}
}
}
You can just reload the content tree with the following code.
String refresh = String.Format("item:refreshchildren(id={0})", Sitecore.Context.Item.Parent.ID);
Sitecore.Context.ClientPage.SendMessage(this, refresh);
Or as Corey discovered if you want to refersh the item you'd use
String refresh = String.Format("item:load(id={0})", myOriginalItem.ID);
Sitecore.Context.ClientPage.SendMessage(this, refresh);
See this post for more details
I think you can try to reload the current content item after aborting your custom save handler to set the intial values of the content item. Not sure if you then still get the "alert message".
Take a look at this post with a similiar issue