Node monitoring and on-the-fly textencoding change
This work is based on the draft node monitoring implementation created by Vlad Slepukhin during GCI 2012 and includes following: * Refactoring of the document "Reload" feature - it replaces "Revert to saved" one because do the same things and a bit more. Looks like we have to keep "Reload" menu entry alive until StyledEdit will get more functional Undo/Redo features. Reload functionality is also heavily used in node monitoring and on-the-fly text encoding changing. Fixes #6887; * Support for text encoding on-the-fly switching. This make life easier for those who lives in countires with multiple popular 8-bit encodings. Russia is the sample of such de facto standards' clash (KOI-8R vs CP1251 etc.); * Node Monitoring support with alerting user in case the file size or modification time were changed. Another alert is shown in case edited file was removed or moved outside of the current volume. Moving file inside of current volume silently changes references. Choosing "Ignore" will supress new change alerts until next Reload or Save user request; * Do not nag user on quiting window with zero-length untitled document. Not a Big Deal but annoys in some cases using this editor session as temporary storage.
This commit is contained in:
@@ -25,7 +25,7 @@ const uint32 MENU_NEW = 'MFnw';
|
||||
const uint32 MENU_OPEN = 'MFop';
|
||||
const uint32 MENU_SAVE = 'MSav';
|
||||
const uint32 MENU_SAVEAS = 'MEsa';
|
||||
const uint32 MENU_REVERT = 'MFre';
|
||||
const uint32 MENU_RELOAD = 'MFrl';
|
||||
const uint32 MENU_CLOSE = 'MFcl';
|
||||
const uint32 MENU_PAGESETUP = 'MFps';
|
||||
const uint32 MENU_PRINT = 'MFpr';
|
||||
|
||||
@@ -73,8 +73,11 @@ StyledEditView::SetSuppressChanges(bool suppressChanges)
|
||||
|
||||
|
||||
status_t
|
||||
StyledEditView::GetStyledText(BPositionIO* stream)
|
||||
StyledEditView::GetStyledText(BPositionIO* stream, const char* forceEncoding)
|
||||
{
|
||||
if (forceEncoding != NULL)
|
||||
fEncoding = strcmp(forceEncoding, "auto") != 0 ? forceEncoding : "";
|
||||
|
||||
fSuppressChanges = true;
|
||||
status_t result = BTranslationUtils::GetStyledText(stream, this,
|
||||
fEncoding.String());
|
||||
@@ -85,24 +88,25 @@ StyledEditView::GetStyledText(BPositionIO* stream)
|
||||
|
||||
BNode* node = dynamic_cast<BNode*>(stream);
|
||||
if (node != NULL) {
|
||||
// get encoding
|
||||
if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) {
|
||||
// try to read as "int32"
|
||||
int32 encoding;
|
||||
ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
|
||||
&encoding, sizeof(encoding));
|
||||
if (bytesRead == (ssize_t)sizeof(encoding)) {
|
||||
if (encoding == 65535) {
|
||||
fEncoding = "UTF-8";
|
||||
} else {
|
||||
const BCharacterSet* characterSet
|
||||
= BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
|
||||
if (characterSet != NULL)
|
||||
fEncoding = characterSet->GetName();
|
||||
if (forceEncoding == NULL) {
|
||||
// get encoding
|
||||
if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) {
|
||||
// try to read as "int32"
|
||||
int32 encoding;
|
||||
ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
|
||||
&encoding, sizeof(encoding));
|
||||
if (bytesRead == (ssize_t)sizeof(encoding)) {
|
||||
if (encoding == 65535) {
|
||||
fEncoding = "UTF-8";
|
||||
} else {
|
||||
const BCharacterSet* characterSet
|
||||
= BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
|
||||
if (characterSet != NULL)
|
||||
fEncoding = characterSet->GetName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move those into BTranslationUtils::GetStyledText() as well?
|
||||
|
||||
// restore alignment
|
||||
|
||||
@@ -34,7 +34,8 @@ class StyledEditView : public BTextView {
|
||||
|
||||
void Reset();
|
||||
void SetSuppressChanges(bool suppressChanges);
|
||||
status_t GetStyledText(BPositionIO* stream);
|
||||
status_t GetStyledText(BPositionIO* stream,
|
||||
const char* forceEncoding = NULL);
|
||||
status_t WriteStyledEditFile(BFile* file);
|
||||
|
||||
void SetEncoding(uint32 encoding);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2012, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -8,6 +8,8 @@
|
||||
* Philippe Saint-Pierre
|
||||
* Jonas Sundström
|
||||
* Ryan Leavengood
|
||||
* Vlad Slepukhin
|
||||
* Sarzhuk Zharski
|
||||
*/
|
||||
|
||||
|
||||
@@ -33,6 +35,7 @@
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <PrintJob.h>
|
||||
#include <Rect.h>
|
||||
@@ -107,6 +110,8 @@ StyledEditWindow::~StyledEditWindow()
|
||||
void
|
||||
StyledEditWindow::Quit()
|
||||
{
|
||||
_SwitchNodeMonitor(false);
|
||||
|
||||
_SaveAttrs();
|
||||
if (StyledEditApp* app = dynamic_cast<StyledEditApp*>(be_app))
|
||||
app->CloseDocument();
|
||||
@@ -124,6 +129,9 @@ StyledEditWindow::QuitRequested()
|
||||
if (fClean)
|
||||
return true;
|
||||
|
||||
if (fTextView->TextLength() == 0 && fSaveMessage == NULL)
|
||||
return true;
|
||||
|
||||
BString alertText;
|
||||
bs_printf(&alertText,
|
||||
B_TRANSLATE("Save changes to the document \"%s\"? "), Title());
|
||||
@@ -179,8 +187,8 @@ StyledEditWindow::MessageReceived(BMessage* message)
|
||||
Quit();
|
||||
break;
|
||||
|
||||
case MENU_REVERT:
|
||||
_RevertToSaved();
|
||||
case MENU_RELOAD:
|
||||
_ReloadDocument(message);
|
||||
break;
|
||||
|
||||
case MENU_CLOSE:
|
||||
@@ -294,6 +302,10 @@ StyledEditWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case B_NODE_MONITOR:
|
||||
_HandleNodeMonitorEvent(message);
|
||||
break;
|
||||
|
||||
// Font menu
|
||||
|
||||
case FONT_SIZE:
|
||||
@@ -485,12 +497,12 @@ StyledEditWindow::MessageReceived(BMessage* message)
|
||||
fRedoFlag = false;
|
||||
}
|
||||
if (fClean) {
|
||||
fRevertItem->SetEnabled(false);
|
||||
fSaveItem->SetEnabled(fSaveMessage == NULL);
|
||||
} else {
|
||||
fRevertItem->SetEnabled(fSaveMessage != NULL);
|
||||
fSaveItem->SetEnabled(true);
|
||||
}
|
||||
fReloadItem->SetEnabled(fSaveMessage != NULL);
|
||||
fEncodingItem->SetEnabled(fSaveMessage != NULL);
|
||||
break;
|
||||
|
||||
case SAVE_AS_ENCODING:
|
||||
@@ -646,6 +658,21 @@ StyledEditWindow::MenusBeginning()
|
||||
fAlignRight->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// text encoding
|
||||
const BCharacterSet* charset
|
||||
= BCharacterSetRoster::GetCharacterSetByFontID(fTextView->GetEncoding());
|
||||
BMenu* encodingMenu = fEncodingItem->Submenu();
|
||||
if (charset != NULL && encodingMenu != NULL) {
|
||||
const char* mime = charset->GetMIMEName();
|
||||
BString name(charset->GetPrintName());
|
||||
if (mime)
|
||||
name << " (" << mime << ")";
|
||||
|
||||
BMenuItem* item = encodingMenu->FindItem(name);
|
||||
if (item != NULL)
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -656,6 +683,8 @@ StyledEditWindow::MenusBeginning()
|
||||
status_t
|
||||
StyledEditWindow::Save(BMessage* message)
|
||||
{
|
||||
_NodeMonitorSuspender nodeMonitorSuspender(this);
|
||||
|
||||
if (!message)
|
||||
message = fSaveMessage;
|
||||
|
||||
@@ -722,10 +751,11 @@ StyledEditWindow::Save(BMessage* message)
|
||||
|
||||
// clear clean modes
|
||||
fSaveItem->SetEnabled(false);
|
||||
fRevertItem->SetEnabled(false);
|
||||
fUndoCleans = false;
|
||||
fRedoCleans = false;
|
||||
fClean = true;
|
||||
fNagOnNodeChange = true;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -811,6 +841,11 @@ StyledEditWindow::OpenFile(entry_ref* ref)
|
||||
|
||||
_LoadAttrs();
|
||||
}
|
||||
|
||||
_SwitchNodeMonitor(true, ref);
|
||||
|
||||
fReloadItem->SetEnabled(fSaveMessage != NULL);
|
||||
fEncodingItem->SetEnabled(fSaveMessage != NULL);
|
||||
fTextView->Select(0, 0);
|
||||
}
|
||||
|
||||
@@ -841,7 +876,7 @@ StyledEditWindow::Print(const char* documentName)
|
||||
printJob.SetSettings(new BMessage(*fPrintSettings));
|
||||
|
||||
if (printJob.ConfigJob() != B_OK)
|
||||
return;
|
||||
return;
|
||||
|
||||
delete fPrintSettings;
|
||||
fPrintSettings = printJob.Settings();
|
||||
@@ -890,7 +925,9 @@ StyledEditWindow::Print(const char* documentName)
|
||||
while (printLine <= lastLine) {
|
||||
float currentHeight = 0;
|
||||
int32 firstLineOnPage = printLine;
|
||||
while (currentHeight < printableRect.Height() && printLine <= lastLine) {
|
||||
while (currentHeight < printableRect.Height()
|
||||
&& printLine <= lastLine)
|
||||
{
|
||||
currentHeight += fTextView->LineHeight(printLine);
|
||||
if (currentHeight < printableRect.Height())
|
||||
printLine++;
|
||||
@@ -993,6 +1030,8 @@ StyledEditWindow::_InitWindow(uint32 encoding)
|
||||
fWrapAround = false;
|
||||
fBackSearch = false;
|
||||
|
||||
fNagOnNodeChange = true;
|
||||
|
||||
// add menubar
|
||||
fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar");
|
||||
AddChild(fMenuBar);
|
||||
@@ -1043,10 +1082,11 @@ StyledEditWindow::_InitWindow(uint32 encoding)
|
||||
menuItem->SetShortcut('S', B_SHIFT_KEY);
|
||||
menuItem->SetEnabled(true);
|
||||
|
||||
menu->AddItem(fRevertItem
|
||||
= new BMenuItem(B_TRANSLATE("Revert to saved" B_UTF8_ELLIPSIS),
|
||||
new BMessage(MENU_REVERT)));
|
||||
fRevertItem->SetEnabled(false);
|
||||
menu->AddItem(fReloadItem
|
||||
= new BMenuItem(B_TRANSLATE("Reload" B_UTF8_ELLIPSIS),
|
||||
new BMessage(MENU_RELOAD), 'L'));
|
||||
fReloadItem->SetEnabled(false);
|
||||
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Close"),
|
||||
new BMessage(MENU_CLOSE), 'W'));
|
||||
|
||||
@@ -1107,7 +1147,7 @@ StyledEditWindow::_InitWindow(uint32 encoding)
|
||||
fFontMenu = new BMenu(B_TRANSLATE("Font"));
|
||||
fMenuBar->AddItem(fFontMenu);
|
||||
|
||||
//"Size"-subMenu
|
||||
// "Size"-subMenu
|
||||
fFontSizeMenu = new BMenu(B_TRANSLATE("Size"));
|
||||
fFontSizeMenu->SetRadioMode(true);
|
||||
fFontMenu->AddItem(fFontSizeMenu);
|
||||
@@ -1210,6 +1250,9 @@ StyledEditWindow::_InitWindow(uint32 encoding)
|
||||
fWrapItem->SetMarked(true);
|
||||
fWrapItem->SetShortcut('W', B_OPTION_KEY);
|
||||
|
||||
menu->AddItem(fEncodingItem = _MakeEncodingMenuItem());
|
||||
fEncodingItem->SetEnabled(false);
|
||||
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Statistics" B_UTF8_ELLIPSIS),
|
||||
new BMessage(SHOW_STATISTICS)));
|
||||
@@ -1286,7 +1329,7 @@ StyledEditWindow::_SaveAttrs()
|
||||
|
||||
|
||||
status_t
|
||||
StyledEditWindow::_LoadFile(entry_ref* ref)
|
||||
StyledEditWindow::_LoadFile(entry_ref* ref, const char* forceEncoding)
|
||||
{
|
||||
BEntry entry(ref, true);
|
||||
// traverse an eventual link
|
||||
@@ -1299,7 +1342,7 @@ StyledEditWindow::_LoadFile(entry_ref* ref)
|
||||
if (status == B_OK)
|
||||
status = file.SetTo(&entry, B_READ_ONLY);
|
||||
if (status == B_OK)
|
||||
status = fTextView->GetStyledText(&file);
|
||||
status = fTextView->GetStyledText(&file, forceEncoding);
|
||||
|
||||
if (status == B_ENTRY_NOT_FOUND) {
|
||||
// Treat non-existing files consideratley; we just want to get an
|
||||
@@ -1351,11 +1394,14 @@ StyledEditWindow::_LoadFile(entry_ref* ref)
|
||||
|
||||
|
||||
void
|
||||
StyledEditWindow::_RevertToSaved()
|
||||
StyledEditWindow::_ReloadDocument(BMessage* message)
|
||||
{
|
||||
entry_ref ref;
|
||||
const char* name;
|
||||
|
||||
if (fSaveMessage == NULL || message == NULL)
|
||||
return;
|
||||
|
||||
fSaveMessage->FindRef("directory", &ref);
|
||||
fSaveMessage->FindString("name", &name);
|
||||
|
||||
@@ -1376,15 +1422,40 @@ StyledEditWindow::_RevertToSaved()
|
||||
return;
|
||||
}
|
||||
|
||||
BString alertText;
|
||||
bs_printf(&alertText,
|
||||
B_TRANSLATE("Revert to the last version of \"%s\"? "), Title());
|
||||
if (_ShowAlert(alertText, B_TRANSLATE("Cancel"), B_TRANSLATE("OK"),
|
||||
"", B_WARNING_ALERT) != 1)
|
||||
return;
|
||||
if (!fClean) {
|
||||
BString alertText;
|
||||
bs_printf(&alertText,
|
||||
B_TRANSLATE("\"%s\" has unsaved changes.\n"
|
||||
"Revert it to the last saved version? "), Title());
|
||||
if (_ShowAlert(alertText, B_TRANSLATE("Cancel"), B_TRANSLATE("OK"),
|
||||
"", B_WARNING_ALERT) != 1)
|
||||
return;
|
||||
}
|
||||
|
||||
const char* forceEncoding = NULL;
|
||||
if (message->FindString("encoding", &forceEncoding) != B_OK) {
|
||||
const BCharacterSet* charset
|
||||
= BCharacterSetRoster::GetCharacterSetByFontID(
|
||||
fTextView->GetEncoding());
|
||||
if (charset != NULL)
|
||||
forceEncoding = charset->GetName();
|
||||
}
|
||||
|
||||
BScrollBar* vertBar = fScrollView->ScrollBar(B_VERTICAL);
|
||||
float vertPos = vertBar != NULL ? vertBar->Value() : 0.f;
|
||||
|
||||
DisableUpdates();
|
||||
|
||||
fTextView->Reset();
|
||||
if (_LoadFile(&ref) != B_OK)
|
||||
|
||||
status = _LoadFile(&ref, forceEncoding);
|
||||
|
||||
if (vertBar != NULL)
|
||||
vertBar->SetValue(vertPos);
|
||||
|
||||
EnableUpdates();
|
||||
|
||||
if (status != B_OK)
|
||||
return;
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
@@ -1400,10 +1471,12 @@ StyledEditWindow::_RevertToSaved()
|
||||
|
||||
// clear clean modes
|
||||
fSaveItem->SetEnabled(false);
|
||||
fRevertItem->SetEnabled(false);
|
||||
|
||||
fUndoCleans = false;
|
||||
fRedoCleans = false;
|
||||
fClean = true;
|
||||
|
||||
fNagOnNodeChange = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1656,7 +1729,8 @@ StyledEditWindow::_UpdateCleanUndoRedoSaveRevert()
|
||||
fClean = false;
|
||||
fUndoCleans = false;
|
||||
fRedoCleans = false;
|
||||
fRevertItem->SetEnabled(fSaveMessage != NULL);
|
||||
fReloadItem->SetEnabled(fSaveMessage != NULL);
|
||||
fEncodingItem->SetEnabled(fSaveMessage != NULL);
|
||||
fSaveItem->SetEnabled(true);
|
||||
fUndoItem->SetLabel(B_TRANSLATE("Can't undo"));
|
||||
fUndoItem->SetEnabled(false);
|
||||
@@ -1686,3 +1760,234 @@ StyledEditWindow::_ShowAlert(const BString& text, const BString& label,
|
||||
|
||||
return alert->Go();
|
||||
}
|
||||
|
||||
|
||||
BMenuItem*
|
||||
StyledEditWindow::_MakeEncodingMenuItem()
|
||||
{
|
||||
BMenu* menu = new BMenu(B_TRANSLATE("Text encoding"));
|
||||
|
||||
BCharacterSetRoster roster;
|
||||
BCharacterSet charset;
|
||||
while (roster.GetNextCharacterSet(&charset) == B_OK) {
|
||||
const char* mime = charset.GetMIMEName();
|
||||
BString name(charset.GetPrintName());
|
||||
|
||||
if (mime)
|
||||
name << " (" << mime << ")";
|
||||
|
||||
BMessage *message = new BMessage(MENU_RELOAD);
|
||||
if (message != NULL) {
|
||||
message->AddString("encoding", charset.GetName());
|
||||
menu->AddItem(new BMenuItem(name, message));
|
||||
}
|
||||
}
|
||||
|
||||
menu->AddSeparatorItem();
|
||||
BMessage *message = new BMessage(MENU_RELOAD);
|
||||
message->AddString("encoding", "auto");
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Autodetect"), message));
|
||||
|
||||
menu->SetRadioMode(true);
|
||||
|
||||
return new BMenuItem(menu, new BMessage(MENU_RELOAD));
|
||||
}
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "NodeMonitorAlerts"
|
||||
|
||||
|
||||
void
|
||||
StyledEditWindow::_ShowNodeChangeAlert(const char* name, bool removed)
|
||||
{
|
||||
if (!fNagOnNodeChange)
|
||||
return;
|
||||
|
||||
BString alertText(removed ? B_TRANSLATE("File \"%file%\" was removed by "
|
||||
"another application, recover it?")
|
||||
: B_TRANSLATE("File \"%file%\" was modified by "
|
||||
"another application, reload it?"));
|
||||
alertText.ReplaceAll("%file%", name);
|
||||
|
||||
if (_ShowAlert(alertText, removed ? B_TRANSLATE("Recover")
|
||||
: B_TRANSLATE("Reload"), B_TRANSLATE("Ignore"), "",
|
||||
B_WARNING_ALERT) == 0)
|
||||
{
|
||||
if (!removed) {
|
||||
// supress the warning - user has already agreed
|
||||
fClean = true;
|
||||
BMessage msg(MENU_RELOAD);
|
||||
_ReloadDocument(&msg);
|
||||
} else
|
||||
Save();
|
||||
} else
|
||||
fNagOnNodeChange = false;
|
||||
|
||||
fSaveItem->SetEnabled(!fClean);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StyledEditWindow::_HandleNodeMonitorEvent(BMessage *message)
|
||||
{
|
||||
int32 opcode = 0;
|
||||
if (message->FindInt32("opcode", &opcode) != B_OK)
|
||||
return;
|
||||
|
||||
if (opcode != B_ENTRY_CREATED
|
||||
&& message->FindInt64("node") != fNodeRef.node)
|
||||
// bypass foreign nodes' event
|
||||
return;
|
||||
|
||||
switch (opcode) {
|
||||
case B_STAT_CHANGED:
|
||||
{
|
||||
int32 fields = 0;
|
||||
if (message->FindInt32("fields", &fields) == B_OK
|
||||
&& (fields & (B_STAT_SIZE | B_STAT_MODIFICATION_TIME)) == 0)
|
||||
break;
|
||||
|
||||
const char* name = NULL;
|
||||
if (fSaveMessage->FindString("name", &name) != B_OK)
|
||||
break;
|
||||
|
||||
_ShowNodeChangeAlert(name, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case B_ENTRY_MOVED:
|
||||
{
|
||||
int32 device = 0;
|
||||
int64 srcFolder = 0;
|
||||
int64 dstFolder = 0;
|
||||
const char* name = NULL;
|
||||
if (message->FindInt32("device", &device) != B_OK
|
||||
|| message->FindInt64("to directory", &dstFolder) != B_OK
|
||||
|| message->FindInt64("from directory", &srcFolder) != B_OK
|
||||
|| message->FindString("name", &name) != B_OK)
|
||||
break;
|
||||
|
||||
entry_ref newRef(device, dstFolder, name);
|
||||
BEntry entry(&newRef);
|
||||
|
||||
BEntry dirEntry;
|
||||
entry.GetParent(&dirEntry);
|
||||
|
||||
entry_ref ref;
|
||||
dirEntry.GetRef(&ref);
|
||||
fSaveMessage->ReplaceRef("directory", &ref);
|
||||
fSaveMessage->ReplaceString("name", name);
|
||||
|
||||
// store previous name - it may be useful in case
|
||||
// we have just moved to temporary copy of file (vim case)
|
||||
const char* sourceName = NULL;
|
||||
if (message->FindString("from name", &sourceName) == B_OK) {
|
||||
fSaveMessage->RemoveName("org.name");
|
||||
fSaveMessage->AddString("org.name", sourceName);
|
||||
fSaveMessage->RemoveName("move time");
|
||||
fSaveMessage->AddInt64("move time", system_time());
|
||||
}
|
||||
|
||||
SetTitle(name);
|
||||
be_roster->AddToRecentDocuments(&newRef, APP_SIGNATURE);
|
||||
|
||||
if (srcFolder != dstFolder) {
|
||||
_SwitchNodeMonitor(false);
|
||||
_SwitchNodeMonitor(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case B_ENTRY_REMOVED:
|
||||
{
|
||||
_SwitchNodeMonitor(false);
|
||||
|
||||
fClean = false;
|
||||
|
||||
// some editors like vim save files in following way:
|
||||
// 1) move t.txt -> t.txt~
|
||||
// 2) re-create t.txt and write data to it
|
||||
// 3) remove t.txt~
|
||||
// go to catch this case
|
||||
int32 device = 0;
|
||||
int64 directory = 0;
|
||||
BString orgName;
|
||||
if (fSaveMessage->FindString("org.name", &orgName) == B_OK
|
||||
&& message->FindInt32("device", &device) == B_OK
|
||||
&& message->FindInt64("directory", &directory) == B_OK)
|
||||
{
|
||||
// reuse the source name if it is not too old
|
||||
bigtime_t time = fSaveMessage->FindInt64("move time");
|
||||
if ((system_time() - time) < 1000000) {
|
||||
entry_ref ref(device, directory, orgName);
|
||||
BEntry entry(&ref);
|
||||
if (entry.InitCheck() == B_OK) {
|
||||
_SwitchNodeMonitor(true, &ref);
|
||||
}
|
||||
|
||||
fSaveMessage->ReplaceString("name", orgName);
|
||||
fSaveMessage->RemoveName("org.name");
|
||||
fSaveMessage->RemoveName("move time");
|
||||
|
||||
SetTitle(orgName);
|
||||
_ShowNodeChangeAlert(orgName, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* name = NULL;
|
||||
if (message->FindString("name", &name) != B_OK
|
||||
&& fSaveMessage->FindString("name", &name) != B_OK)
|
||||
name = "Unknown";
|
||||
|
||||
_ShowNodeChangeAlert(name, true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StyledEditWindow::_SwitchNodeMonitor(bool on, entry_ref* ref)
|
||||
{
|
||||
if (!on) {
|
||||
watch_node(&fNodeRef, B_STOP_WATCHING, this);
|
||||
watch_node(&fFolderNodeRef, B_STOP_WATCHING, this);
|
||||
fNodeRef = node_ref();
|
||||
fFolderNodeRef = node_ref();
|
||||
return;
|
||||
}
|
||||
|
||||
BEntry entry, folderEntry;
|
||||
|
||||
if (ref != NULL) {
|
||||
entry.SetTo(ref, true);
|
||||
entry.GetParent(&folderEntry);
|
||||
|
||||
} else if (fSaveMessage != NULL) {
|
||||
entry_ref ref;
|
||||
const char* name = NULL;
|
||||
if (fSaveMessage->FindRef("directory", &ref) != B_OK
|
||||
|| fSaveMessage->FindString("name", &name) != B_OK)
|
||||
return;
|
||||
|
||||
BDirectory dir(&ref);
|
||||
entry.SetTo(&dir, name);
|
||||
folderEntry.SetTo(&ref);
|
||||
|
||||
} else
|
||||
return;
|
||||
|
||||
if (entry.InitCheck() != B_OK || folderEntry.InitCheck() != B_OK)
|
||||
return;
|
||||
|
||||
entry.GetNodeRef(&fNodeRef);
|
||||
folderEntry.GetNodeRef(&fFolderNodeRef);
|
||||
|
||||
watch_node(&fNodeRef, B_WATCH_STAT, this);
|
||||
watch_node(&fFolderNodeRef, B_WATCH_DIRECTORY, this);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2012, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -15,15 +15,15 @@
|
||||
#include <Window.h>
|
||||
#include <String.h>
|
||||
#include <Message.h>
|
||||
|
||||
#include <Node.h>
|
||||
|
||||
struct entry_ref;
|
||||
|
||||
class BFilePanel;
|
||||
class BMenu;
|
||||
class BMessage;
|
||||
class BMenuBar;
|
||||
class BMenuItem;
|
||||
class BFilePanel;
|
||||
class BMessage;
|
||||
class BScrollView;
|
||||
class StyledEditView;
|
||||
|
||||
@@ -52,10 +52,12 @@ public:
|
||||
|
||||
private:
|
||||
void _InitWindow(uint32 encoding = 0);
|
||||
BMenuItem* _MakeEncodingMenuItem();
|
||||
void _LoadAttrs();
|
||||
void _SaveAttrs();
|
||||
status_t _LoadFile(entry_ref* ref);
|
||||
void _RevertToSaved();
|
||||
status_t _LoadFile(entry_ref* ref,
|
||||
const char* forceEncoding = NULL);
|
||||
void _ReloadDocument(BMessage *message);
|
||||
bool _Search(BString searchFor, bool caseSensitive,
|
||||
bool wrap, bool backSearch,
|
||||
bool scrollToOccurence = true);
|
||||
@@ -76,6 +78,27 @@ private:
|
||||
const BString& label3,
|
||||
alert_type type) const;
|
||||
|
||||
// node monitoring helper
|
||||
class _NodeMonitorSuspender {
|
||||
StyledEditWindow *fWindow;
|
||||
public:
|
||||
_NodeMonitorSuspender(StyledEditWindow *w) : fWindow(w) {
|
||||
fWindow->_SwitchNodeMonitor(false);
|
||||
}
|
||||
|
||||
~_NodeMonitorSuspender() {
|
||||
fWindow->_SwitchNodeMonitor(true);
|
||||
}
|
||||
};
|
||||
|
||||
friend class _NodeMonitorSuspender;
|
||||
|
||||
void _HandleNodeMonitorEvent(BMessage *message);
|
||||
void _ShowNodeChangeAlert(const char* name,
|
||||
bool removed);
|
||||
void _SwitchNodeMonitor(bool on,
|
||||
entry_ref* ref = NULL);
|
||||
|
||||
private:
|
||||
BMenuBar* fMenuBar;
|
||||
BMessage* fPrintSettings;
|
||||
@@ -89,7 +112,7 @@ private:
|
||||
BMenuItem* fCurrentStyleItem;
|
||||
|
||||
BMenuItem* fSaveItem;
|
||||
BMenuItem* fRevertItem;
|
||||
BMenuItem* fReloadItem;
|
||||
|
||||
BMenuItem* fUndoItem;
|
||||
BMenuItem* fCutItem;
|
||||
@@ -113,6 +136,7 @@ private:
|
||||
BMenuItem* fAlignLeft;
|
||||
BMenuItem* fAlignCenter;
|
||||
BMenuItem* fAlignRight;
|
||||
BMenuItem* fEncodingItem;
|
||||
|
||||
BString fStringToFind;
|
||||
BString fReplaceString;
|
||||
@@ -139,6 +163,10 @@ private:
|
||||
|
||||
BFilePanel* fSavePanel;
|
||||
BMenu* fSavePanelEncodingMenu;
|
||||
// node monitoring
|
||||
node_ref fNodeRef;
|
||||
node_ref fFolderNodeRef;
|
||||
bool fNagOnNodeChange;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user