How to show NSAlert using Sheet window in separate .XIB files? - applescript-objc

I have a button to perform a task and if an error occurs during the process a warning is displayed using NSAlert "Sheet window"
in this moment I am using multiple .XIB files in a project, I can't display the "Sheet window" in these files(.XIB) is there any way to do this?
Thanks in advance!
on clickedButton:sender
try
--some code here...
on error errorMsg
set alert to current application's NSAlert's alloc's init()
tell alert
its setMessageText:"This is an ERROR"
its setInformativeText: "Error: " & errorMsg
its setAlertStyle:2
its beginSheetModalForWindow:theWindow modalDelegate:me didEndSelector:(missing value) contextInfo:(missing value)
end tell
end try
end clickedButton:

If you don't have a window to put the sheet on, you will need to run the normal alert dialog. You can test for a window by using NSApp's mainWindow(), which will be missing value if there isn't one, and do either alert's runModal() or the sheet depending on the result:
use framework "Cocoa"
use scripting additions
property theWindow : missing value -- this will be the main window...
property sheetOrNot : true -- ... or not, depending on this flag
on run -- this lets the example run from the Script Editor if you forget the main thread thing
my performSelectorOnMainThread:"doWindow" withObject:(missing value) waitUntilDone:true
my performSelectorOnMainThread:"doAlert" withObject:(missing value) waitUntilDone:true
end run
on doWindow() -- create a window to play with
set theWindow to current application's NSWindow's alloc's initWithContentRect:{{200, 400}, {400, 200}} styleMask:7 backing:(current application's NSBackingStoreBuffered) defer:true
set theWindow's releasedWhenClosed to true
if sheetOrNot then tell theWindow to makeKeyAndOrderFront:me
end doWindow
on doAlert() -- show the alert
try
--some code here...
error "oops" -- ...that went badly
on error errorMsg
set alert to current application's NSAlert's alloc's init()
tell alert
its setMessageText:"This is an ERROR"
its setInformativeText:("Error: " & errorMsg)
its setAlertStyle:2
if current application's NSApp's mainWindow() is not missing value then
its beginSheetModalForWindow:theWindow modalDelegate:me didEndSelector:(missing value) contextInfo:(missing value)
else -- no window, so do a normal modal dialog
its runModal()
end if
end tell
end try
end doAlert

Related

How to automatically run a VBA macro (to do regex replacement of e-mail body text) when Outlook inspector has opened a reply/forward e-mail?

I have an Outlook VBA macro that does a regex replacement of some text in a reply/forward e-mail, using the WordMail representation of the e-mail.
I can trigger it from a button added to the ribbon. I want it to execute automatically immediately the inspector has opened, i.e. remove the need to remember to press the button once the editor is displayed. I have tried overloading the Open event, but the message does not appear to be accessible at that point - I think this gets invoked too early. None of the other events appears to be at the correct time.
Thank you for any suggestions.
There are multiple events that you consider handling for such purposes.
The very first option is to handle the NewInspector event which is fired whenever a new inspector window is opened, either as a result of user action or through program code The inspector that was opened is passed as a parameter, so you can subscribe to the Activate event which is fired when an inspector becomes the active window, either as a result of user action or through program code. So, at this stage the item and the inspector window have been initialized and you are free to do any customizations.
You may find the Implement a wrapper for inspectors and track item-level events in each inspector article helpful.
The second option is to handle the MailItem.Reply event which is fired when the user selects the Reply action for an item, or when the Reply method is called for the item, which is an instance of the parent object.
Inspectors.NewInspector event
Occurs whenever a new inspector window is opened, either as a result of user action or through program code
Option Explicit
' In ThisOutlookSession
Private WithEvents myOlInspectors As Inspectors
Private Sub Application_Startup_Temporary()
Set myOlInspectors = Application.Inspectors
End Sub
Private Sub myOlInspectors_NewInspector(ByVal oInspector As Inspector)
' https://learn.microsoft.com/en-us/office/vba/api/outlook.inspectors.newinspector
' Occurs whenever a new inspector window is opened,
' either as a result of user action or through program code
Dim msg As MailItem
If oInspector.CurrentItem.Class = olMail Then
Set msg = oInspector.CurrentItem
If msg.Size > 0 Then
Debug.Print "Subject: " & msg.subject
Debug.Print " Non-zero size message opened."
' Your code here
End If
End If
End Sub
Private Sub myOlInspectors_NewInspector_Test()
myOlInspectors_NewInspector ActiveInspector
End Sub

