1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2010 Andrey Rijov <ANDron142@yandex.ru>
4 ** Copyright (C) 2016 Tobias Gläßer
5 **
6 ** This file is part of AQEMU.
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License.
11 **
12 ** This program 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 this program; if not, write to the Free Software
19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ** Boston, MA 02110-1301, USA.
21 **
22 ****************************************************************************/
23
24 #include <QDir>
25 #include <QFile>
26 #include <QFileInfo>
27 #include <QFileInfoList>
28 #include <QDateTime>
29 #include <QMessageBox>
30 #include <QApplication>
31 #include <QSettings>
32 #include <QRegExp>
33 #include <QProcess>
34 #include <QStringList>
35 #include <QTextStream>
36
37 #ifdef Q_OS_WIN32
38 #include <iostream>
39 #include <windows.h>
40 HANDLE Console_HANDLE = GetStdHandle( STD_OUTPUT_HANDLE );
41 #else
42 #include <QDebug>
43 #include <iostream>
44 #endif
45
46 #include "Utils.h"
47 #include "System_Info.h"
48
49 static uint Messages_Index = 0;
50
51 static bool Save_Messages_To_Log = true;
52 static QString Log_Path = "";
53
54 static bool Use_Stdout;
55 static bool Stdout_Debug;
56 static bool Stdout_Warning;
57 static bool Stdout_Error;
58
59 static bool Show_User_Graphic_Warning = true;
60
61 static QStringList Recent_CD_Images;
62 static QStringList Recent_FDD_Images;
63
Disable_User_Graphic_Warning()64 Disable_User_Graphic_Warning::Disable_User_Graphic_Warning()
65 {
66 Show_User_Graphic_Warning = false;
67 }
~Disable_User_Graphic_Warning()68 Disable_User_Graphic_Warning::~Disable_User_Graphic_Warning()
69 {
70 Show_User_Graphic_Warning = true;
71 }
72
AQDebugStdCout(const QString & s)73 void AQDebugStdCout(const QString& s)
74 {
75 std::cout << s.toLatin1().constData() << std::endl;
76 }
77
78
AQDebug(const QString & sender,const QString & mes)79 void AQDebug( const QString &sender, const QString &mes )
80 {
81 if( Use_Stdout && Stdout_Debug )
82 {
83 #ifdef Q_OS_WIN32
84 SetConsoleTextAttribute( Console_HANDLE, 10 );
85 std::cout << QString( "\nAQEMU Debug [%1] >>>\nSender: %2\nMessage: %3" )
86 .arg(Messages_Index).arg(sender).arg(mes).toStdString();
87 #else
88 AQDebugStdCout( QString(
89 "\n\33[32mAQEMU Debug\33[0m [%1] >>>\n\33[32mSender:\33[0m %2\n\33[32mMessage:\33[0m %3")
90 .arg(Messages_Index).arg(sender).arg(mes));
91 #endif
92 }
93
94 if( Save_Messages_To_Log && Stdout_Debug )
95 AQSave_To_Log( "Debug", sender, mes );
96
97 Messages_Index++;
98 }
99
AQWarning(const QString & sender,const QString & mes)100 void AQWarning( const QString &sender, const QString &mes )
101 {
102 if( Use_Stdout && Stdout_Warning )
103 {
104 #ifdef Q_OS_WIN32
105 SetConsoleTextAttribute( Console_HANDLE, 14 );
106 std::cout << QString( "\nAQEMU Warning [%1] >>>\nSender: %2\nMessage: %3" )
107 .arg(Messages_Index).arg(sender).arg(mes).toStdString();
108 #else
109 AQDebugStdCout( QString(
110 "\n\33[34mAQEMU Warning\33[0m [%1] >>>\n\33[34mSender:\33[0m %2\n\33[34mMessage:\33[0m %3")
111 .arg(Messages_Index).arg(sender).arg(mes));
112 #endif
113 }
114
115 if( Save_Messages_To_Log && Stdout_Warning )
116 AQSave_To_Log( "Warning", sender, mes );
117
118 Messages_Index++;
119 }
120
AQError(const QString & sender,const QString & mes)121 void AQError( const QString &sender, const QString &mes )
122 {
123 if( Use_Stdout && Stdout_Error )
124 {
125 #ifdef Q_OS_WIN32
126 SetConsoleTextAttribute( Console_HANDLE, 12 );
127 std::cout << QString( "\nAQEMU Error [%1] >>>\nSender: %2\nMessage: %3" )
128 .arg(Messages_Index).arg(sender).arg(mes).toStdString();
129 #else
130 AQDebugStdCout( QString(
131 "\n\33[31mAQEMU Error\33[0m [%1] >>>\n\33[31mSender:\33[0m %2\n\33[31mMessage:\33[0m %3")
132 .arg(Messages_Index).arg(sender).arg(mes));
133 #endif
134 }
135
136 if( Save_Messages_To_Log && Stdout_Error )
137 AQSave_To_Log( "Error", sender, mes );
138
139 Messages_Index++;
140 }
141
AQGraphic_Warning(const QString & caption,const QString & mes)142 void AQGraphic_Warning( const QString &caption, const QString &mes )
143 {
144 if ( Show_User_Graphic_Warning == false )
145 return;
146
147 QMessageBox::warning( NULL, caption, mes, QMessageBox::Ok );
148 }
149
AQGraphic_Warning(const QString & sender,const QString & caption,const QString & mes,bool fatal)150 void AQGraphic_Warning( const QString &sender, const QString &caption, const QString &mes, bool fatal )
151 {
152 if ( Show_User_Graphic_Warning == false )
153 return;
154
155 if( fatal )
156 {
157 QMessageBox::warning( NULL, caption,
158 QString("Sender: %1\nMessage: %2\n").arg(sender).arg(mes) +
159 QObject::tr("This Fatal Error. Recomend Close AQEMU."),
160 QMessageBox::Ok );
161 }
162 else
163 {
164 QMessageBox::warning( NULL, caption,
165 QString("Sender: %1\nMessage: %2").arg(sender).arg(mes),
166 QMessageBox::Ok );
167 }
168
169 if( Save_Messages_To_Log )
170 AQSave_To_Log( "Warning", sender, mes );
171 }
172
AQGraphic_Error(const QString & sender,const QString & caption,const QString & mes,bool fatal)173 void AQGraphic_Error( const QString &sender, const QString &caption, const QString &mes, bool fatal )
174 {
175 if( fatal )
176 {
177 QMessageBox::critical( NULL, caption,
178 QString("Sender: %1\nMessage: %2\n").arg(sender).arg(mes) +
179 QObject::tr("Fatal error. It's recommended to close AQEMU"),
180 QMessageBox::Ok );
181 }
182 else
183 {
184 QMessageBox::critical( NULL, caption,
185 QString("Sender: %1\nMessage: %2").arg(sender).arg(mes),
186 QMessageBox::Ok );
187 }
188
189 if( Save_Messages_To_Log )
190 AQSave_To_Log( "Error", sender, mes );
191 }
192
AQUse_Log(bool use)193 void AQUse_Log( bool use )
194 {
195 Save_Messages_To_Log = use;
196 }
197
AQUse_Debug_Output(bool use,bool d,bool w,bool e)198 void AQUse_Debug_Output( bool use, bool d, bool w, bool e )
199 {
200 Use_Stdout = use;
201 Stdout_Debug = d;
202 Stdout_Warning = w;
203 Stdout_Error = e;
204 }
205
AQLog_Path(const QString & path)206 void AQLog_Path( const QString& path )
207 {
208 Log_Path = path;
209 }
210
AQSave_To_Log(const QString & mes_type,const QString & sender,const QString & mes)211 void AQSave_To_Log( const QString &mes_type, const QString &sender, const QString &mes )
212 {
213 if( Log_Path.isEmpty() ) return;
214
215 QFile log_file( Log_Path );
216
217 if( ! log_file.open(QIODevice::Append | QIODevice::Text) )
218 {
219 AQUse_Log( false ); // off loging
220 AQError( "void AQSave_To_Log( const QString& mes_type, const QString& sender, const QString& mes )",
221 "Cannot Open Log file to Write! Log Path: \"" + Log_Path + "\"" );
222 }
223 else
224 {
225 QTextStream out( &log_file );
226 out << "Type: " << mes_type << " Num: " << Messages_Index << "\nDate: "
227 << QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss zzz")
228 << "\nSender: " << sender << "\nMessage: " << mes << "\n\n";
229 }
230 }
231
Create_New_HDD_Image(bool encrypted,const QString & base_image,const QString & file_name,const QString & format,VM::Device_Size size,bool verbose)232 bool Create_New_HDD_Image( bool encrypted, const QString &base_image,
233 const QString &file_name, const QString &format, VM::Device_Size size, bool verbose )
234 {
235 // Create command line
236 QStringList args;
237 args << "create";
238
239 if( encrypted )
240 args << "-e";
241
242 if( ! base_image.isEmpty() )
243 args << "-b" << base_image;
244
245 args << "-f" << format;
246
247 args << file_name;
248
249 switch( size.Suffix )
250 {
251 case VM::Size_Suf_Mb: // MB
252 args << QString::number( size.Size ) + "M";
253 break;
254
255 case VM::Size_Suf_Gb: // GB
256 args << QString::number( size.Size ) + "G";
257 break;
258
259 default: // KG
260 args << QString::number( size.Size );
261 break;
262 }
263
264 // Start qemu-img process
265 QProcess qemu_img;
266 QSettings settings;
267 qemu_img.start( settings.value("QEMU-IMG_Path", "qemu-img").toString(), args );
268
269 if( ! qemu_img.waitForStarted(2000) )
270 {
271 AQGraphic_Error( "bool Create_New_HDD_Image( bool encrypted, const QString &base_image,"
272 "const QString &file_name, const QString &format, VM::Device_Size size, bool verbose )",
273 QObject::tr("Error!"), QObject::tr("Cannot Start qemu-img! Image isn't Created!") );
274 return false;
275 }
276
277 if( ! qemu_img.waitForFinished(10000) )
278 {
279 AQGraphic_Error( "bool Create_New_HDD_Image( bool encrypted, const QString &base_image,"
280 "const QString &file_name, const QString &format, VM::Device_Size size, bool verbose )",
281 QObject::tr("Error!"), QObject::tr("qemu-img Cannot Finish! Image isn't Created!") );
282 return false;
283 }
284 else
285 {
286 QByteArray err = qemu_img.readAllStandardError();
287 QByteArray out = qemu_img.readAllStandardOutput();
288
289 if( err.count() > 0 )
290 {
291 AQGraphic_Error( "bool Create_New_HDD_Image( bool encrypted, const QString &base_image,"
292 "const QString &file_name, const QString &format, VM::Device_Size size, bool verbose )",
293 QObject::tr("Error!"), QObject::tr("Cannot Create Image!\nInformation: ") + err );
294 }
295
296 QRegExp rx( "Format*ing*fmt*size*" );
297 rx.setPatternSyntax( QRegExp::Wildcard );
298
299 if( verbose )
300 {
301 if( rx.exactMatch( out ) )
302 {
303 QMessageBox::information( NULL, QObject::tr("Complete!"),
304 QObject::tr("QEMU-IMG is Creates HDD Image.\nAdditional Information:\n") + out );
305 }
306 else
307 {
308 QMessageBox::information( NULL, QObject::tr("Warning!"),
309 QObject::tr("QEMU-IMG is Returned non Standard Message!.\nAdditional Information:\n") + out );
310 }
311 }
312
313 return true;
314 }
315 }
316
Create_New_HDD_Image(const QString & file_name,VM::Device_Size size)317 bool Create_New_HDD_Image( const QString &file_name, VM::Device_Size size )
318 {
319 QSettings settings;
320 QString format = settings.value( "Default_HDD_Image_Format", "qcow2" ).toString();
321
322 return Create_New_HDD_Image( false, "", file_name, format, size, false );
323 }
324
Format_HDD_Image(const QString & file_name,VM::Disk_Info info)325 bool Format_HDD_Image( const QString &file_name, VM::Disk_Info info )
326 {
327 if( file_name.isEmpty() )
328 {
329 AQError( "bool Format_HDD_Image( const QString &file_name )",
330 "File Name is Empty!" );
331
332 return false;
333 }
334
335 VM_HDD tmp_hd = VM_HDD( true, file_name );
336 tmp_hd.Set_Disk_Info( info );
337 QString hd_format = tmp_hd.Get_Image_Format();
338
339 if( hd_format.isEmpty() )
340 {
341 AQError( "bool Format_HDD_Image( const QString &file_name )",
342 "Format is Empty!" );
343
344 return false;
345 }
346
347 return Create_New_HDD_Image( false, "", file_name, hd_format, tmp_hd.Get_Virtual_Size(), false );
348 }
349
Get_Templates_List()350 QList<QString> Get_Templates_List()
351 {
352 QList<QString> all_templates;
353 QSettings settings;
354
355 // VM Templates
356 QDir sys_templates_dir( QDir::toNativeSeparators(settings.value("AQEMU_Data_Folder", "").toString() + "/os_templates/") );
357
358 QFileInfoList sys_templates_list = sys_templates_dir.entryInfoList(
359 QStringList("*.aqvmt"), QDir::Files, QDir::Unsorted );
360
361 QDir user_templates_dir( QDir::toNativeSeparators(settings.value("VM_Directory", "").toString() + "/os_templates/") );
362
363 QFileInfoList user_templates_list = user_templates_dir.entryInfoList(
364 QStringList("*.aqvmt"), QDir::Files, QDir::Unsorted );
365
366 for( int tx = 0; tx < sys_templates_list.count(); ++tx )
367 {
368 for( int ux = 0; ux < user_templates_list.count(); ++ux )
369 {
370 if( sys_templates_list[tx].completeBaseName() ==
371 user_templates_list[ux].completeBaseName() )
372 {
373 sys_templates_list.takeAt( tx ); // delete system template
374 tx -= 1;
375 ux = user_templates_list.count();
376 }
377 }
378 }
379
380 // OK. In Template Lists Only Unique Values
381 for( int ix = 0; ix < sys_templates_list.count(); ++ix )
382 all_templates.append( sys_templates_list[ix].absoluteFilePath() );
383
384 for( int ix = 0; ix < user_templates_list.count(); ++ix )
385 all_templates.append( user_templates_list[ix].absoluteFilePath() );
386
387 // sort
388 qSort( all_templates );
389
390 return all_templates;
391 }
392
393
Get_FS_Compatible_VM_Name(const QString & name)394 QString Get_FS_Compatible_VM_Name( const QString &name )
395 {
396 //QRegExp vm_name_val = QRegExp( "[^a-zA-Z0-9_]" ); // old style
397 QRegExp vm_name_val = QRegExp( "[^\\w\\.]" );
398
399 QString tmp = name;
400 tmp = tmp.replace( vm_name_val, "_" );
401
402 return tmp.replace( "__", "_" );
403 }
404
Get_Complete_VM_File_Path(const QString & vm_name)405 QString Get_Complete_VM_File_Path( const QString &vm_name )
406 {
407 //QRegExp vm_name_val = QRegExp( "[^a-zA-Z0-9_]" ); // old style
408 QRegExp vm_name_val = QRegExp( "[^\\w]" );
409
410 QString tmp = vm_name;
411 tmp = tmp.replace( vm_name_val, "_" );
412
413 QString new_name = tmp.replace( "__", "_" );
414 QString tmp_str = new_name;
415
416 QSettings settings;
417
418 QString ret_str = settings.value("VM_Directory", "").toString() + tmp_str;
419
420 if( ! ret_str.endsWith(".aqemu") )
421 ret_str += ".aqemu";
422
423 for( int ix = 0; QFile::exists(ret_str); ++ix )
424 tmp_str = new_name + QString::number( ix );
425
426 return ret_str;
427 }
428
Get_TR_Size_Suffix(VM::Device_Size suf)429 QString Get_TR_Size_Suffix( VM::Device_Size suf )
430 {
431 switch( suf.Suffix )
432 {
433 case VM::Size_Suf_Kb:
434 return QObject::tr("Kb");
435
436 case VM::Size_Suf_Mb:
437 return QObject::tr("Mb");
438
439 case VM::Size_Suf_Gb:
440 return QObject::tr("Gb");
441
442 default:
443 AQError( "QString Get_TR_Size_Suffix( VM::Device_Size suf )",
444 "Virtual Size Suffix Default Section!" );
445 return "";
446 }
447 }
448
Get_Last_Dir_Path(const QString & path)449 QString Get_Last_Dir_Path( const QString &path )
450 {
451 QFileInfo info( path );
452 QString dir = info.path();
453
454 if( dir.isEmpty() ) return "/";
455 else return dir;
456 }
457
It_Host_Device(const QString & path)458 bool It_Host_Device( const QString &path )
459 {
460 #ifdef Q_OS_WIN32
461 // FIXME
462 return false;
463 #else
464 if( path.startsWith("/dev/") ) return true;
465 else return false;
466 #endif
467 }
468
Check_AQEMU_Permissions()469 void Check_AQEMU_Permissions()
470 {
471 QSettings settings;
472 QFileInfo test_perm;
473
474 #ifndef Q_OS_WIN32
475 // This Section For Unix Like OS.
476 test_perm = QFileInfo( settings.fileName() );
477
478 if( test_perm.exists() )
479 {
480 if( ! test_perm.isWritable() )
481 {
482 AQGraphic_Error( "void Check_AQEMU_Permissions()", QObject::tr("Error!"),
483 QObject::tr("AQEMU Config File is Read Only!\nCheck Permissions For File: ") +
484 settings.fileName(), true );
485 }
486 }
487 #endif
488
489 // Check VM Dir Permissions
490 test_perm = QFileInfo( settings.value("VM_Directory", "~").toString() );
491
492 if( test_perm.exists() )
493 {
494 if( ! test_perm.isWritable() )
495 {
496 AQGraphic_Error( "void Check_AQEMU_Permissions()", QObject::tr("Error!"),
497 QObject::tr("AQEMU VM Directory is Read Only!\nCheck Permissions For: ") +
498 settings.value("VM_Directory", "~").toString(), true );
499 }
500 }
501
502 // Check VM Templates Dir Permissions
503 test_perm = QFileInfo( settings.value("VM_Directory", "~").toString() + "os_templates" );
504
505 if( test_perm.exists() )
506 {
507 if( ! test_perm.isWritable() )
508 {
509 AQGraphic_Error( "void Check_AQEMU_Permissions()", QObject::tr("Error!"),
510 QObject::tr("AQEMU VM Template Directory is Read Only!\nCheck Permissions For: ") +
511 settings.value("VM_Directory", "~").toString() + "os_templates", true );
512 }
513 }
514
515 // Check AQEMU Log File Permissions
516 if( ! settings.value("Log/Log_Path", "").toString().isEmpty() )
517 {
518 test_perm = QFileInfo( settings.value("Log/Log_Path", "").toString() );
519
520 if( test_perm.exists() )
521 {
522 if( ! test_perm.isWritable() )
523 {
524 AQGraphic_Error( "void Check_AQEMU_Permissions()", QObject::tr("Error!"),
525 QObject::tr("AQEMU Log File is Read Only!\nCheck Permissions For File: ") +
526 settings.value("Log/Log_Path", "").toString(), false );
527 }
528 }
529 }
530 }
531
String_To_Emulator_Version(const QString & str)532 VM::Emulator_Version String_To_Emulator_Version( const QString &str )
533 {
534 if( str == "QEMU 0.9.0" ) return VM::QEMU_2_0;
535 else if( str == "QEMU 0.9.1" ) return VM::QEMU_2_0;
536 else if( str == "QEMU 0.10.X" ) return VM::QEMU_2_0;
537 else if( str == "QEMU 0.11.X" ) return VM::QEMU_2_0;
538 else if( str == "QEMU 0.12.X" ) return VM::QEMU_2_0;
539 else if( str == "QEMU 0.13.X" ) return VM::QEMU_2_0;
540 else if( str == "QEMU 0.14.X" ) return VM::QEMU_2_0;
541 else if( str == "QEMU 0.15.X" ) return VM::QEMU_2_0;
542 else if( str == "QEMU 1.0" ) return VM::QEMU_2_0;
543 else if( str == "QEMU 2.0" ) return VM::QEMU_2_0;
544 else if( str == "KVM 7X" ) return VM::QEMU_2_0;
545 else if( str == "KVM 8X" ) return VM::QEMU_2_0;
546 else if( str == "KVM 0.11.X" ) return VM::QEMU_2_0;
547 else if( str == "KVM 0.12.X" ) return VM::QEMU_2_0;
548 else if( str == "KVM 0.13.X" ) return VM::QEMU_2_0;
549 else if( str == "KVM 0.14.X" ) return VM::QEMU_2_0;
550 else if( str == "KVM 0.15.X" ) return VM::QEMU_2_0;
551 else if( str == "KVM 1.0" ) return VM::QEMU_2_0;
552 else if( str == "Obsolete" ) return VM::Obsolete;
553 else
554 {
555 AQError( "VM::Emulator_Version String_To_Emulator_Version( const QString &str )",
556 QString("Emulator version \"%1\" not valid!").arg(str) );
557 return VM::Obsolete;
558 }
559 }
560
Emulator_Version_To_String(VM::Emulator_Version ver)561 QString Emulator_Version_To_String( VM::Emulator_Version ver )
562 {
563 switch( ver )
564 {
565 case VM::QEMU_2_0:
566 return "QEMU 2.0";
567
568 case VM::Obsolete:
569 return "Obsolete";
570
571 default:
572 AQError( "QString Emulator_Version_To_String( VM::Emulator_Version ver )",
573 QString("Emulator version \"%1\" not valid!").arg((int)ver) );
574 return "";
575 }
576 }
577
578 static QList<Emulator> Emulators_List;
579 static QList<Emulator> Empty_Emul_List;
580 static Emulator Empty_Emul;
581
Update_Emulators_List()582 bool Update_Emulators_List()
583 {
584 // Clear old emulator list
585 Emulators_List.clear();
586
587 // Get dir path
588 QSettings settings;
589 QFileInfo info( settings.fileName() );
590 QString aqemuSettingsFolder = info.absoluteDir().absolutePath();
591 if( ! (aqemuSettingsFolder.endsWith("/") || aqemuSettingsFolder.endsWith("\\")) )
592 aqemuSettingsFolder = QDir::toNativeSeparators( aqemuSettingsFolder + "/" );
593
594 if( ! QFile::exists(aqemuSettingsFolder) )
595 {
596 AQError( "bool Update_Emulators_List()",
597 QString("Cannot get path for save emulator! Folder \"%1\" not exists!").arg(aqemuSettingsFolder) );
598 return false;
599 }
600
601 // Get all *.emulators files
602 QDir emulDir( aqemuSettingsFolder );
603 QStringList emulFiles = emulDir.entryList( QStringList("*.emulator"), QDir::Files, QDir::Name );
604
605 if( emulFiles.isEmpty() )
606 {
607 AQWarning( "bool Update_Emulators_List()",
608 QString("No emulators found in \"%1\"").arg(aqemuSettingsFolder) );
609 return false;
610 }
611
612 // Check default emulators
613 bool qDef = false;
614
615 // Load emulators
616 for( int ex = 0; ex < emulFiles.count(); ++ex )
617 {
618 Emulator tmp;
619
620 if( ! tmp.Load(aqemuSettingsFolder + emulFiles[ex]) )
621 {
622 AQError( "bool Update_Emulators_List()",
623 QString("Cannot load emulator from file: \"%1\"").arg(emulFiles[ex]) );
624 continue;
625 }
626
627 // Default?
628 if( tmp.Get_Default() )
629 {
630 if( qDef )
631 {
632 AQWarning( "bool Update_Emulators_List()",
633 "Default QEMU emulator already loaded." );
634 tmp.Set_Default( false );
635 }
636 else qDef = true;
637 }
638
639 // Update available options?
640 if( tmp.Get_Check_Available_Options() )
641 {
642 QMap<QString, QString> tmpBinFiles = tmp.Get_Binary_Files();
643 QMap<QString, Available_Devices> tmpDevMap; // result
644
645 for( QMap<QString, QString>::const_iterator it = tmpBinFiles.constBegin(); it != tmpBinFiles.constEnd(); ++it )
646 {
647 if( ! it.value().isEmpty() )
648 {
649 bool ok = false;
650 Available_Devices tmpDev = System_Info::Get_Emulator_Info( it.value(), &ok, tmp.Get_Version(), it.key() );
651
652 if( ! ok )
653 {
654 AQError( "bool Update_Emulators_List()",
655 "Cannot set new emulator available options!" );
656 continue;
657 }
658
659 // Adding device
660 tmpDevMap[ it.key() ] = tmpDev;
661 }
662 }
663
664 // Set all devices
665 tmp.Set_Devices( tmpDevMap );
666 }
667
668 // Check version?
669 if( tmp.Get_Check_Version() )
670 {
671 // Get bin file path
672 QString binFilePath = "";
673 QMap<QString, QString> tmpBinFiles = tmp.Get_Binary_Files();
674 for( QMap<QString, QString>::const_iterator it = tmpBinFiles.constBegin(); it != tmpBinFiles.constEnd(); ++it )
675 {
676 if( QFile::exists(it.value()) )
677 {
678 binFilePath = it.value();
679 break;
680 }
681 }
682
683 if( binFilePath.isEmpty() )
684 {
685 AQError( "bool Update_Emulators_List()",
686 QString("Cannot find exists emulator binary file for emulator \"%1\"!").arg(tmp.Get_Name()) );
687 }
688
689 // All OK, check version
690 tmp.Set_Version( System_Info::Get_Emulator_Version(binFilePath) );
691 }
692
693 // Adding emulator
694 Emulators_List << tmp;
695 }
696
697 // Emulator loaded?
698 if( Emulators_List.isEmpty() )
699 {
700 AQWarning( "bool Update_Emulators_List()",
701 "No emulators loaded!" );
702 return false;
703 }
704
705 // Check defaults
706 if( qDef == false )
707 {
708 for( int ex = 0; ex < Emulators_List.count(); ++ex )
709 {
710 Emulators_List[ex].Set_Default( true );
711 break;
712 }
713 }
714
715 // All OK
716 return true;
717 }
718
Get_Emulators_List()719 const QList<Emulator> &Get_Emulators_List()
720 {
721 if( Update_Emulators_List() ) return Emulators_List; // FIXME Update
722 else
723 {
724 AQError( "QList<Emulator> Get_Emulators_List()",
725 "Cannot Update Emulators List" );
726 return Empty_Emul_List;
727 }
728 }
729
Remove_All_Emulators_Files()730 bool Remove_All_Emulators_Files()
731 {
732 // Get emulators dir path
733 QSettings settings;
734 QFileInfo info( settings.fileName() );
735 QString aqemuSettingsFolder = info.absoluteDir().absolutePath();
736 aqemuSettingsFolder += aqemuSettingsFolder.endsWith( QDir::toNativeSeparators("/") )
737 ? ""
738 : QDir::toNativeSeparators( "/" );
739
740 if( ! QFile::exists(aqemuSettingsFolder) )
741 {
742 AQError( "bool Remove_All_Emulators_Files()",
743 QString("Cannot get path for save emulator! Folder \"%1\" not exists!").arg(aqemuSettingsFolder) );
744 return false;
745 }
746 else
747 {
748 // Get all *.emulators files
749 QDir emulDir( aqemuSettingsFolder );
750 QStringList emulFiles = emulDir.entryList( QStringList("*.emulator"), QDir::Files, QDir::Name );
751
752 bool allFilesRemoved = true;
753 for( int dx = 0; dx < emulFiles.count(); ++dx )
754 {
755 if( ! QFile::remove(aqemuSettingsFolder + emulFiles[dx]) )
756 {
757 AQError( "bool Remove_All_Emulators_Files()",
758 QString("Cannot delete file \"%1\"!").arg(emulFiles[dx]) );
759 allFilesRemoved = false;
760 }
761 }
762
763 return allFilesRemoved;
764 }
765 }
766
Get_Default_Emulator()767 const Emulator &Get_Default_Emulator()
768 {
769 if( Emulators_List.count() <= 0 )
770 AQError( "const Emulator &Get_Default_Emulator()",
771 "Emulator Count == 0" );
772 else
773 {
774 for( int ix = 0; ix < Emulators_List.count(); ix++ )
775 {
776 if( Emulators_List[ix].Get_Default() )
777 {
778 return Emulators_List[ ix ];
779 }
780 }
781 }
782
783 AQWarning( "const Emulator &Get_Default_Emulator()",
784 "Cannot Find!" );
785 return Empty_Emul;
786 }
787
Get_Emulator_By_Name(const QString & name)788 const Emulator &Get_Emulator_By_Name( const QString &name )
789 {
790 if( Emulators_List.count() <= 0 )
791 AQError( "const Emulator Get_Emulator_By_Name( const QString &name )",
792 "Emulator Count == 0" );
793 else
794 {
795 for( int ix = 0; ix < Emulators_List.count(); ix++ )
796 {
797 if( Emulators_List[ix].Get_Name() == name )
798 return Emulators_List[ ix ];
799 }
800 }
801
802 AQWarning( "const Emulator Get_Emulator_By_Name( const QString &name )",
803 "Cannot Find!" );
804 return Empty_Emul;
805 }
806
Get_Random(int min,int max)807 int Get_Random( int min, int max )
808 {
809 if( min < 0 || max > RAND_MAX || min > max )
810 {
811 return -1;
812 }
813
814 qsrand( QTime::currentTime().msec() );
815
816 return int( qrand() / (RAND_MAX + 1.0) * (max + 1 - min) + min );
817 }
818
Load_Recent_Images_List()819 void Load_Recent_Images_List()
820 {
821 QSettings settings;
822
823 // CD
824 int max_cd = settings.value( "CD_ROM_Existing_Images/Max", "5" ).toString().toInt();
825
826 Recent_CD_Images.clear();
827
828 for( int ix = 0; ix < max_cd; ++ix )
829 {
830 QString tmp = settings.value( "CD_ROM_Existing_Images/item" + QString::number(ix), "" ).toString();
831
832 if( ! tmp.isEmpty() ) Recent_CD_Images << tmp;
833 }
834
835 // FDD
836 int max_fdd = settings.value( "Floppy_Existing_Images/Max", "5" ).toString().toInt();
837
838 Recent_FDD_Images.clear();
839
840 for( int ix = 0; ix < max_fdd; ++ix )
841 {
842 QString tmp = settings.value( "Floppy_Existing_Images/item" + QString::number(ix), "" ).toString();
843
844 if( ! tmp.isEmpty() ) Recent_FDD_Images << tmp;
845 }
846 }
847
Get_CD_Recent_Images_List()848 const QStringList &Get_CD_Recent_Images_List()
849 {
850 return Recent_CD_Images;
851 }
852
Add_To_Recent_CD_Files(const QString & path)853 void Add_To_Recent_CD_Files( const QString &path )
854 {
855 QSettings settings;
856 int max = settings.value( "CD_ROM_Existing_Images/Max", "5" ).toString().toInt();
857
858 // This Unique Path?
859 for( int fx = 0; fx < Recent_CD_Images.count() && fx < max; ++fx )
860 {
861 if( Recent_CD_Images[fx] == path )
862 {
863 AQDebug( "void Add_To_Recent_CD_Files( const QString &path )",
864 "CD-ROM Path Not Unique." );
865
866 // Up it path in list
867 if( fx < Recent_CD_Images.count()-1 )
868 {
869 // swap items
870 QString tmp = Recent_CD_Images[ fx+1 ];
871 Recent_CD_Images[ fx+1 ] = Recent_CD_Images[ fx ];
872 Recent_CD_Images[ fx ] = tmp;
873 }
874 else return;
875 }
876 }
877
878 // Add to List
879 if( Recent_CD_Images.count() < max )
880 {
881 Recent_CD_Images << path;
882 settings.setValue( "CD_ROM_Existing_Images/item" + QString::number(Recent_CD_Images.count()-1), path );
883 }
884 else
885 {
886 // Delete first element and add new to end
887 for( int ix = 0; ix < Recent_CD_Images.count() -1 && ix < max -1; ++ix )
888 {
889 Recent_CD_Images[ ix ] = Recent_CD_Images[ ix +1 ];
890 }
891
892 Recent_CD_Images[ max -1 ] = path;
893
894 // Save Items
895 for( int ix = 0; ix < Recent_CD_Images.count(); ix++ )
896 {
897 settings.setValue( "CD_ROM_Existing_Images/item" + QString::number(ix), Recent_CD_Images[ix] );
898 }
899 }
900 }
901
Get_FDD_Recent_Images_List()902 const QStringList &Get_FDD_Recent_Images_List()
903 {
904 return Recent_FDD_Images;
905 }
906
Add_To_Recent_FDD_Files(const QString & path)907 void Add_To_Recent_FDD_Files( const QString &path )
908 {
909 QSettings settings;
910 int max = settings.value( "Floppy_Existing_Images/Max", "5" ).toString().toInt();
911
912 // This Unique Path?
913 for( int fx = 0; fx < Recent_FDD_Images.count() && fx < max; ++fx )
914 {
915 if( Recent_FDD_Images[fx] == path )
916 {
917 AQDebug( "void Add_To_Recent_FDD_Files( const QString &path )",
918 "Floppy Path Not Unique." );
919
920 // Up it path in list
921 if( fx < Recent_FDD_Images.count()-1 )
922 {
923 // swap items
924 QString tmp = Recent_FDD_Images[ fx+1 ];
925 Recent_FDD_Images[ fx+1 ] = Recent_FDD_Images[ fx ];
926 Recent_FDD_Images[ fx ] = tmp;
927 }
928 else return;
929 }
930 }
931
932 // Add to List
933 if( Recent_FDD_Images.count() < max )
934 {
935 Recent_FDD_Images << path;
936 settings.setValue( "Floppy_Existing_Images/item" + QString::number(Recent_FDD_Images.count()-1), path );
937 }
938 else
939 {
940 // Delete first element and add new to end
941 for( int ix = 0; ix < Recent_FDD_Images.count() -1 && ix < max -1; ++ix )
942 {
943 Recent_FDD_Images[ ix ] = Recent_FDD_Images[ ix +1 ];
944 }
945
946 Recent_FDD_Images[ max -1 ] = path;
947
948 // Save Items
949 for( int ix = 0; ix < Recent_FDD_Images.count(); ix++ )
950 {
951 settings.setValue( "Floppy_Existing_Images/item" + QString::number(ix), Recent_FDD_Images[ix] );
952 }
953 }
954 }
955
956 static bool Show_Error_Window;
957
Get_Show_Error_Window()958 bool Get_Show_Error_Window()
959 {
960 return Show_Error_Window;
961 }
962
Set_Show_Error_Window(bool show)963 void Set_Show_Error_Window( bool show )
964 {
965 Show_Error_Window = show;
966 }
967
968 #include <QCheckBox>
969
Checkbox_Dependend_Set_Enabled(QList<QWidget * > & children_to_enable,QCheckBox * checkbox,bool enabled)970 void Checkbox_Dependend_Set_Enabled(QList<QWidget*>& children_to_enable, QCheckBox* checkbox, bool enabled)
971 {
972 checkbox->setEnabled(enabled);
973
974 if ( ! checkbox->isChecked() )
975 enabled = false;
976
977 for( int i = 0; i < children_to_enable.count(); i++)
978 children_to_enable[i]->setEnabled(enabled);
979 }
980
981
982