From adebe5cfa1540497e8ea415fe7e32c524067148f Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Sat, 17 Jan 2026 00:22:54 -0700 Subject: [PATCH] EditorWindow: add menuitem to toggle file write permissions --- locales/en.catkeys | 11 +++++-- src/editor/EditorWindow.cpp | 64 ++++++++++++++++++++++++++----------- src/editor/EditorWindow.h | 2 ++ src/support/File.cpp | 30 +++++++++++++++++ src/support/File.h | 1 + 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/locales/en.catkeys b/locales/en.catkeys index 057449f..ddbfc8e 100644 --- a/locales/en.catkeys +++ b/locales/en.catkeys @@ -1,4 +1,4 @@ -1 English x-vnd.KapiX-Koder 2982779499 +1 English x-vnd.KapiX-Koder 542788947 Something wrong has happened while opening the configuration file. Your personal settings will not be %s%. Preferences Something wrong has happened while opening the configuration file. Your personal settings will not be %s%. Access denied EditorWindow Access denied Line endings EditorWindow Line endings @@ -54,6 +54,7 @@ Reached the end of the target. No results found. EditorWindow Reached the end o Gigantic AppPreferencesWindow Toolbar icon size Gigantic write Preferences Make sure you have _ permission for write Show toolbar AppPreferencesWindow Show toolbar +Make file writable EditorWindow Make file writable Select all EditorWindow Select all Do nothing EditorWindow Do nothing Trailing whitespace AppPreferencesWindow Trailing whitespace @@ -78,6 +79,7 @@ Up to the next non-empty line AppPreferencesWindow Up to the next non-empty lin Replace all FindWindow Replace all Koder System name Koder View or submit bug reports EditorWindow View or submit bug reports +Make file read only EditorWindow Make file read only Extra large AppPreferencesWindow Toolbar icon size Extra large Stack new windows AppPreferencesWindow Stack new windows Find selection EditorWindow Find selection @@ -92,6 +94,7 @@ Wrap lines EditorWindow Wrap lines History FindStatusView History Small AppPreferencesWindow Toolbar icon size Small Find next EditorWindow Find next +Permission Error EditorWindow Permission Error Incremental search EditorWindow Incremental search Style files Styler Style files Cut EditorWindow Cut @@ -108,9 +111,9 @@ Replacement finished EditorWindow Replacement finished Always open files in new window AppPreferencesWindow Always open files in new window Your changes will be lost. EditorWindow Your changes will be lost. Find/Replace… EditorWindow Find/Replace… +Replace and find FindWindow Replace and find Show white space EditorWindow Show white space Could not launch Open Terminal Tracker add-on. EditorWindow Could not launch Open Terminal Tracker add-on. -Replace and find FindWindow Replace and find Huge AppPreferencesWindow Toolbar icon size Huge Regex FindWindow Regex Go to BookmarksListView Go to @@ -131,7 +134,9 @@ Clear FindStatusView Clear Style AppPreferencesWindow Style Paste EditorWindow Paste Help EditorWindow Help +OK EditorWindow OK Save as… EditorWindow Save as… +An error occurred while attempting to change file permissions. EditorWindow An error occurred while attempting to change file permissions. Bookmarks EditorWindow Bookmarks Untitled EditorWindow Untitled Unknown error. Preferences Unknown error. @@ -167,7 +172,7 @@ Highlight trailing whitespace AppPreferencesWindow Highlight trailing whitespac Up to the next/previous non-empty line AppPreferencesWindow Up to the next/previous non-empty line Show indentation guides AppPreferencesWindow Show indentation guides Koder preferences AppPreferencesWindow Koder preferences -An error occurred while attempting to save the file. EditorWindow An error occurred while attempting to save the file. Don't save QuitAlert Don't save +An error occurred while attempting to save the file. EditorWindow An error occurred while attempting to save the file. Replace FindWindow Replace [read-only] EditorWindow [read-only] diff --git a/src/editor/EditorWindow.cpp b/src/editor/EditorWindow.cpp index 31def38..feeb389 100644 --- a/src/editor/EditorWindow.cpp +++ b/src/editor/EditorWindow.cpp @@ -77,6 +77,7 @@ EditorWindow::EditorWindow(bool stagger) fBookmarksWindow = nullptr; fOpenedFilePath = nullptr; fOpenedFileMimeType.SetTo("text/plain"); + fOpenedFileModificationTime = -1; fCurrentLanguage = "text"; @@ -98,6 +99,7 @@ EditorWindow::EditorWindow(bool stagger) .AddSeparator() .AddItem(B_TRANSLATE("Quit"), MAINMENU_FILE_QUIT, 'Q'); + fReadWriteMenuItem = new BMenuItem("", new BMessage(MAINMENU_FILE_TOGGLE_READONLY)); fMainMenu = new BMenuBar("MainMenu"); BLayoutBuilder::Menu<>(fMainMenu) .AddItem(new IconMenuItem(appMenu, nullptr, gAppMime, B_MINI_ICON)) @@ -112,6 +114,7 @@ EditorWindow::EditorWindow(bool stagger) .AddItem(B_TRANSLATE("Save"), MAINMENU_FILE_SAVE, 'S') .AddItem(B_TRANSLATE("Save as" B_UTF8_ELLIPSIS), MAINMENU_FILE_SAVEAS) .AddSeparator() + .AddItem(fReadWriteMenuItem) .AddItem(B_TRANSLATE("Open partner file"), MAINMENU_FILE_OPEN_CORRESPONDING, 'O', B_OPTION_KEY) .AddSeparator() .AddItem(B_TRANSLATE("Close"), B_QUIT_REQUESTED, 'W') @@ -568,6 +571,17 @@ EditorWindow::MessageReceived(BMessage* message) _OpenCorrespondingFile(*fOpenedFilePath, fCurrentLanguage); } } break; + case MAINMENU_FILE_TOGGLE_READONLY: { + if(fOpenedFilePath == nullptr || fOpenedFileModificationTime == -1) { + return; + } + BEntry entry(fOpenedFilePath->Path()); + if(entry.InitCheck() != B_OK || File::SetWritable(&entry, fReadOnly) != B_OK) { + (new BAlert(B_TRANSLATE("Permission Error"), + B_TRANSLATE("An error occurred while attempting to change file permissions."), + B_TRANSLATE("OK"), nullptr, nullptr, B_WIDTH_FROM_LABEL, B_STOP_ALERT))->Go(); + } + } break; case MAINMENU_FILE_QUIT: { be_app->PostMessage(B_QUIT_REQUESTED); } break; @@ -954,28 +968,40 @@ EditorWindow::Show() void EditorWindow::MenusBeginning() { - if(fWindowsMenu == nullptr) { - return; - } - for(int32 x = fWindowsMenu->CountItems() - 1; x >= 0; x--) { - delete fWindowsMenu->ItemAt(x); + if(fWindowsMenu != nullptr) { + for(int32 x = fWindowsMenu->CountItems() - 1; x >= 0; x--) { + delete fWindowsMenu->ItemAt(x); + } + for(int32 x = 0; x < be_app->CountWindows(); x++) { + // use a dynamic_cast to filter out other window types (find, save, bookmarks, ...) + EditorWindow* window = dynamic_cast(be_app->WindowAt(x)); + if(window == nullptr) + continue; + + BMessage* message = new BMessage(ACTIVATE_WINDOW); + message->AddPointer("window", window); + BMenuItem* menuItem = new BMenuItem(window->Title(), message); + if(window == this) { + menuItem->SetEnabled(false); + menuItem->SetMarked(true); + } + fWindowsMenu->AddItem(menuItem); + } + fWindowsMenu->SetTargetForItems(be_app); } - for(int32 x = 0; x < be_app->CountWindows(); x++) { - // use a dynamic_cast to filter out other window types (find, save, bookmarks, ...) - EditorWindow* window = dynamic_cast(be_app->WindowAt(x)); - if(window == nullptr) - continue; - - BMessage* message = new BMessage(ACTIVATE_WINDOW); - message->AddPointer("window", window); - BMenuItem* menuItem = new BMenuItem(window->Title(), message); - if(window == this) { - menuItem->SetEnabled(false); - menuItem->SetMarked(true); + + if(fReadWriteMenuItem != nullptr) { + if(fOpenedFilePath == nullptr || fOpenedFileModificationTime == -1) { + fReadWriteMenuItem->SetEnabled(false); + fReadWriteMenuItem->SetLabel(B_TRANSLATE("Make file writable")); + } else if(fReadOnly) { + fReadWriteMenuItem->SetEnabled(true); + fReadWriteMenuItem->SetLabel(B_TRANSLATE("Make file writable")); + } else { + fReadWriteMenuItem->SetEnabled(true); + fReadWriteMenuItem->SetLabel(B_TRANSLATE("Make file read only")); } - fWindowsMenu->AddItem(menuItem); } - fWindowsMenu->SetTargetForItems(be_app); } diff --git a/src/editor/EditorWindow.h b/src/editor/EditorWindow.h index 4051571..c93a9a1 100644 --- a/src/editor/EditorWindow.h +++ b/src/editor/EditorWindow.h @@ -49,6 +49,7 @@ enum { MAINMENU_FILE_RELOAD = 'mrld', MAINMENU_FILE_SAVE = 'msav', MAINMENU_FILE_SAVEAS = 'msva', + MAINMENU_FILE_TOGGLE_READONLY = 'mtgl', MAINMENU_FILE_OPEN_CORRESPONDING = 'mcrf', MAINMENU_FILE_QUIT = 'mqut', @@ -153,6 +154,7 @@ class EditorWindow : public BWindow { BMenu* fOpenRecentMenu; BMenu* fLanguageMenu; BMenu* fWindowsMenu; + BMenuItem* fReadWriteMenuItem; std::string fCurrentLanguage; ToolBar* fToolbar; StatusView* fStatusView; diff --git a/src/support/File.cpp b/src/support/File.cpp index 8d0e8d5..7cdf94b 100644 --- a/src/support/File.cpp +++ b/src/support/File.cpp @@ -177,6 +177,36 @@ File::CanWrite(BStatable* file) } +status_t +File::SetWritable(BStatable* file, bool writable) +{ + if(file == nullptr) + return B_ERROR; + + BVolume volume; + if(file->GetVolume(&volume) != B_OK || volume.IsReadOnly()) { + return B_ERROR; + } + + mode_t permissions; + if(file->GetPermissions(&permissions) != B_OK) { + return B_ERROR; + } + + if(writable) { + mode_t mask = umask(0); + umask(mask); + permissions |= (S_IWUSR | S_IWGRP | S_IWOTH) & ~mask; + // force S_IWUSR in case the user has a weird umask + permissions |= S_IWUSR; + } else { + permissions &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } + + return file->SetPermissions(permissions); +} + + BackupFileGuard::BackupFileGuard(const char* path, BHandler* handler) : fPath(path ? path : ""), diff --git a/src/support/File.h b/src/support/File.h index 8729563..0fb7f0d 100644 --- a/src/support/File.h +++ b/src/support/File.h @@ -38,6 +38,7 @@ class File : public BFile { static status_t Monitor(BStatable* file, bool enable, BHandler* handler); static bool CanWrite(BStatable* file); + static status_t SetWritable(BStatable* file, bool writable); };