]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/autosave.cpp
refactored CONTENTS_DETAIL macro
[xonotic/netradiant.git] / radiant / autosave.cpp
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "autosave.h"
23
24 #include "os/file.h"
25 #include "os/path.h"
26 #include "cmdlib.h"
27 #include "stream/stringstream.h"
28 #include "gtkutil/messagebox.h"
29 #include "scenelib.h"
30 #include "mapfile.h"
31
32 #include "map.h"
33 #include "mainframe.h"
34 #include "qe3.h"
35 #include "preferences.h"
36
37
38 #if defined(WIN32)
39 #define PATH_MAX 260
40 #endif
41
42
43 bool DoesFileExist(const char* name, std::size_t& size)
44 {
45   if(file_exists(name))
46   {
47     size += file_size(name);
48     return true;
49   }
50   return false;
51 }
52
53 void Map_Snapshot()
54 {
55   // we need to do the following
56   // 1. make sure the snapshot directory exists (create it if it doesn't)
57   // 2. find out what the lastest save is based on number
58   // 3. inc that and save the map
59   const char* path = Map_Name(g_map);
60   const char* name = path_get_filename_start(path);
61
62   StringOutputStream snapshotsDir(256);
63   snapshotsDir << StringRange(path, name) << "snapshots";
64
65   if(file_exists(snapshotsDir.c_str()) || Q_mkdir(snapshotsDir.c_str()))
66   {
67     std::size_t lSize = 0;
68     StringOutputStream strNewPath(256);
69     strNewPath << snapshotsDir.c_str() << '/' << name;
70
71     StringOutputStream snapshotFilename(256);
72
73     for(int nCount = 0; ; ++nCount)
74     {
75       // The original map's filename is "<path>/<name>.<ext>"
76       // The snapshot's filename will be "<path>/snapshots/<name>.<count>.<ext>"
77       const char* end = path_get_filename_base_end(strNewPath.c_str());
78       snapshotFilename << StringRange(strNewPath.c_str(), end) << '.' << nCount << end;
79
80       if(!DoesFileExist(snapshotFilename.c_str(), lSize))
81       {
82         break;
83       }
84
85       snapshotFilename.clear();
86     }
87
88     // save in the next available slot
89     Map_SaveFile(snapshotFilename.c_str());
90
91     if (lSize > 50 * 1024 * 1024) // total size of saves > 50 mb
92     {
93       globalOutputStream() << "The snapshot files in " << snapshotsDir.c_str() << " total more than 50 megabytes. You might consider cleaning up.";
94     }
95   }
96   else
97   {
98     StringOutputStream strMsg(256);
99     strMsg << "Snapshot save failed.. unabled to create directory\n" << snapshotsDir.c_str();
100     gtk_MessageBox(GTK_WIDGET(MainFrame_getWindow()), strMsg.c_str());
101   }
102 }
103 /*
104 ===============
105 QE_CheckAutoSave
106
107 If five minutes have passed since making a change
108 and the map hasn't been saved, save it out.
109 ===============
110 */
111
112 bool g_AutoSave_Enabled = true;
113 int m_AutoSave_Frequency = 5;
114 bool g_SnapShots_Enabled = false;
115
116 namespace
117 {
118   time_t s_start = 0;
119   std::size_t s_changes = 0;
120 }
121
122 void AutoSave_clear()
123 {
124   s_changes = 0;
125 }
126
127 scene::Node& Map_Node()
128 {
129   return GlobalSceneGraph().root();
130 }
131
132 void QE_CheckAutoSave( void )
133 {
134   if(!Map_Valid(g_map) || !ScreenUpdates_Enabled())
135   {
136     return;
137   }
138
139   time_t now;
140   time(&now);
141
142   if(s_start == 0 || s_changes == Node_getMapFile(Map_Node())->changes())
143   {
144     s_start = now;
145   }
146
147   if((now - s_start) > (60 * m_AutoSave_Frequency))
148   {
149     s_start = now;
150     s_changes = Node_getMapFile(Map_Node())->changes();
151
152     if (g_AutoSave_Enabled)
153     {
154       const char* strMsg = g_SnapShots_Enabled ? "Autosaving snapshot..." : "Autosaving...";
155       globalOutputStream() << strMsg << "\n";
156       //Sys_Status(strMsg);
157
158       // only snapshot if not working on a default map
159       if (g_SnapShots_Enabled && !Map_Unnamed(g_map))
160       {
161         Map_Snapshot();
162       } 
163       else
164       {
165         if(Map_Unnamed(g_map))
166         {
167           StringOutputStream autosave(256);
168           autosave << g_qeglobals.m_userGamePath.c_str() << "maps/";
169           Q_mkdir(autosave.c_str());
170           autosave << "autosave.map";
171           Map_SaveFile(autosave.c_str());
172         }
173         else
174         {
175           const char* name = Map_Name(g_map);
176           const char* extension = path_get_filename_base_end(name);
177           StringOutputStream autosave(256);
178           autosave << StringRange(name, extension) << ".autosave" << extension;
179           Map_SaveFile(autosave.c_str());
180         }
181       }
182     }
183     else
184     {
185       globalOutputStream() << "Autosave skipped...\n";
186       //Sys_Status ("Autosave skipped...");
187     }
188   }
189 }
190
191 void Autosave_constructPreferences(PreferencesPage& page)
192 {
193   GtkWidget* autosave_enabled = page.appendCheckBox("Autosave", "Enable Autosave", g_AutoSave_Enabled);
194   GtkWidget* autosave_frequency = page.appendSpinner("Autosave Frequency (minutes)", m_AutoSave_Frequency, 1, 1, 60);
195   Widget_connectToggleDependency(autosave_frequency, autosave_enabled);
196   page.appendCheckBox("", "Save Snapshots", g_SnapShots_Enabled);
197 }
198 void Autosave_constructPage(PreferenceGroup& group)
199 {
200   PreferencesPage page(group.createPage("Autosave", "Autosave Preferences"));
201   Autosave_constructPreferences(page);
202 }
203 void Autosave_registerPreferencesPage()
204 {
205   PreferencesDialog_addSettingsPage(FreeCaller1<PreferenceGroup&, Autosave_constructPage>());
206 }
207
208
209 #include "preferencesystem.h"
210 #include "stringio.h"
211
212 void Autosave_Construct()
213 {
214   GlobalPreferenceSystem().registerPreference("Autosave", BoolImportStringCaller(g_AutoSave_Enabled), BoolExportStringCaller(g_AutoSave_Enabled));
215   GlobalPreferenceSystem().registerPreference("AutosaveMinutes", IntImportStringCaller(m_AutoSave_Frequency), IntExportStringCaller(m_AutoSave_Frequency));
216   GlobalPreferenceSystem().registerPreference("Snapshots", BoolImportStringCaller(g_SnapShots_Enabled), BoolExportStringCaller(g_SnapShots_Enabled));
217
218   Autosave_registerPreferencesPage();
219 }
220
221 void Autosave_Destroy()
222 {
223 }
224