Skip to content

Commit

Permalink
Merge pull request #26 from matyalatte/safe_mode
Browse files Browse the repository at this point in the history
Add safe mode
  • Loading branch information
matyalatte authored Feb 11, 2024
2 parents 165a0a7 + 765f3b1 commit 764cb44
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 39 deletions.
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Tuw: a tiny GUI wrapper for command-line tools

```text
_____
_____
|_ _| ___ __
| || | | \ \ /\ / /
| || |_| |\ V V /
| || |_| |\ V V /
|_| \__,_| \_/\_/
Tiny UI wrapper for
CLI tools
Expand Down Expand Up @@ -84,6 +84,6 @@ Files in this repository are available under the [MIT license](../license.txt).

| Project | Used for | License |
| -- | -- | -- |
| [libui-ng](https://github.com/libui-ng/libui-ng) | GUI framework | [MIT](http://opensource.org/licenses/MIT) |
| [libui-ng](https://github.com/libui-ng/libui-ng) | GUI framework | [MIT](http://opensource.org/licenses/MIT) |
| [RapidJSON](https://github.com/Tencent/rapidjson) | JSON handling | [MIT](http://opensource.org/licenses/MIT) |
| [subprocess.h](https://github.com/sheredom/subprocess.h) | Command processing | [Unlicense](https://github.com/sheredom/subprocess.h/blob/master/LICENSE) |
| [subprocess.h](https://github.com/sheredom/subprocess.h) | Command processing | [Unlicense](https://github.com/sheredom/subprocess.h/blob/master/LICENSE) |
2 changes: 2 additions & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
ver 0.6.2
- Fixed typos.
- Fixed a bug that the menu can be empty on macOS.
- Added safe mode.

ver 0.6.1
- Added radio buttons to GUI components
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ Not about the JSON format, but they might help you.

- [Multiple Lines](./tips/multi_lines): How to run multiple commands in a process.
- [Unicode Characters](./tips/unicode): Tuw supports UTF-8!
- [Safe Mode](./tips/safe_mode): You can check commands without executing them.
13 changes: 13 additions & 0 deletions examples/tips/safe_mode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Safe Mode

You can disable the command processing with the safe mode (`Debug > Safe Mode`.)

![safe_mode](https://github.com/matyalatte/tuw/assets/69258547/d6d319ce-b643-4fb7-8dfb-2e00c29b73bc)

The main purpose of the safe mode is to check the actual commands without execution.

![safe_mode_dialog](https://github.com/matyalatte/tuw/assets/69258547/f32b4896-3d78-460f-8799-b8a8a5cb98b2)

You can also check the help documents without opening their URLs.

![safe_mode_dialog2](https://github.com/matyalatte/tuw/assets/69258547/e8f9e0c4-4266-4fc3-a904-94bac1053c5e)
2 changes: 2 additions & 0 deletions include/main_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class MainFrame {
std::vector<Component*> m_components;
uiGrid* m_grid;
uiButton* m_run_button;
uiMenuItem* m_menu_item;

void CreateFrame();
void CreateMenu();
Expand All @@ -42,6 +43,7 @@ class MainFrame {
if (m_mainwin == NULL) return;
uiControlDestroy(uiControl(m_mainwin));
}
int IsSafeMode() { return uiMenuItemChecked(m_menu_item); }
};

void MainFrameDisableDialog();
4 changes: 2 additions & 2 deletions include/tuw_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace tuw_constants {
" CLI tools\n";
constexpr char TOOL_NAME[] = "Tuw";
constexpr char AUTHOR[] = "matyalatte";
constexpr char VERSION[] = "0.6.1";
constexpr int VERSION_INT = 601;
constexpr char VERSION[] = "0.6.2";
constexpr int VERSION_INT = 602;

#ifdef _WIN32
constexpr char OS[] = "win";
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ if tuw_OS == 'windows'
endif

if (tuw_is_release)
tuw_cpp_args += ['/GL']
tuw_cpp_args += ['/GL', '/D_HAS_EXCEPTIONS=0']
tuw_link_args += ['/OPT:REF', '/OPT:ICF', '/LTCG']
endif
else
Expand Down
94 changes: 62 additions & 32 deletions src/main_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ MainFrame::MainFrame(const rapidjson::Document& definition, const rapidjson::Doc
PrintFmt(tuw_constants::LOGO);

m_grid = NULL;
m_menu_item = NULL;
std::string exe_path = env_utils::GetExecutablePath();

m_definition.CopyFrom(definition, m_definition.GetAllocator());
Expand Down Expand Up @@ -113,6 +114,7 @@ void MainFrame::CreateFrame() {
uiWindowSetMargined(m_mainwin, 1);

#ifdef __linux__
// Console window for linux
uiWindow* log_win = uiNewWindow(env_utils::GetExecutablePath().c_str(), 600, 400, 0);
uiWindowOnClosing(log_win, OnClosing, NULL);
uiMultilineEntry* log_entry = uiNewMultilineEntry();
Expand Down Expand Up @@ -162,8 +164,16 @@ static void OnOpenURL(uiMenuItem *item, uiWindow *w, void *data) {

void MainFrame::CreateMenu() {
uiMenuItem* item;
uiMenu* menu = uiNewMenu("Menu");
uiMenu* menu = NULL;

#ifdef __APPLE__
// No need the menu for the quit item on macOS.
if (m_definition["gui"].Size() > 1) {
menu = uiNewMenu("Menu");
#else
menu = uiNewMenu("Menu");
if (m_definition["gui"].Size() > 1) {
#endif // __APPLE__
for (int i = 0; i < m_definition["gui"].Size(); i++) {
item = uiMenuAppendItem(menu, m_definition["gui"][i]["label"].GetString());
uiMenuItemOnClicked(item, OnUpdatePanel, new MenuData(this, i));
Expand All @@ -180,6 +190,8 @@ void MainFrame::CreateMenu() {
uiMenuItemOnClicked(item, OnOpenURL, new MenuData(this, i));
}
}
menu = uiNewMenu("Debug");
m_menu_item = uiMenuAppendCheckItem(menu, "Safe Mode");
}

void MainFrame::OpenURL(int id) {
Expand Down Expand Up @@ -229,11 +241,19 @@ void MainFrame::OpenURL(int id) {
url = "file:" + url;
}

ExecuteResult result = LaunchDefaultApp(url);
if (result.exit_code != 0) {
std::string msg = "Failed to open a " + type + " by an unexpected error.";
PrintFmt("%sError: %s\n", tag.c_str(), msg.c_str());
ShowErrorDialog(msg.c_str());
if (IsSafeMode()) {
std::string msg = "The URL was not opened because the safe mode is enabled.\n"
"You can disable it from the menu bar (Debug > Safe Mode.)\n"
"\n"
"URL: " + url;
ShowSuccessDialog(msg, "Safe Mode");
} else {
ExecuteResult result = LaunchDefaultApp(url);
if (result.exit_code != 0) {
std::string msg = "Failed to open a " + type + " by an unexpected error.";
PrintFmt("%sError: %s\n", tag.c_str(), msg.c_str());
ShowErrorDialog(msg.c_str());
}
}
}

Expand Down Expand Up @@ -358,36 +378,46 @@ void MainFrame::RunCommand() {

std::string cmd = GetCommand();
PrintFmt("[RunCommand] Command: %s\n", cmd.c_str());
ExecuteResult result = Execute(cmd);
uiButtonSetText(m_run_button, text);

rapidjson::Value& sub_definition = m_definition["gui"][m_definition_id];
bool check_exit_code = json_utils::GetBool(sub_definition, "check_exit_code", false);
int exit_success = json_utils::GetInt(sub_definition, "exit_success", 0);
bool show_last_line = json_utils::GetBool(sub_definition, "show_last_line", false);

if (result.err_msg != "") {
PrintFmt("[RunCommand] Error: %s\n", result.err_msg.c_str());
ShowErrorDialog(result.err_msg);
return;
}
if (IsSafeMode()) {
std::string msg = "The command was not executed because the safe mode is enabled.\n"
"You can disable it from the menu bar (Debug > Safe Mode.)\n"
"\n"
"Command: " + cmd;
ShowSuccessDialog(msg, "Safe Mode");
} else {
ExecuteResult result = Execute(cmd);

if (check_exit_code && result.exit_code != exit_success) {
std::string err_msg;
if (show_last_line)
err_msg = result.last_line;
else
err_msg = "Invalid exit code (" + std::to_string(result.exit_code) + ")";
PrintFmt("[RunCommand] Error: %s\n", err_msg.c_str());
ShowErrorDialog(err_msg);
return;
}
rapidjson::Value& sub_definition = m_definition["gui"][m_definition_id];
bool check_exit_code = json_utils::GetBool(sub_definition, "check_exit_code", false);
int exit_success = json_utils::GetInt(sub_definition, "exit_success", 0);
bool show_last_line = json_utils::GetBool(sub_definition, "show_last_line", false);

if (show_last_line && result.last_line != "") {
ShowSuccessDialog(result.last_line);
} else {
ShowSuccessDialog("Success!");
if (result.err_msg != "") {
PrintFmt("[RunCommand] Error: %s\n", result.err_msg.c_str());
ShowErrorDialog(result.err_msg);
return;
}

if (check_exit_code && result.exit_code != exit_success) {
std::string err_msg;
if (show_last_line)
err_msg = result.last_line;
else
err_msg = "Invalid exit code (" + std::to_string(result.exit_code) + ")";
PrintFmt("[RunCommand] Error: %s\n", err_msg.c_str());
ShowErrorDialog(err_msg);
return;
}

if (show_last_line && result.last_line != "") {
ShowSuccessDialog(result.last_line);
} else {
ShowSuccessDialog("Success!");
}
}

uiButtonSetText(m_run_button, text);
}

// read gui_definition.json
Expand Down

0 comments on commit 764cb44

Please sign in to comment.