]> git.lyx.org Git - features.git/commitdiff
Enable File -> Revert when the file is externally modified, rename this menu item...
authorBo Peng <bpeng@lyx.org>
Thu, 9 Aug 2007 20:46:22 +0000 (20:46 +0000)
committerBo Peng <bpeng@lyx.org>
Thu, 9 Aug 2007 20:46:22 +0000 (20:46 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19380 a592a061-630c-0410-9148-cb99ea01b6c8

lib/ui/stdmenus.inc
src/Buffer.cpp
src/Buffer.h
src/LyXFunc.cpp

index 5b0602961f5fdb401f26294646b336a4d12e5f8f..56aeb90a2a3a9ed5c6551633f6bbb3be6d4769ea 100644 (file)
@@ -41,7 +41,7 @@ Menuset
                Item "Save|S" "buffer-write"
                Item "Save As...|A" "buffer-write-as"
                Item "Save All|l" "buffer-write-all"
-               Item "Revert|R" "buffer-reload"
+               Item "Revert to saved|R" "buffer-reload"
                Submenu "Version Control|V" "file_vc"
                Separator
                Submenu "Import|I" "file_import"
index d55b5961475258503693e4a76c943cd87958915b..e5de38c4822312d9198ff5850e25c63f9feea08e 100644 (file)
@@ -103,6 +103,7 @@ using std::pair;
 using std::stack;
 using std::vector;
 using std::string;
+using std::time_t;
 
 
 namespace lyx {
@@ -131,6 +132,7 @@ using support::split;
 using support::subst;
 using support::tempName;
 using support::trim;
+using support::sum;
 
 namespace Alert = frontend::Alert;
 namespace os = support::os;
@@ -192,13 +194,18 @@ public:
 
        /// Container for all sort of Buffer dependant errors.
        map<string, ErrorList> errorLists;
+
+       /// timestamp and checksum used to test if the file has been externally
+       /// modified. (Used to properly enable 'File->Revert to saved', bug 4114).
+       time_t timestamp_;
+       unsigned long checksum_;
 };
 
 
 Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
        : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_),
          filename(file), file_fully_loaded(false), inset(params),
-         toc_backend(&parent)
+         timestamp_(0), checksum_(0), toc_backend(&parent)
 {
        inset.setAutoBreakRows(true);
        lyxvc.buffer(&parent);
@@ -755,6 +762,9 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename,
        //MacroTable::localMacros().clear();
 
        pimpl_->file_fully_loaded = true;
+       // save the timestamp and checksum of disk file
+       pimpl_->timestamp_ = fs::last_write_time(filename.toFilesystemEncoding());
+       pimpl_->checksum_ = sum(filename);
        return success;
 }
 
@@ -789,9 +799,22 @@ bool Buffer::save() const
                }
        }
 
+       // ask if the disk file has been externally modified (use checksum method)
+       if (fs::exists(encodedFilename) && isExternallyModified(checksum_method)) {
+               docstring const file = makeDisplayPath(fileName(), 20);
+               docstring text = bformat(_("Document %1$s has been externally modified. Are you sure "
+                                                            "you want to overwrite this file?"), file);
+               int const ret = Alert::prompt(_("Overwrite modified file?"),
+                       text, 1, 1, _("&Overwrite"), _("&Cancel"));
+               if (ret == 1)
+                       return false;
+       }
+
        if (writeFile(pimpl_->filename)) {
                markClean();
                removeAutosaveFile(fileName());
+               pimpl_->timestamp_ = fs::last_write_time(pimpl_->filename.toFilesystemEncoding());
+               pimpl_->checksum_ = sum(pimpl_->filename);
                return true;
        } else {
                // Saving failed, so backup is not backup
@@ -1556,6 +1579,16 @@ bool Buffer::isBakClean() const
 }
 
 
+bool Buffer::isExternallyModified(CheckMethod method) const
+{
+       BOOST_ASSERT(fs::exists(pimpl_->filename.toFilesystemEncoding()));
+       // if method == timestamp, check timestamp before checksum
+       return (method == checksum_method 
+               || pimpl_->timestamp_ != fs::last_write_time(pimpl_->filename.toFilesystemEncoding()))
+               && pimpl_->checksum_ != sum(pimpl_->filename);
+}
+
+
 void Buffer::markClean() const
 {
        if (!pimpl_->lyx_clean) {
index 2ce9ae6508337687ba2c2b9a3be86312b2d6235d..218f472744e20343b7142b41d71941d4b8277f19 100644 (file)
@@ -83,6 +83,22 @@ public:
                wrongversion ///< The version of the file does not match ours
        };
 
+       /// Method to check if a file is externally modified, used by 
+       /// isExternallyModified()
+       /**
+        * timestamp is fast but inaccurate. For example, the granularity
+        * of timestamp on a FAT filesystem is 2 second. Also, various operations
+        * may touch the timestamp of a file even when its content is unchanged.
+        *
+        * checksum is accurate but slow, which can be a problem when it is 
+        * frequently used, or used for a large file on a slow (network) file
+        * system.
+        */
+       enum CheckMethod {
+               checksum_method,  ///< Use file check sum
+               timestamp_method, ///< Use timestamp, and checksum if timestamp has changed
+       };
+       
        /** Constructor
            \param file
            \param b  optional \c false by default
@@ -210,6 +226,9 @@ public:
        ///
        bool isDepClean(std::string const & name) const;
 
+       /// whether or not disk file has been externally modified
+       bool isExternallyModified(CheckMethod method) const;
+
        /// mark the main lyx file as not needing saving
        void markClean() const;
 
index 075dd6c427a3e2395b13200c8f8edc78624d8f9c..e724ed0c78f6a7c3223113cacf2b43a5bd49dda3 100644 (file)
@@ -496,7 +496,8 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
                enable = buf->lyxvc().inUse();
                break;
        case LFUN_BUFFER_RELOAD:
-               enable = !buf->isUnnamed() && !buf->isClean();
+               enable = !buf->isUnnamed() && fs::exists(buf->fileName())
+                       && (!buf->isClean() || buf->isExternallyModified(Buffer::timestamp_method));
                break;
 
        case LFUN_INSET_SETTINGS: {