ApplescriptObjC: text view not updating from bound property

I'm having trouble updating a text view in my AppleScript Xcode (12.5.1) project.
I have:
Bound my text view to my "msg" property, and
Selected "Continuously updates value" in the bindings inspector.
However, when I update the "msg" property the change is not displayed in my text view.
Although my msg property has been updated with the "initializing..." string (as evidenced by the alert message) my text view is not updating.
bindings inspector
connections inspector here
App running with "msg" property displayed in text view (indicating successful binding)
inside appInit function
myAppDelegate code:
property parent : class "NSObject"
property msg : "zig" -- the message
-- IBOutlets
property theWindow : missing value
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
activate
display alert msg -- "zig" property successfully displayed in text view. Binding is apparently set.
set msg to ("initializing…" as string) -- text view not updated.
appInit()
end applicationWillFinishLaunching_
on appInit()
activate
display alert msg -- "initializing"; msg property updated, just not being updated in text view...
end appInit```
Bindings to properties use key-value observing (KVO), which is a mechanism that allows objects to be notified of changes to properties of other objects. AppleScriptObjC properties are set up for this when bound via Xcode, but in order to use this mechanism when changing the property in your script, you need to use a setter to trigger the notification - otherwise the property itself will be changed, but the object will not be notified of the change.
Examples would be:
set my msg to "initializing…" -- using the `my` keyword
setMsg_("initializing…") -- also my setMsg:("initializing…") -- using the built-in setter method
Note that the property will be a Cocoa value, so it will need to be coerced to a string when using it (later in the appInit dialog, for example).

MFC MDI ID_FILE_OPEN Non override, but use the variable for status message

Preface: I have an MFC MDI using the wizard in VS2017 to create the project...it works without issue.
Goal: To use the ID_FILE_OPEN to execute normal document creation without modification but use the same ID to trigger my own function in parallel to write to the output tab at the bottom.
So here is what is happening. When I select file>open from the menu or toolbar button, the file open dialog works as I expect and docs open normally. What I want to do is fire my own function that writes a status message of "File Open Process" in the status output window tab. What I am finding is that even with the message map that uses the ID_FILE_OPEN ID with my unique function (that does work with other IDs that are not system bound) when I debug it and I call the open command, the file dialog opens, but it never enters my unique function to simply write the "File Open Process" string to the output pane. I read about overriding the default handler for this particular variable here:
https://learn.microsoft.com/en-us/cpp/mfc/reference/cwinapp-class?view=msvc-160#onfileopen
I don't want to change that or have to rewrite the file open dialog since it is already handled by the framework, all I want to do is track the ID_FILE_OPEN and have it trigger my function to write the status message for the user. It seems I can do one or the other, but not both at the same time? So below is what my message map looks like and my function, is there a way to track the ID_FILE_OPEN so I can have it do both as I expect?
The message
In my Application.cpp:
I've tried....
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpenMe)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpenMe)
ON_COMMAND(ID_FILE_OPEN, OnFileOpenMe)
BEGIN_MESSAGE_MAP(CApplication, CWinAppEx)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpenMe) // << This never fires even with &CwinApp
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_UPDATE_COMMAND_UI(ID_WINDOW_NEW, DisableNewWindowMenuItem)
END_MESSAGE_MAP()
The status message function in Application.cpp that works with other IDs but is never called from the message map using ID_FILE_OPEN ID:
void CApplication::OnFileOpenMe()
{
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
pMainFrame->m_wndOutput.AddStringStatusTab(_T("File Open Process"));
}
Here is prototype in Application.h
class CApplication : public CWinAppEx
{
protected:
.......... //More message above omitted
afx_msg void DisableNewWindowMenuItem(CCmdUI *ppkCmdUI);
afx_msg void OnFileOpenMe();
}
Ok, I figured out a a more elegant way to handle this without compromising the solution and default framework.
Using this post here:
MFC trigger ID_FILE_OPEN command
I've reformed the message map:
BEGIN_MESSAGE_MAP(CApplication, CWinAppEx)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen) // Leave active, not used, needed to keep control active to call open
ON_COMMAND(ID_FILE_BRANCH_OPEN, OnFileBranchOpen)
END_MESSAGE_MAP()
I changed the ID on the ID_FILE_OPEN to ID_FILE_BRANCH_OPEN in all the menu and buttons that used to call ID_FILE_OPEN.
Using the thread I listed above my function now looks like:
void CApplication::OnFileBranchOpen()
{
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
pMainFrame->m_wndOutput.AddStringStatusTab(_T("File Open Process"));
AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_FILE_OPEN, 0); // Open File Open Dialog and load
}
Note that the ID_FILE_OPEN remains in the message map even if unused/called, my understanding is that it leaves the framework call function/handling in tact while using my new menu ID to trigger the Open File Dialog framework call while also processing my status message as my original intent.
I'm hoping that this may help someone in the future and show a different way to make this work when dealing with system reserved message mappings.
If any of my description of what I did needs clarification, please feel free to add your comments.
Thanks for reading.

Save the state of QCheckBox in file, and load the state when program restarts

In my GUI application, I have some labels in my mainwindow the visibility of the labels are controlled from checkboxes in a dialog which opens when a button (setting) is pressed. Now, it all works fine, i.e. if I open the settings dialog I can check or uncheck the checkboxes; consequently the labels are also set visible or invisible.
mysettingsdialog.cpp
void mysettingsdialog::onclick(bool checked) //by AJ kpi conf
{
if(myCheckBox->isChecked()==true)
{
emit setlabelvisible();
}
else
{
emit setlabelinvisible();
}
}
mainwindow.cpp
MySettingsDialog* myset=new MySettingsDialog(this);
connect(myset,SIGNAL(setlabelvisible()),this,SLOT(enable1()));
connect(myset,SIGNAL(setlabelinvisible()),this,SLOT(disable1()));
void MainWindow::enable1()
{
ui->label->setVisible(true);
qDebug()<<"VISIBLE label";
}
void MainWindow::disable1()
{
ui->label->setVisible(false);
qDebug()<<"INVISIBLE label";
}
Now the problem is, every time my application restarts it does not retain the previous state of the checkboxes. So I was thinking to save the state of the checkbox in a variable and writing it to a file, so whenever my application starts it will read the file and set the status of check box accordingly.
My question is, how can I store the "state" of checkbox in a variable and write it to file. And again use the same to set the state of checkbox ???
I mean reading / writing values from file for QLabels and QLineEdits is easy enough but I am baffled about how to do it with checkbox.
Create a container to store the pointer of each checkbox.
Create another container to store the "state" of each checkbox. For a binary check box, you can use isChecked() to query whether or not a checkbox is checked. Otherwise you can call checkState() to return the state as enum if you use a tri-state check box (see the edit).
When loading settings, assign the state to each check box accordingly.
You may use QSettings to manage the settings and save them as an ini file.
Edit
Just mention there is an option for a tri-state check box. From the document:
QCheckBox optionally provides a third state to indicate "no change".
This is useful whenever you need to give the user the option of
neither checking nor unchecking a checkbox. If you need this third
state, enable it with setTristate(), and use checkState() to query the
current toggle state.

How do I make Visual Studio pause after executing a console application in debug mode?

I have a collection of Boost unit tests I want to run as a console application.
When I'm working on the project and I run the tests I would like to be able to debug the tests, and I would like to have the console stay open after the tests run.
I see that if I run in release mode the console window stays up after the program exits, but in debug mode this is not the case.
I do not want to add 'system("pause");' or any other hacks like reading a character to my program. I just want to make Visual Studio pause after running the tests with debugging like it would if I were running in release mode. I would also like it if the output of tests were captured in one of Visual Studio's output windows, but that also seems to be harder than it should be.
How can I do this?
Try to run the application with the Ctrl + F5 combination.
http://connect.microsoft.com/VisualStudio/feedback/details/540969/missing-press-any-key-to-continue-when-lauching-with-ctrl-f5
In the older versions it would default to the console subsystem even if you selected "empty project", but not in 2010, so you have to set it manually. To do this select the project in the solution explorer on the right or left (probably is already selected so you don't have to worry about this). Then select "project" from the menu bar drop down menus, then select "project_name properties" > "configuration properties" > "linker" > "system" and set the first property, the drop down "subsystem" property to "console (/SUBSYSTEM:CONSOLE)". The console window should now stay open after execution as usual.
Boost test offers the following usage recommendations for Visual Studio that would enable you to run the unit tests automatically at the end of compilation and capture the output into the build window.
The nice side effect of this trick is it enable you to treat test failures as compilation errors. "...you could jump through these errors using usual keyboard shortcuts/mouse clicks you use for compilation error analysis..."
Set a breakpoint on the last line of code.
I just copied from http://social.msdn.microsoft.com/forums/en-US/Vsexpressvc/thread/1555ce45-8313-4669-a31e-b95b5d28c787/?prof=required:
The following works for me :-)
/////////////////////////////////////////////////////////////////////////////////////
Here is another reason the console may disappear. And the solution:
With the new Visual Studio 2010 you might see this behavior even when you use Ctrl + F5 aka "start without debugging". This is most likely because you created an "empty project" instead of a "Win32 console application". If you create the project as a "Win32 console application" you can disregard this as it does not apply.
In the older versions it would default to the console subsystem even if you selected "empty project", but not in Visual Studio 2010, so you have to set it manually. To do this select the project in the solution explorer on the right or left (probably is already selected so you don't have to worry about this).
Then select "project" from the menu bar drop down menus, then select "project_name properties" → "configuration properties" → "linker" → "system" and set the first property, the drop down "subsystem" property to "console (/SUBSYSTEM:CONSOLE)". The console window should now stay open after execution as usual.
/////////////////////////////////////////////////////////////////////////////////////
If it is a console application, use Ctrl + F5.
In Boost.Test there is the --auto_start_dbg parameter for breaking into the debugger when a test fails (on an exception or on an assertion failure). For some reason it doesn't work for me.
See http://www.boost.org/doc/libs/1_40_0/libs/test/doc/html/utf/usage-recommendations/dot-net-specific.html
For this reason I have created my custom test_observer that will break into the debugger when there is an assertion failure or an exception. This is enabled on debug builds when we are running under a debugger.
In one of the source files of my unit test EXE file I have added this code:
#ifdef _DEBUG
#include <boost/test/framework.hpp>
#include <boost/test/test_observer.hpp>
struct BoostUnitTestCrtBreakpointInDebug: boost::unit_test::test_observer
{
BoostUnitTestCrtBreakpointInDebug()
{
boost::unit_test::framework::register_observer(*this);
}
virtual ~BoostUnitTestCrtBreakpointInDebug()
{
boost::unit_test::framework::deregister_observer(*this);
}
virtual void assertion_result( bool passed /* passed */ )
{
if (!passed)
BreakIfInDebugger();
}
virtual void exception_caught( boost::execution_exception const& )
{
BreakIfInDebugger();
}
void BreakIfInDebugger()
{
if (IsDebuggerPresent())
{
/**
* Hello, I know you are here staring at the debugger :)
*
* If you got here then there is an exception in your unit
* test code. Walk the call stack to find the actual cause.
*/
_CrtDbgBreak();
}
}
};
BOOST_GLOBAL_FIXTURE(BoostUnitTestCrtBreakpointInDebug);
#endif
You say you don't want to use the system("pause") hack. Why not?
If it's because you don't want the program to prompt when it's not being debugged, there's a way around that. This works for me:
void pause () {
system ("pause");
}
int main (int argc, char ** argv) {
// If "launched", then don't let the console close at the end until
// the user has seen the report.
// (See the MSDN ConGUI sample code)
//
do {
HANDLE hConsoleOutput = ::GetStdHandle (STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == hConsoleOutput)
break;
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (0 == ::GetConsoleScreenBufferInfo (hConsoleOutput, &csbi))
break;
if (0 != csbi.dwCursorPosition.X)
break;
if (0 != csbi.dwCursorPosition.Y)
break;
if (csbi.dwSize.X <= 0)
break;
if (csbi.dwSize.Y <= 0)
break;
atexit (pause);
} while (0);
I just paste this code into each new console application I'm writing. If the program is being run from a command window, the cursor position won't be <0,0>, and it won't call atexit(). If it has been launched from you debugger (any debugger) the console cursor position will be <0,0> and the atexit() call will be executed.
I got the idea from a sample program that used to be in the MSDN library, but I think it's been deleted.
NOTE: The Microsoft Visual Studio implementation of the system() routine requires the COMSPEC environment variable to identify the command line interpreter. If this environment variable gets messed up -- for example, if you've got a problem in the Visual Studio project's debugging properties so that the environment variables aren't properly passed down when the program is launched -- then it will just fail silently.
It would actually be more effort, but you could just build in VS.Net, run it from the regular command line (cmd.exe), and then attach to the process after it starts running. This is probably not the solution you are looking for however.
Or you could use boost_test "Test Log Output."
http://www.boost.org/doc/libs/1_47_0/libs/test/doc/html/utf/user-guide/test-output/test-log.html
Then it won't matter whether the console window shows up at all AND your build logging can preserve the unit testing output as an artifact for examination on failed builds...
Adding the following line will do a simple MS-DOS pause displaying no message.
system("pause >nul | set /p \"=\"");
And there is no need to Ctrl+F5 (which will make your application run in Release Mode)
I would use a "wait"-command for a specific time (milliseconds) of your own choice. The application executes until the line you want to inspect and then continues after the time expired.
Include the <time.h> header:
clock_t wait;
wait = clock();
while (clock() <= (wait + 5000)) // Wait for 5 seconds and then continue
;
wait = 0;
You could also setup your executable as an external tool, and mark the tool for Use output window. That way the output of the tool will be visible within Visual Studio itself, not a separate window.
I start the app with F11 and get a breakpoint somewhere in unit_test_main.ipp (can be assembly code). I use shift-f11 (Step out) to run the unit test and get the next assembly instruction in the CRT (normally in mainCRTStartup()). I use F9 to set a breakpoint at that instruction.
On the next invocation, I can start the app with F5 and the app will break after running the tests, therefore giving me a chance to peek at the console window
Just use a logging library, like log4net, and have it log to a file appender.
Prompt for user input.
https://www.youtube.com/watch?v=NIGhjrWLWBo
shows how to do this for C++. For Node.js, this is taken right from the docs (and it works):
'use strict';
console.log('Hello world');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Press enter to continue...', (answer) => {
rl.close(); /* discard the answer */
});
Do a readline at the end (it's the "forma cochina", like we say in Colombia, but it works):
static void Main(string[] args)
{
.
.
.
String temp = Console.ReadLine();
}