1 #include <QtGui>
2 #include <QFileDialog>
3 #include <QMessageBox>
4 #include <QDesktopServices>
5 #include <QUrl>
6 
7 #include "mainwindow.h"
8 #include "ui_mainwindow.h"
9 #include "projectwindow.h"
10 #include "projectwidget.h"
11 #include "macros.h"
12 #include "qchdmansettings.h"
13 
14 extern QtChdmanGuiSettings *globalConfig;
15 extern quint64 runningProjects;
16 extern quint64 runningScripts;
17 
18 QStringList MainWindow::projectTypes;
19 QMap<QString, QList<DiskGeometry> > MainWindow::hardDiskTemplates;
20 
MainWindow(QWidget * parent)21 MainWindow::MainWindow(QWidget *parent) :
22 	QMainWindow(parent),
23 	ui(new Ui::MainWindow)
24 {
25 	ui->setupUi(this);
26 
27 	closeOk = true;
28 	forceQuit = false;
29 
30 #if QT_VERSION >= 0x040800
31 	ui->mdiArea->setTabsMovable(true);
32 	ui->mdiArea->setTabsClosable(true);
33 #endif
34 
35 	preferencesDialog = new PreferencesDialog(this);
36 	aboutDialog = new AboutDialog(this);
37 
38 	restoreGeometry(globalConfig->mainWindowGeometry());
39 	restoreState(globalConfig->mainWindowState());
40 
41 	setWindowTitle(QCHDMAN_APP_TITLE + " " + QCHDMAN_APP_VERSION + " [Qt " + qVersion() + "]");
42 	nextProjectID = 0;
43 
44 	if ( projectTypes.isEmpty() )
45 		projectTypes << "Info" << "Verify" << "Copy" << "CreateRaw" << "CreateHD" << "CreateCD" << "CreateLD" << "ExtractRaw" << "ExtractHD" << "ExtractCD" << "ExtractLD" << "DumpMeta" << "AddMeta" << "DelMeta";
46 
47 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
48 		on_actionWindowViewModeWindowed_triggered();
49 	else
50 		on_actionWindowViewModeTabbed_triggered();
51 
52 	recentFiles = globalConfig->mainWindowRecentFiles();
53 	foreach (QString file, recentFiles) {
54 		QFile f(file);
55 		if ( f.exists() )
56 			ui->menuProjectRecent->addAction(file, this, SLOT(loadRecentFile()));
57 	}
58 
59 	recentScripts = globalConfig->mainWindowRecentScripts();
60 	foreach (QString script, recentScripts) {
61 		QFile f(script);
62 		if ( f.exists() )
63 			ui->menuProjectRecentScripts->addAction(script, this, SLOT(loadRecentScript()));
64 	}
65 
66 	// sub-window icons
67 	iconMap[QCHDMAN_PRJ_INFO] = QIcon(":/images/info.png");
68 	iconMap[QCHDMAN_PRJ_VERIFY] = QIcon(":/images/verify.png");
69 	iconMap[QCHDMAN_PRJ_COPY] = QIcon(":/images/copy.png");
70 	iconMap[QCHDMAN_PRJ_CREATE_RAW] = QIcon(":/images/createraw.png");
71 	iconMap[QCHDMAN_PRJ_CREATE_HD] = QIcon(":/images/createhd.png");
72 	iconMap[QCHDMAN_PRJ_CREATE_CD] = QIcon(":/images/createcd.png");
73 	iconMap[QCHDMAN_PRJ_CREATE_LD] = QIcon(":/images/createld.png");
74 	iconMap[QCHDMAN_PRJ_EXTRACT_RAW] = QIcon(":/images/extractraw.png");
75 	iconMap[QCHDMAN_PRJ_EXTRACT_HD] = QIcon(":/images/extracthd.png");
76 	iconMap[QCHDMAN_PRJ_EXTRACT_CD] = QIcon(":/images/extractcd.png");
77 	iconMap[QCHDMAN_PRJ_EXTRACT_LD] = QIcon(":/images/extractld.png");
78 	iconMap[QCHDMAN_PRJ_DUMP_META] = QIcon(":/images/dumpmeta.png");
79 	iconMap[QCHDMAN_PRJ_ADD_META] = QIcon(":/images/addmeta.png");
80 	iconMap[QCHDMAN_PRJ_DEL_META] = QIcon(":/images/delmeta.png");
81 
82 	// compression codecs
83 	compressionTypes["avhu"] = tr("avhu (A/V Huffman)");
84 	compressionTypes["cdfl"] = tr("cdfl (CD FLAC)");
85 	compressionTypes["cdlz"] = tr("cdlz (CD LZMA)");
86 	compressionTypes["cdzl"] = tr("cdzl (CD Deflate)");
87 	compressionTypes["flac"] = tr("flac (FLAC)");
88 	compressionTypes["huff"] = tr("huff (Huffman)");
89 	compressionTypes["lzma"] = tr("lzma (LZMA)");
90 	compressionTypes["zlib"] = tr("zlib (Deflate)");
91 
92 	// morph & clone types
93 	copyTypes[QCHDMAN_PRJ_INFO]
94 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_CHECKBOX;
95 	copyTypes[QCHDMAN_PRJ_VERIFY]
96 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT;
97 	copyTypes[QCHDMAN_PRJ_COPY]
98 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
99 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
100 			<< QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_COMBOBOX;
101 	copyTypes[QCHDMAN_PRJ_CREATE_RAW]
102 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
103 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
104 			<< QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_COMBOBOX
105 			<< QCHDMAN_TYPE_SPINBOX;
106 	copyTypes[QCHDMAN_PRJ_CREATE_HD]
107 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
108 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
109 			<< QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_COMBOBOX
110 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
111 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_SPINBOX;
112 	copyTypes[QCHDMAN_PRJ_CREATE_CD]
113 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
114 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
115 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_COMBOBOX;
116 	copyTypes[QCHDMAN_PRJ_CREATE_LD]
117 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
118 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
119 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_COMBOBOX
120 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
121 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX;
122 	copyTypes[QCHDMAN_PRJ_EXTRACT_RAW]
123 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE
124 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
125 			<< QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX;
126 	copyTypes[QCHDMAN_PRJ_EXTRACT_HD]
127 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE
128 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX
129 			<< QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX;
130 	copyTypes[QCHDMAN_PRJ_EXTRACT_CD]
131 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
132 			<< QCHDMAN_TYPE_CHECKBOX;
133 	copyTypes[QCHDMAN_PRJ_EXTRACT_LD]
134 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE
135 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
136 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
137 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
138 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_SPINBOX;
139 	copyTypes[QCHDMAN_PRJ_DUMP_META]
140 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
141 			<< QCHDMAN_TYPE_CHECKBOX << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
142 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
143 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
144 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
145 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_SPINBOX;
146 	copyTypes[QCHDMAN_PRJ_ADD_META]
147 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
148 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
149 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
150 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
151 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
152 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_SPINBOX << QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_LINEEDIT
153 			<< QCHDMAN_TYPE_CHECKBOX;
154 	copyTypes[QCHDMAN_PRJ_DEL_META]
155 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
156 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
157 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
158 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
159 			<< QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE << QCHDMAN_TYPE_NONE
160 			<< QCHDMAN_TYPE_LINEEDIT << QCHDMAN_TYPE_SPINBOX;
161 
162 	// hard disk templates
163 	hardDiskTemplates["Alps Electric"]
164 			<< DiskGeometry("DRND-10A", 615, 2, 17, 256)
165 			<< DiskGeometry("DRND-20A", 615, 4, 17, 256)
166 			<< DiskGeometry("RPO-20A", 615, 4, 17, 512);
167 
168 	hardDiskTemplates["Ampex"]
169 			<< DiskGeometry("Pyxis-7", 320, 2, 17, 512)
170 			<< DiskGeometry("Pyxis-13", 320, 4, 17, 512)
171 			<< DiskGeometry("Pyxis-20", 320, 6, 17, 512)
172 			<< DiskGeometry("Pyxis-27", 320, 8, 17, 512);
173 
174 	hardDiskTemplates["Amstrad"]
175 			<< DiskGeometry("DRMD2OA12A", 615, 4, 17, 512)
176 			<< DiskGeometry("SRD 30400-50", 822, 2, 51, 512)
177 			<< DiskGeometry("SRD 3O8OC-50", 964, 10, 17, 512);
178 
179 	hardDiskTemplates["APS Technologies"]
180 			<< DiskGeometry("MS 4.0", 3124, 19, 144, 512)
181 			<< DiskGeometry("Q 10800", 2864, 16, 46, 512)
182 			<< DiskGeometry("Q 2.0", 3850, 10, 109, 512)
183 			<< DiskGeometry("ST 2000(W)", 6311, 4, 175, 512)
184 			<< DiskGeometry("ST 23000(W)", 6880, 28, 237, 512)
185 			<< DiskGeometry("ST 4200", 3992, 19, 110, 512)
186 			<< DiskGeometry("ST 9.0", 2925, 27, 133, 512);
187 
188 	hardDiskTemplates["Blue Disk"]
189 			<< DiskGeometry("CD 1241-ISA", 976, 8, 31, 512)
190 			<< DiskGeometry("CD 1501-ISA", 989, 8, 37, 512)
191 			<< DiskGeometry("CD 2401-ISA", 977, 8, 59, 512)
192 			<< DiskGeometry("CD 3251-ISA", 1024, 12, 51, 512)
193 			<< DiskGeometry("CD 421-ISA", 976, 4, 21, 512)
194 			<< DiskGeometry("CD 5101", 977, 14, 72, 512);
195 
196 	hardDiskTemplates["Conner"]
197 			<< DiskGeometry("CP3024", 636, 2, 33, 512)
198 			<< DiskGeometry("CP349", 788, 4, 26, 512)
199 			<< DiskGeometry("CFA 2161A", 1023, 64, 63, 512)
200 			<< DiskGeometry("CFS 1275A", 2479, 16, 63, 512)
201 			<< DiskGeometry("CFS 1621A", 3146, 16, 63, 512)
202 			<< DiskGeometry("CFP 1080S(E)", 3658, 6, 96, 512)
203 			<< DiskGeometry("CFP 4217S", 6028, 10, 147, 512)
204 			<< DiskGeometry("CFP 9117S", 6028, 20, 158, 512)
205 			<< DiskGeometry("CP3184", 832, 6, 33, 512)
206 			<< DiskGeometry("CP3104", 776, 8, 33, 512)
207 			<< DiskGeometry("CFS210A", 685, 16, 38, 512);
208 
209 	hardDiskTemplates["Data General"]
210 			<< DiskGeometry("6301", 640, 7, 17, 512)
211 			<< DiskGeometry("6338", 1024, 8, 17, 512)
212 			<< DiskGeometry("6339", 965, 15, 17, 512);
213 
214 	hardDiskTemplates["DMA"]
215 			<< DiskGeometry("306", 612, 2, 17, 256);
216 
217 	hardDiskTemplates["Hitachi"]
218 			<< DiskGeometry("DK226A-21", 4188, 16, 63, 512)
219 			<< DiskGeometry("DK227A-41", 7944, 16, 63, 512);
220 
221 	hardDiskTemplates["JVC"]
222 			<< DiskGeometry("JD 3812M0Z0", 436, 2, 48, 512)
223 			<< DiskGeometry("JD E3848HA", 436, 4, 48, 512);
224 
225 	hardDiskTemplates["JTC"]
226 			<< DiskGeometry("100", 131, 4, 17, 512)
227 			<< DiskGeometry("1006", 436, 2, 17, 512)
228 			<< DiskGeometry("1010", 436, 4, 17, 512);
229 
230 	hardDiskTemplates["Magtron"]
231 			<< DiskGeometry("MT 5760", 1632, 15, 54, 512);
232 
233 	hardDiskTemplates["Maxtor"]
234 			<< DiskGeometry("72025AP", 3936, 16, 63, 512)
235 			<< DiskGeometry("72577AV", 4996, 16, 63, 512)
236 			<< DiskGeometry("82625A6", 5100, 16, 63, 512)
237 			<< DiskGeometry("83209A5", 6218, 16, 63, 512)
238 			<< DiskGeometry("83500A4", 7237, 16, 63, 512)
239 			<< DiskGeometry("84000A6", 7763, 16, 63, 512)
240 			<< DiskGeometry("85250A6", 10856, 16, 63, 512)
241 			<< DiskGeometry("86480A8", 13392, 16, 63, 512)
242 			<< DiskGeometry("87000A8", 14475, 16, 63, 512)
243 			<< DiskGeometry("88400D8", 16278, 16, 63, 512)
244 			<< DiskGeometry("MXT 1240S", 2512, 15, 67, 512)
245 			<< DiskGeometry("XT-1065", 918, 7, 17, 512)
246 			<< DiskGeometry("XT-1085", 1024, 8, 17, 512)
247 			<< DiskGeometry("XT-1105", 918, 11, 17, 512)
248 			<< DiskGeometry("XT-2085", 1224, 7, 33, 256)
249 			<< DiskGeometry("XT-2190", 1224, 15, 33, 256)
250 			<< DiskGeometry("XT-4170E/S", 1224, 7, 36, 512)
251 			<< DiskGeometry("XT-4280S", 1224, 11, 36, 512)
252 			<< DiskGeometry("XT-8380S", 1632, 8, 54, 512)
253 			<< DiskGeometry("XT-8760S", 1632, 15, 54, 512);
254 
255 	hardDiskTemplates["Olivetti"]
256 			<< DiskGeometry("HD 362", 612, 4, 17, 512)
257 			<< DiskGeometry("HD 561-1", 180, 2, 17, 512)
258 			<< DiskGeometry("HD 561-2", 180, 4, 17, 512)
259 			<< DiskGeometry("HD 561-3", 180, 6, 17, 512)
260 			<< DiskGeometry("HD 662/11", 612, 2, 17, 512)
261 			<< DiskGeometry("HD 662/12", 612, 4, 17, 512)
262 			<< DiskGeometry("HD 674", 820, 6, 17, 512);
263 
264 	hardDiskTemplates["Quantum"]
265 			<< DiskGeometry("ProDrive 40 S", 834, 3, 35, 512) // SCSI
266 			<< DiskGeometry("ProDrive 105 S", 1019, 6, 35, 512) // SCSI
267 			<< DiskGeometry("ProDrive 170 AT", 1123, 7, 43, 512)
268 			<< DiskGeometry("ProDrive 210 AT", 1156, 7, 56, 512)
269 			<< DiskGeometry("ProDrive 425 AT", 1021, 16, 51, 512)
270 			<< DiskGeometry("ProDrive LPS 525 AT", 1017, 16, 63, 512);
271 
272 	hardDiskTemplates["Samsung"]
273 			<< DiskGeometry("SP 1366D", 26464, 16, 63, 512)
274 			<< DiskGeometry("SV 1296A/D", 25038, 16, 63, 512)
275 			<< DiskGeometry("SV 1533D", 29660, 16, 63, 512)
276 			<< DiskGeometry("SV 1705D", 33187, 16, 63, 512)
277 			<< DiskGeometry("SV 1824D", 35324, 16, 63, 512)
278 			<< DiskGeometry("SV 2044D", 39546, 16, 63, 512);
279 
280 	hardDiskTemplates["Seagate"]
281 			<< DiskGeometry("ST-506", 153, 4, 32, 256)
282 			<< DiskGeometry("ST-412", 306, 4, 32, 256)
283 			<< DiskGeometry("ST-225", 615, 4, 17, 512) // same specs as Western Digital WD262
284 			<< DiskGeometry("ST-251", 820, 6, 17, 512)
285 			<< DiskGeometry("ST-9100A", 748, 14, 16, 512)
286 			<< DiskGeometry("ST-3243A", 1024, 12, 34, 512)
287 			<< DiskGeometry("ST-9655AG", 1024, 16, 64, 512)
288 			<< DiskGeometry("ST-423451N", 6876, 28, 237, 512);
289 
290 	hardDiskTemplates["Texas Instruments"]
291 			<< DiskGeometry("TI-5", 153, 4, 17, 512)
292 			<< DiskGeometry("525-122", 306, 4, 17, 512);
293 
294 	hardDiskTemplates["Western Digital"]
295 			<< DiskGeometry("WD262", 615, 4, 17, 512) // same specs as Seagate ST-225
296 			<< DiskGeometry("WD95038X", 615, 6, 17, 512)
297 			<< DiskGeometry("WDAC140", 980, 5, 17, 512)
298 			<< DiskGeometry("WDAC280", 980, 10, 17, 512)
299 			<< DiskGeometry("WDAC1170", 1010, 6, 55, 512)
300 			<< DiskGeometry("WDAC2340", 1010, 12, 55, 512)
301 			<< DiskGeometry("WDAC2700", 1416, 16, 63, 512)
302 			<< DiskGeometry("WDAC11000", 2046, 16, 63, 512);
303 
304 	hardDiskTemplates["Applied Engineering"]
305 			<< DiskGeometry("Vulcan 40MB", 960, 5, 17, 512)
306 			<< DiskGeometry("Vulcan 80MB v1", 1067, 5, 29, 512)
307 			<< DiskGeometry("Vulcan 80MB v2", 954, 10, 17, 512)
308 			<< DiskGeometry("Vulcan 100MB", 863, 7, 34, 512)
309 			<< DiskGeometry("Vulcan 140MB", 1068, 9, 29, 512);
310 
311 	statisticsLabel = new QLabel(this);
312 	statusBar()->addPermanentWidget(statisticsLabel);
313 	updateStatus();
314 	connect(&statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
315 	statusTimer.start(QCHDMAN_STATUS_INTERVAL);
316 
317 	QTimer::singleShot(0, preferencesDialog, SLOT(applySettings()));
318 
319 	// check CHDMAN binary setting
320 	QFileInfo chdmanFileInfo(globalConfig->preferencesChdmanBinary());
321 	if ( globalConfig->preferencesChdmanBinary().isEmpty() || !chdmanFileInfo.isExecutable() )
322 		QTimer::singleShot(100, preferencesDialog, SLOT(initialSetup()));
323 }
324 
~MainWindow()325 MainWindow::~MainWindow()
326 {
327 	delete ui;
328 	globalConfig->deleteLater();
329 }
330 
mdiArea()331 QMdiArea *MainWindow::mdiArea()
332 {
333 	return ui->mdiArea;
334 }
335 
on_actionProjectNew_triggered(bool)336 void MainWindow::on_actionProjectNew_triggered(bool)
337 {
338 	createProjectWindow(QCHDMAN_MDI_PROJECT);
339 }
340 
on_actionProjectNewScript_triggered(bool checked)341 void MainWindow::on_actionProjectNewScript_triggered(bool checked)
342 {
343 	createProjectWindow(QCHDMAN_MDI_SCRIPT);
344 }
345 
on_actionProjectLoad_triggered(bool)346 void MainWindow::on_actionProjectLoad_triggered(bool)
347 {
348 	QString fileName = QFileDialog::getOpenFileName(this, tr("Choose project file"), QString(), tr("Project files (*.prj)") + ";;" + tr("All files (*)"), 0, globalConfig->preferencesNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
349 	if ( !fileName.isNull() ) {
350 		ProjectWindow *projectWindow = new ProjectWindow(fileName, QCHDMAN_MDI_PROJECT, ui->mdiArea);
351 		projectWindow->show();
352 		if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
353 			if ( globalConfig->preferencesMaximizeWindows() )
354 				projectWindow->showMaximized();
355 		projectWindow->projectWidget->load(fileName);
356 	}
357 }
358 
on_actionProjectLoadScript_triggered(bool checked)359 void MainWindow::on_actionProjectLoadScript_triggered(bool checked)
360 {
361 	QString fileName = QFileDialog::getOpenFileName(this, tr("Choose script file"), QString(), tr("Script files (*.scr)") + ";;" + tr("All files (*)"), 0, globalConfig->preferencesNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
362 	if ( !fileName.isNull() ) {
363 		ProjectWindow *projectWindow = new ProjectWindow(fileName, QCHDMAN_MDI_SCRIPT, ui->mdiArea);
364 		projectWindow->show();
365 		if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
366 			if ( globalConfig->preferencesMaximizeWindows() )
367 				projectWindow->showMaximized();
368 		projectWindow->scriptWidget->load(fileName);
369 	}
370 }
371 
on_actionProjectSave_triggered(bool)372 void MainWindow::on_actionProjectSave_triggered(bool)
373 {
374 	ProjectWindow *projectWindow = (ProjectWindow *)ui->mdiArea->activeSubWindow();
375 	if ( projectWindow ) {
376 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT )
377 			projectWindow->projectWidget->save();
378 		else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT )
379 			projectWindow->scriptWidget->save();
380 	}
381 }
382 
on_actionProjectSaveAs_triggered(bool)383 void MainWindow::on_actionProjectSaveAs_triggered(bool)
384 {
385 	ProjectWindow *projectWindow = (ProjectWindow *)ui->mdiArea->activeSubWindow();
386 	if ( projectWindow ) {
387 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
388 			projectWindow->projectWidget->askFileName = true;
389 			projectWindow->projectWidget->saveAs();
390 			projectWindow->projectWidget->askFileName = false;
391 		} else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT ) {
392 			projectWindow->scriptWidget->askFileName = true;
393 			projectWindow->scriptWidget->saveAs();
394 			projectWindow->scriptWidget->askFileName = false;
395 		}
396 	}
397 }
398 
on_actionProjectSaveAll_triggered(bool)399 void MainWindow::on_actionProjectSaveAll_triggered(bool)
400 {
401 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
402 		ProjectWindow *projectWindow = (ProjectWindow *)w;
403 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
404 			ProjectWidget *projectWidget = (ProjectWidget *)projectWindow->widget();
405 			projectWidget->save();
406 		} else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT ) {
407 			ScriptWidget *scriptWidget = (ScriptWidget *)projectWindow->widget();
408 			scriptWidget->save();
409 		}
410 	}
411 }
412 
on_actionProjectPreferences_triggered(bool)413 void MainWindow::on_actionProjectPreferences_triggered(bool)
414 {
415 	preferencesDialog->show();
416 }
417 
on_actionProjectExit_triggered(bool)418 void MainWindow::on_actionProjectExit_triggered(bool)
419 {
420 	QTimer::singleShot(0, this, SLOT(close()));
421 }
422 
on_actionWindowNext_triggered(bool)423 void MainWindow::on_actionWindowNext_triggered(bool)
424 {
425 	ui->mdiArea->activateNextSubWindow();
426 }
427 
on_actionWindowPrevious_triggered(bool)428 void MainWindow::on_actionWindowPrevious_triggered(bool)
429 {
430 	ui->mdiArea->activatePreviousSubWindow();
431 }
432 
on_actionWindowTile_triggered(bool)433 void MainWindow::on_actionWindowTile_triggered(bool)
434 {
435 	ui->mdiArea->tileSubWindows();
436 	QTimer::singleShot(0, this, SLOT(updateSubWindows()));
437 }
438 
on_actionWindowCascade_triggered(bool)439 void MainWindow::on_actionWindowCascade_triggered(bool)
440 {
441 	ui->mdiArea->cascadeSubWindows();
442 	QTimer::singleShot(0, this, SLOT(updateSubWindows()));
443 }
444 
on_actionWindowClose_triggered(bool)445 void MainWindow::on_actionWindowClose_triggered(bool)
446 {
447 	ui->mdiArea->closeActiveSubWindow();
448 }
449 
on_actionWindowCloseAll_triggered(bool)450 void MainWindow::on_actionWindowCloseAll_triggered(bool)
451 {
452 	ui->mdiArea->closeAllSubWindows();
453 }
454 
on_actionWindowViewModeWindowed_triggered(bool)455 void MainWindow::on_actionWindowViewModeWindowed_triggered(bool)
456 {
457 	ui->actionWindowViewModeWindowed->setChecked(true);
458 	ui->actionWindowViewModeTabbed->setChecked(false);
459 	globalConfig->setMainWindowViewMode(QCHDMAN_VIEWMODE_WINDOWED);
460 	ui->mdiArea->setViewMode(QCHDMAN_VIEWMODE_WINDOWED);
461 	if ( !ui->mdiArea->subWindowList().isEmpty() ) {
462 		ui->actionWindowCascade->setEnabled(true);
463 		ui->actionWindowTile->setEnabled(true);
464 	}
465 
466 	applySettings();
467 
468 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
469 		ProjectWindow *projectWindow = (ProjectWindow *)w;
470 		if ( globalConfig->preferencesMaximizeWindows() ) {
471 			projectWindow->showMaximized();
472 			qApp->processEvents();
473 		}
474 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT )
475 			projectWindow->projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
476 	}
477 }
478 
on_actionWindowViewModeTabbed_triggered(bool)479 void MainWindow::on_actionWindowViewModeTabbed_triggered(bool)
480 {
481 	ui->actionWindowViewModeTabbed->setChecked(true);
482 	ui->actionWindowViewModeWindowed->setChecked(false);
483 	globalConfig->setMainWindowViewMode(QCHDMAN_VIEWMODE_TABBED);
484 	ui->mdiArea->setViewMode(QCHDMAN_VIEWMODE_TABBED);
485 	ui->actionWindowCascade->setEnabled(false);
486 	ui->actionWindowTile->setEnabled(false);
487 	applySettings();
488 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
489 		ProjectWindow *projectWindow = (ProjectWindow *)w;
490 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT )
491 			projectWindow->projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
492 	}
493 }
494 
on_actionHelpAbout_triggered(bool)495 void MainWindow::on_actionHelpAbout_triggered(bool)
496 {
497 	aboutDialog->show();
498 }
499 
on_actionHelpAboutQt_triggered(bool)500 void MainWindow::on_actionHelpAboutQt_triggered(bool)
501 {
502 	QApplication::aboutQt();
503 }
504 
on_actionHelpWiki_triggered(bool)505 void MainWindow::on_actionHelpWiki_triggered(bool)
506 {
507 	QDesktopServices::openUrl(QUrl::fromUserInput("http://wiki.batcom-it.net/index.php?title=Qt_CHDMAN_GUI"));
508 }
509 
on_actionHelpForum_triggered(bool)510 void MainWindow::on_actionHelpForum_triggered(bool)
511 {
512 	QDesktopServices::openUrl(QUrl::fromUserInput("http://forums.bannister.org/ubbthreads.php?ubb=postlist&Board=12"));
513 }
514 
on_actionHelpBugTracker_triggered(bool checked)515 void MainWindow::on_actionHelpBugTracker_triggered(bool checked)
516 {
517 	QDesktopServices::openUrl(QUrl::fromUserInput("http://tracker.batcom-it.net/view_all_bug_page.php?project_id=1"));
518 }
519 
createProjectWindow(int type)520 ProjectWindow *MainWindow::createProjectWindow(int type)
521 {
522 	ProjectWindow *projectWindow = new ProjectWindow(QString(), type, ui->mdiArea);
523 
524 	projectWindow->show();
525 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
526 		if ( globalConfig->preferencesMaximizeWindows() )
527 			projectWindow->showMaximized();
528 
529 	return projectWindow;
530 }
531 
humanReadable(qreal value)532 QString MainWindow::humanReadable(qreal value)
533 {
534 	qreal humanReadableValue;
535 	QLocale locale;
536 
537 #if __WORDSIZE == 64
538 	if ( (qreal)value / (qreal)QCHDMAN_ONE_KILOBYTE < (qreal)QCHDMAN_ONE_KILOBYTE ) {
539 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_KILOBYTE;
540 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" KB"));
541 	} else if ( (qreal)value / (qreal)QCHDMAN_ONE_MEGABYTE < (qreal)QCHDMAN_ONE_KILOBYTE ) {
542 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_MEGABYTE;
543 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" MB"));
544 	} else if ( (qreal)value / (qreal)QCHDMAN_ONE_GIGABYTE < (qreal)QCHDMAN_ONE_KILOBYTE ) {
545 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_GIGABYTE;
546 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" GB"));
547 	} else {
548 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_TERABYTE;
549 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" TB"));
550 	}
551 #else
552 	if ( (qreal)value / (qreal)QCHDMAN_ONE_KILOBYTE < (qreal)QCHDMAN_ONE_KILOBYTE ) {
553 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_KILOBYTE;
554 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" KB"));
555 	} else if ( (qreal)value / (qreal)QCHDMAN_ONE_MEGABYTE < (qreal)QCHDMAN_ONE_KILOBYTE ) {
556 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_MEGABYTE;
557 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" MB"));
558 	} else {
559 		humanReadableValue = (qreal)value / (qreal)QCHDMAN_ONE_GIGABYTE;
560 		humanReadableString = locale.toString(humanReadableValue, 'f', 2) + QString(tr(" GB"));
561 	}
562 #endif
563 
564 	return humanReadableString;
565 }
566 
updateStatus()567 void MainWindow::updateStatus()
568 {
569 	statisticsLabel->setText(" " + tr("Running scripts / projects: %1 / %2").arg(runningScripts).arg(runningProjects) + " ");
570 }
571 
applySettings()572 void MainWindow::applySettings()
573 {
574 	qApp->processEvents();
575 	QFont logFont;
576 	logFont.fromString(globalConfig->preferencesLogFont());
577 	logFont.setPointSize(globalConfig->preferencesLogFontSize());
578 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
579 		ProjectWindow *projectWindow = (ProjectWindow *)w;
580 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
581 			ProjectWidget *projectWidget = (ProjectWidget *)projectWindow->widget();
582 			if ( projectWidget ) {
583 				projectWidget->setLogFont(logFont);
584 				projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
585 				projectWidget->needsTabbedUiAdjustment = true;
586 				projectWidget->needsWindowedUiAdjustment = true;
587 			}
588 		} else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT ) {
589 			ScriptWidget *scriptWidget = (ScriptWidget *)projectWindow->widget();
590 			if ( scriptWidget )
591 				scriptWidget->adjustFonts();
592 		}
593 	}
594 	preferredCHDInputFolder = globalConfig->preferencesPreferredCHDInputPath();
595 	preferredInputFolder = globalConfig->preferencesPreferredInputPath();
596 	preferredCHDOutputFolder = globalConfig->preferencesPreferredCHDOutputPath();
597 	preferredOutputFolder = globalConfig->preferencesPreferredOutputPath();
598 }
599 
updateSubWindows()600 void MainWindow::updateSubWindows()
601 {
602 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
603 		ProjectWindow *projectWindow = (ProjectWindow *)w;
604 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
605 			ProjectWidget *projectWidget = (ProjectWidget *)projectWindow->widget();
606 			projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
607 			projectWidget->needsTabbedUiAdjustment = true;
608 			projectWidget->needsWindowedUiAdjustment = true;
609 		}
610 	}
611 }
612 
addRecentFile(const QString & fileName)613 void MainWindow::addRecentFile(const QString &fileName)
614 {
615 	if ( !fileName.isEmpty() ) {
616 		recentFiles.removeAll(fileName);
617 		recentFiles.insert(0, fileName);
618 		if ( recentFiles.count() > QCHDMAN_MAX_RECENT_FILES )
619 			recentFiles.removeAt(recentFiles.count() - 1);
620 		ui->menuProjectRecent->clear();
621 		foreach (QString file, recentFiles) {
622 			QFile f(file);
623 			if ( f.exists() )
624 				ui->menuProjectRecent->addAction(file, this, SLOT(loadRecentFile()));
625 		}
626 		globalConfig->setMainWindowRecentFiles(recentFiles);
627 	}
628 }
629 
addRecentScript(const QString & fileName)630 void MainWindow::addRecentScript(const QString &fileName)
631 {
632 	if ( !fileName.isEmpty() ) {
633 		recentScripts.removeAll(fileName);
634 		recentScripts.insert(0, fileName);
635 		if ( recentScripts.count() > QCHDMAN_MAX_RECENT_FILES )
636 			recentScripts.removeAt(recentScripts.count() - 1);
637 		ui->menuProjectRecentScripts->clear();
638 		foreach (QString file, recentScripts) {
639 			QFile f(file);
640 			if ( f.exists() )
641 				ui->menuProjectRecentScripts->addAction(file, this, SLOT(loadRecentScript()));
642 		}
643 		globalConfig->setMainWindowRecentScripts(recentScripts);
644 	}
645 }
646 
loadRecentFile()647 void MainWindow::loadRecentFile()
648 {
649 	QAction *action = (QAction *)sender();
650 	QFile f(action->text());
651 	if ( !f.exists() ) {
652 		statusBar()->showMessage(tr("Project '%1' doesn't exist"), QCHDMAN_STATUS_MSGTIME);
653 		return;
654 	}
655 	ProjectWindow *projectWindow = new ProjectWindow(action->text(), QCHDMAN_MDI_PROJECT, ui->mdiArea);
656 	projectWindow->show();
657 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
658 		if ( globalConfig->preferencesMaximizeWindows() )
659 			projectWindow->showMaximized();
660 	projectWindow->projectWidget->load(action->text());
661 }
662 
loadRecentScript()663 void MainWindow::loadRecentScript()
664 {
665 	QAction *action = (QAction *)sender();
666 	QFile f(action->text());
667 	if ( !f.exists() ) {
668 		statusBar()->showMessage(tr("Script '%1' doesn't exist"), QCHDMAN_STATUS_MSGTIME);
669 		return;
670 	}
671 	ProjectWindow *projectWindow = new ProjectWindow(action->text(), QCHDMAN_MDI_SCRIPT, ui->mdiArea);
672 	projectWindow->show();
673 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED )
674 		if ( globalConfig->preferencesMaximizeWindows() )
675 			projectWindow->showMaximized();
676 	projectWindow->scriptWidget->load(action->text());
677 }
678 
enableActions(bool enable)679 void MainWindow::enableActions(bool enable)
680 {
681 	ui->actionProjectSave->setEnabled(enable);
682 	ui->actionProjectSaveAs->setEnabled(enable);
683 	ui->actionProjectSaveAll->setEnabled(enable);
684 	if ( ui->mdiArea->subWindowList().count() > 0 || !enable ) {
685 		ui->actionWindowNext->setEnabled(enable);
686 		ui->actionWindowPrevious->setEnabled(enable);
687 	}
688 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_WINDOWED ) {
689 		ui->actionWindowTile->setEnabled(enable);
690 		ui->actionWindowCascade->setEnabled(enable);
691 	}
692 	ui->actionWindowClose->setEnabled(enable);
693 	ui->actionWindowCloseAll->setEnabled(enable);
694 }
695 
disableActionsRequiringTwo()696 void MainWindow::disableActionsRequiringTwo()
697 {
698 	ui->actionWindowNext->setEnabled(false);
699 	ui->actionWindowPrevious->setEnabled(false);
700 }
701 
on_mdiArea_subWindowActivated(QMdiSubWindow * w)702 void MainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *w)
703 {
704 	if ( !w )
705 		return;
706 
707 	ProjectWindow *projectWindow = (ProjectWindow *)w;
708 	if ( globalConfig->mainWindowViewMode() == QCHDMAN_VIEWMODE_TABBED ) {
709 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
710 			if ( projectWindow->projectWidget->needsTabbedUiAdjustment ) {
711 				projectWindow->projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
712 				projectWindow->projectWidget->needsTabbedUiAdjustment = false;
713 			}
714 			projectWindow->projectWidget->needsWindowedUiAdjustment = true;
715 		}
716 	} else {
717 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
718 			if ( projectWindow->projectWidget->needsWindowedUiAdjustment ) {
719 				projectWindow->projectWidget->on_comboBoxProjectType_currentIndexChanged(-1);
720 				projectWindow->projectWidget->needsWindowedUiAdjustment = false;
721 			}
722 			projectWindow->projectWidget->needsTabbedUiAdjustment = true;
723 		} else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT ) {
724 			// NOP
725 		}
726 	}
727 }
728 
resizeEvent(QResizeEvent *)729 void MainWindow::resizeEvent(QResizeEvent *)
730 {
731 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
732 		ProjectWindow *projectWindow = (ProjectWindow *)w;
733 		if ( projectWindow->subWindowType == QCHDMAN_MDI_PROJECT ) {
734 			QTimer::singleShot(0, (ProjectWidget *)w->widget(), SLOT(triggerUpdate()));
735 		} else if ( projectWindow->subWindowType == QCHDMAN_MDI_SCRIPT ) {
736 			// NOP
737 		}
738 	}
739 }
740 
closeEvent(QCloseEvent * e)741 void MainWindow::closeEvent(QCloseEvent *e)
742 {
743 	closeOk = true;
744 	forceQuit = false;
745 
746 	if ( runningScripts > 0 ) {
747 		switch ( QMessageBox::question(this, tr("Confirm"),
748 					       tr("There are %n script(s) currently running.\n\nProceed?", "", runningScripts),
749 					       QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
750 		case QMessageBox::Yes:
751 			forceQuit = true;
752 			break;
753 		case QMessageBox::No:
754 		default:
755 			closeOk = false;
756 			forceQuit = false;
757 			QTimer::singleShot(100, this, SLOT(resetCloseFlag()));
758 			e->ignore();
759 			return;
760 			break;
761 		}
762 	}
763 
764 	int runningIndependentProjects = 0;
765 	foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
766 		ProjectWindow *pw = (ProjectWindow *)w;
767 		if ( pw->subWindowType == QCHDMAN_MDI_PROJECT )
768 			if ( !pw->projectWidget->isScriptElement && pw->projectWidget->status == QCHDMAN_PRJSTAT_RUNNING )
769 				runningIndependentProjects++;
770 	}
771 
772 	if ( runningIndependentProjects > 0 ) {
773 		switch ( QMessageBox::question(this, tr("Confirm"),
774 					       runningIndependentProjects == 1 ?
775 					       tr("There is 1 project currently running.\n\nClosing its window will kill the external process!\n\nProceed?") :
776 					       tr("There are %1 projects currently running.\n\nClosing their windows will kill the external processes!\n\nProceed?").arg(runningIndependentProjects),
777 					       QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
778 		case QMessageBox::Yes:
779 			forceQuit = true;
780 			break;
781 		case QMessageBox::No:
782 		default:
783 			closeOk = false;
784 			forceQuit = false;
785 			QTimer::singleShot(100, this, SLOT(resetCloseFlag()));
786 			e->ignore();
787 			return;
788 			break;
789 		}
790 	}
791 
792 	if ( closeOk ) {
793 		foreach (QMdiSubWindow *w, ui->mdiArea->subWindowList()) {
794 			if ( ((ProjectWindow *)w)->subWindowType == QCHDMAN_MDI_PROJECT ) {
795 				ProjectWidget *projectWidget = (ProjectWidget *)w->widget();
796 				if ( projectWidget ) {
797 					if ( projectWidget->chdmanProc && projectWidget->chdmanProc->state() == QProcess::Running )
798 						projectWidget->chdmanProc->terminate();
799 				}
800 			}
801 			QTimer::singleShot(0, w, SLOT(close()));
802 		}
803 
804 		globalConfig->setMainWindowState(saveState());
805 		globalConfig->setMainWindowGeometry(saveGeometry());
806 
807 		if ( preferencesDialog )
808 			delete preferencesDialog;
809 
810 		e->accept();
811 	} else
812 		e->ignore();
813 
814 	qApp->processEvents();
815 }
816