]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/autosave.cpp
reformat code! now the code is only ugly on the *inside*
[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 <uilib/uilib.h>
23 #include "autosave.h"
24 #include "globaldefs.h"
25
26 #include "os/file.h"
27 #include "os/path.h"
28 #include "cmdlib.h"
29 #include "stream/stringstream.h"
30 #include "gtkutil/messagebox.h"
31 #include "scenelib.h"
32 #include "mapfile.h"
33
34 #include "map.h"
35 #include "mainframe.h"
36 #include "qe3.h"
37 #include "preferences.h"
38
39
40 #if GDEF_OS_WINDOWS
41 #define PATH_MAX 260
42 #endif
43
44
45 bool DoesFileExist(const char *name, std::size_t &size)
46 {
47     if (file_exists(name)) {
48         size += file_size(name);
49         return true;
50     }
51     return false;
52 }
53
54 void Map_Snapshot()
55 {
56     // we need to do the following
57     // 1. make sure the snapshot directory exists (create it if it doesn't)
58     // 2. find out what the lastest save is based on number
59     // 3. inc that and save the map
60     const char *path = Map_Name(g_map);
61     const char *name = path_get_filename_start(path);
62
63     StringOutputStream snapshotsDir(256);
64     snapshotsDir << StringRange(path, name) << "snapshots";
65
66     if (file_exists(snapshotsDir.c_str()) || Q_mkdir(snapshotsDir.c_str())) {
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             // The original map's filename is "<path>/<name>.<ext>"
75             // The snapshot's filename will be "<path>/snapshots/<name>.<count>.<ext>"
76             const char *end = path_get_filename_base_end(strNewPath.c_str());
77             snapshotFilename << StringRange(strNewPath.c_str(), end) << '.' << nCount << end;
78
79             if (!DoesFileExist(snapshotFilename.c_str(), lSize)) {
80                 break;
81             }
82
83             snapshotFilename.clear();
84         }
85
86         // save in the next available slot
87         Map_SaveFile(snapshotFilename.c_str());
88
89         if (lSize > 50 * 1024 * 1024) { // total size of saves > 50 mb
90             globalOutputStream() << "The snapshot files in " << snapshotsDir.c_str()
91                                  << " total more than 50 megabytes. You might consider cleaning up.";
92         }
93     } else {
94         StringOutputStream strMsg(256);
95         strMsg << "Snapshot save failed.. unabled to create directory\n" << snapshotsDir.c_str();
96         ui::alert(MainFrame_getWindow(), strMsg.c_str());
97     }
98 }
99
100 /*
101    ===============
102    QE_CheckAutoSave
103
104    If five minutes have passed since making a change
105    and the map hasn't been saved, save it out.
106    ===============
107  */
108
109 bool g_AutoSave_Enabled = true;
110 int m_AutoSave_Frequency = 5;
111 bool g_SnapShots_Enabled = false;
112
113 namespace {
114     time_t s_start = 0;
115     std::size_t s_changes = 0;
116 }
117
118 void AutoSave_clear()
119 {
120     s_changes = 0;
121 }
122
123 scene::Node &Map_Node()
124 {
125     return GlobalSceneGraph().root();
126 }
127
128 void QE_CheckAutoSave(void)
129 {
130     if (!Map_Valid(g_map) || !ScreenUpdates_Enabled()) {
131         return;
132     }
133
134     time_t now;
135     time(&now);
136
137     if (s_start == 0 || s_changes == Node_getMapFile(Map_Node())->changes()) {
138         s_start = now;
139     }
140
141     if ((now - s_start) > (60 * m_AutoSave_Frequency)) {
142         s_start = now;
143         s_changes = Node_getMapFile(Map_Node())->changes();
144
145         if (g_AutoSave_Enabled) {
146             const char *strMsg = g_SnapShots_Enabled ? "Autosaving snapshot..." : "Autosaving...";
147             globalOutputStream() << strMsg << "\n";
148             //Sys_Status(strMsg);
149
150             // only snapshot if not working on a default map
151             if (g_SnapShots_Enabled && !Map_Unnamed(g_map)) {
152                 Map_Snapshot();
153             } else {
154                 if (Map_Unnamed(g_map)) {
155                     StringOutputStream autosave(256);
156                     autosave << g_qeglobals.m_userGamePath.c_str() << "maps/";
157                     Q_mkdir(autosave.c_str());
158                     autosave << "autosave.map";
159                     Map_SaveFile(autosave.c_str());
160                 } else {
161                     const char *name = Map_Name(g_map);
162                     const char *extension = path_get_filename_base_end(name);
163                     StringOutputStream autosave(256);
164                     autosave << StringRange(name, extension) << ".autosave" << extension;
165                     Map_SaveFile(autosave.c_str());
166                 }
167             }
168         } else {
169             globalOutputStream() << "Autosave skipped...\n";
170             //Sys_Status ("Autosave skipped...");
171         }
172     }
173 }
174
175 void Autosave_constructPreferences(PreferencesPage &page)
176 {
177     ui::CheckButton autosave_enabled = page.appendCheckBox("Autosave", "Enable Autosave", g_AutoSave_Enabled);
178     ui::SpinButton autosave_frequency = page.appendSpinner("Autosave Frequency (minutes)", m_AutoSave_Frequency, 1, 1,
179                                                            60);
180     Widget_connectToggleDependency(autosave_frequency, autosave_enabled);
181     page.appendCheckBox("", "Save Snapshots", g_SnapShots_Enabled);
182 }
183
184 void Autosave_constructPage(PreferenceGroup &group)
185 {
186     PreferencesPage page(group.createPage("Autosave", "Autosave Preferences"));
187     Autosave_constructPreferences(page);
188 }
189
190 void Autosave_registerPreferencesPage()
191 {
192     PreferencesDialog_addSettingsPage(makeCallbackF(Autosave_constructPage));
193 }
194
195
196 #include "preferencesystem.h"
197 #include "stringio.h"
198
199 void Autosave_Construct()
200 {
201     GlobalPreferenceSystem().registerPreference("Autosave", make_property_string(g_AutoSave_Enabled));
202     GlobalPreferenceSystem().registerPreference("AutosaveMinutes", make_property_string(m_AutoSave_Frequency));
203     GlobalPreferenceSystem().registerPreference("Snapshots", make_property_string(g_SnapShots_Enabled));
204
205     Autosave_registerPreferencesPage();
206 }
207
208 void Autosave_Destroy()
209 {
210 }