1 #include <qglobal.h>
2 #include <QMessageBox>
3 #include <QCache>
4 #include <QHeaderView>
5 #include <QTextStream>
6 #include <QTextDocument>
7 #include <QScrollBar>
8 #include <QProcess>
9 #include <QTimer>
10 #include <QTime>
11 #include <QFile>
12 #include <QMap>
13 #include <QMultiMap>
14 #include <QHash>
15 #include <QCursor>
16 #include <QHashIterator>
17 #include <QStyleFactory>
18 #include <QBitArray>
19 #include <QFileInfo>
20 #include <QFileDialog>
21 #include <QAction>
22 #include <QPair>
23 #include <QClipboard>
24 #include <QDateTime>
25 #include <QMutex>
26 #include <QtWebKit>
27 #include <QNetworkAccessManager>
28 #include <QSplashScreen>
29 #include <QDir>
30 #include <QTest>
31 #include <QColorDialog>
32 #include <QChar>
33 #if QT_VERSION >= 0x050000
34 #include <QInputDialog>
35 #include <QDesktopWidget>
36 #include <QtWebKitWidgets/QWebFrame>
37 #endif
38 
39 #include <algorithm> // std::sort()
40 
41 #include "macros.h"
42 #include "qmc2main.h"
43 #include "options.h"
44 #include "emuopt.h"
45 #include "processmanager.h"
46 #include "machinelist.h"
47 #include "preview.h"
48 #include "flyer.h"
49 #include "cabinet.h"
50 #include "controller.h"
51 #include "marquee.h"
52 #include "title.h"
53 #include "pcb.h"
54 #include "docbrowser.h"
55 #include "about.h"
56 #include "welcome.h"
57 #include "imagechecker.h"
58 #include "samplechecker.h"
59 #include "romalyzer.h"
60 #include "romstatusexport.h"
61 #include "componentsetup.h"
62 #include "miniwebbrowser.h"
63 #include "unzip.h"
64 #include "sevenzipfile.h"
65 #include "downloaditem.h"
66 #include "embedder.h"
67 #include "demomode.h"
68 #include "softwarelist.h"
69 #include "softwaresnapshot.h"
70 #include "toolbarcustomizer.h"
71 #include "paletteeditor.h"
72 #include "brusheditor.h"
73 #include "iconlineedit.h"
74 #include "cookiejar.h"
75 #include "networkaccessmanager.h"
76 #if QMC2_JOYSTICK == 1
77 #include "joystick.h"
78 #endif
79 #include "deviceconfigurator.h"
80 #if QMC2_USE_PHONON_API
81 #include "audioeffects.h"
82 #endif
83 #if QMC2_MULTIMEDIA_ENABLED
84 #include <QMediaMetaData>
85 #endif
86 #include "toolexec.h"
87 #if defined(QMC2_OS_UNIX)
88 #include "keyseqscan.h"
89 #include "x11_tools.h"
90 #endif
91 #if defined(QMC2_YOUTUBE_ENABLED)
92 #include "youtubevideoplayer.h"
93 #endif
94 #if defined(QMC2_OS_WIN)
95 #include "windows_tools.h"
96 #endif
97 #include "htmleditor/htmleditor.h"
98 #include "arcademodesetup.h"
99 #include "fileiconprovider.h"
100 #include "aspectratiolabel.h"
101 #if defined(QMC2_LIBARCHIVE_ENABLED)
102 #include "archivefile.h"
103 #endif
104 #include "itemselect.h"
105 
106 #if defined(QMC2_OS_MAC)
107 #include <ApplicationServices/ApplicationServices.h>
108 #if defined(verify) // verify() is #defined in AssertMacros.h on OS X
109 #undef verify
110 #endif
111 #include <mach-o/dyld.h>
112 #endif
113 
114 // global variables
115 MainWindow *qmc2MainWindow = 0;
116 MachineList *qmc2MachineList = 0;
117 Options *qmc2Options = 0;
118 Settings *qmc2Config = 0;
119 EmulatorOptions *qmc2GlobalEmulatorOptions = 0;
120 EmulatorOptions *qmc2EmulatorOptions = 0;
121 ProcessManager *qmc2ProcessManager = 0;
122 Preview *qmc2Preview = 0;
123 Flyer *qmc2Flyer = 0;
124 Cabinet *qmc2Cabinet = 0;
125 Controller *qmc2Controller = 0;
126 Marquee *qmc2Marquee = 0;
127 Title *qmc2Title = 0;
128 PCB *qmc2PCB = 0;
129 About *qmc2About = 0;
130 DocBrowser *qmc2DocBrowser = 0;
131 Welcome *qmc2Welcome = 0;
132 ImageChecker *qmc2ImageChecker = 0;
133 SampleChecker *qmc2SampleChecker = 0;
134 ROMAlyzer *qmc2SystemROMAlyzer = 0;
135 ROMAlyzer *qmc2SoftwareROMAlyzer = 0;
136 ROMStatusExporter *qmc2ROMStatusExporter = 0;
137 ComponentSetup *qmc2ComponentSetup = 0;
138 ToolBarCustomizer *qmc2ToolBarCustomizer = 0;
139 PaletteEditor *qmc2PaletteEditor = 0;
140 SoftwareList *qmc2SoftwareList = 0;
141 SoftwareSnap *qmc2SoftwareSnap = 0;
142 SoftwareSnapshot *qmc2SoftwareSnapshot = 0;
143 QString qmc2DriverName;
144 DeviceConfigurator *qmc2DeviceConfigurator = 0;
145 QTreeWidgetItem *qmc2LastDeviceConfigItem = 0;
146 QTreeWidgetItem *qmc2LastSoftwareListItem = 0;
147 #if QMC2_USE_PHONON_API
148 AudioEffectDialog *qmc2AudioEffectDialog = 0;
149 #endif
150 #if QMC2_USE_PHONON_API || QMC2_MULTIMEDIA_ENABLED
151 QString qmc2AudioLastIndividualTrack;
152 #endif
153 DemoModeDialog *qmc2DemoModeDialog = 0;
154 bool qmc2ReloadActive = false;
155 bool qmc2ImageCheckActive = false;
156 bool qmc2SampleCheckActive = false;
157 bool qmc2EarlyReloadActive = false;
158 bool qmc2VerifyActive = false;
159 bool qmc2VerifyTaggedActive = false;
160 bool qmc2FilterActive = false;
161 bool qmc2GuiReady = false;
162 bool qmc2CleaningUp = false;
163 bool qmc2StartingUp = true;
164 bool qmc2EarlyStartup = true;
165 bool qmc2ScaledPreview = true;
166 bool qmc2ScaledFlyer = true;
167 bool qmc2ScaledCabinet = true;
168 bool qmc2ScaledController = true;
169 bool qmc2ScaledMarquee = true;
170 bool qmc2ScaledTitle = true;
171 bool qmc2ScaledPCB = true;
172 bool qmc2ScaledSoftwareSnapshot = true;
173 bool qmc2SmoothScaling = false;
174 bool qmc2RetryLoadingImages = true;
175 bool qmc2ParentImageFallback = false;
176 bool qmc2UsePreviewFile = false;
177 bool qmc2UseFlyerFile = false;
178 bool qmc2UseCabinetFile = false;
179 bool qmc2UseControllerFile = false;
180 bool qmc2UseIconFile = false;
181 bool qmc2UseMarqueeFile = false;
182 bool qmc2UseTitleFile = false;
183 bool qmc2UsePCBFile = false;
184 bool qmc2UseSoftwareSnapFile = false;
185 bool qmc2IconsPreloaded = false;
186 bool qmc2CheckItemVisibility = true;
187 bool qmc2AutomaticReload = false;
188 bool qmc2LoadingMachineInfoDB = false;
189 bool qmc2WidgetsEnabled = true;
190 bool qmc2ExportingROMStatus = false;
191 bool qmc2StatesTogglesEnabled = true;
192 bool qmc2DestroyingArcadeView = false;
193 bool qmc2IgnoreItemActivation = false;
194 bool qmc2StartEmbedded = false;
195 bool qmc2SuppressQtMessages = false;
196 bool qmc2CriticalSection = false;
197 bool qmc2UseDefaultEmulator = true;
198 bool qmc2ForceCacheRefresh = false;
199 bool qmc2ReconfigureRestartRequested = false;
200 int qmc2MachineListResponsiveness = 100;
201 int qmc2UpdateDelay = 10;
202 QFile *qmc2FrontendLogFile = 0;
203 QFile *qmc2EmulatorLogFile = 0;
204 QTextStream qmc2FrontendLogStream;
205 QTextStream qmc2EmulatorLogStream;
206 QTranslator *qmc2Translator = 0;
207 QTranslator *qmc2QtTranslator = 0;
208 QString qmc2LastFrontendLogMessage;
209 quint64 qmc2FrontendLogMessageRepeatCount = 0;
210 QString qmc2LastEmulatorLogMessage;
211 quint64 qmc2EmulatorLogMessageRepeatCount = 0;
212 bool qmc2LoadingInterrupted = false;
213 QTreeWidgetItem *qmc2CurrentItem = 0;
214 QTreeWidgetItem *qmc2LastConfigItem = 0;
215 QTreeWidgetItem *qmc2LastMachineInfoItem = 0;
216 bool qmc2LoadingEmuInfoDB = false;
217 QTreeWidgetItem *qmc2LastEmuInfoItem = 0;
218 bool qmc2LoadingSoftwareInfoDB = false;
219 QTreeWidgetItem *qmc2LastSoftwareInfoItem = 0;
220 MiniWebBrowser *qmc2ProjectMESSLookup = 0;
221 QTreeWidgetItem *qmc2LastProjectMESSItem = 0;
222 QCache<QString, QByteArray> qmc2ProjectMESSCache;
223 QHash<QString, QTreeWidgetItem *> qmc2CategoryItemHash;
224 QTreeWidgetItem *qmc2CategoryViewSelectedItem = 0;
225 QHash<QString, QTreeWidgetItem *> qmc2VersionItemHash;
226 QTreeWidgetItem *qmc2VersionViewSelectedItem = 0;
227 MiniWebBrowser *qmc2ProjectMESS = 0;
228 QTreeWidgetItem *qmc2LastSoftwareNotesItem = 0;
229 QTreeWidgetItem *qmc2LastSystemNotesItem = 0;
230 HtmlEditor *qmc2SystemNotesEditor = 0;
231 HtmlEditor *qmc2SoftwareNotesEditor = 0;
232 #if defined(QMC2_YOUTUBE_ENABLED)
233 YouTubeVideoPlayer *qmc2YouTubeWidget = 0;
234 QTreeWidgetItem *qmc2LastYouTubeItem = 0;
235 QHash<QString, YouTubeVideoInfo> qmc2YouTubeVideoInfoHash;
236 bool qmc2YouTubeVideoInfoHashChanged = false;
237 #endif
238 QTreeWidgetItem *qmc2HierarchySelectedItem = 0;
239 QMenu *qmc2EmulatorMenu = 0,
240       *qmc2MachineMenu = 0,
241       *qmc2FavoritesMenu = 0,
242       *qmc2PlayedMenu = 0,
243       *qmc2SearchMenu = 0,
244       *qmc2ForeignIDsMenu = 0;
245 QHash<QString, QTreeWidgetItem *> qmc2MachineListItemHash;
246 QHash<QString, QTreeWidgetItem *> qmc2HierarchyItemHash;
247 QHash<QString, QString> qmc2ParentHash;
248 QHash<QString, QIcon> qmc2IconHash;
249 QHash<QString, QPair<QString, QAction *> > qmc2ShortcutHash;
250 QHash<QString, QString> qmc2CustomShortcutHash;
251 QList<QWidget *> qmc2ActiveViews;
252 QString qmc2DemoMachine;
253 QStringList qmc2DemoArgs;
254 int qmc2SortCriteria = QMC2_SORT_BY_DESCRIPTION;
255 Qt::SortOrder qmc2SortOrder = Qt::AscendingOrder;
256 bool qmc2SortingActive = false;
257 QBitArray qmc2Filter;
258 QMap<QString, unzFile> qmc2IconFileMap;
259 QMap<QString, SevenZipFile *> qmc2IconFileMap7z;
260 #if defined(QMC2_LIBARCHIVE_ENABLED)
261 QMap<QString, ArchiveFile *> qmc2IconArchiveMap;
262 #endif
263 MainEventFilter *qmc2MainEventFilter = 0;
264 QHash<QString, QKeySequence> qmc2QtKeyHash;
265 #if QMC2_JOYSTICK == 1
266 QHash<QString, QString> qmc2JoystickFunctionHash;
267 bool qmc2JoystickIsCalibrating = false;
268 #endif
269 bool qmc2ShowMachineName = false;
270 bool qmc2ShowMachineNameOnlyWhenRequired = true;
271 QMutex qmc2LogFrontendMutex;
272 QMutex qmc2LogEmulatorMutex;
273 QString qmc2FileEditStartPath;
274 QString qmc2DirectoryEditStartPath;
275 NetworkAccessManager *qmc2NetworkAccessManager = 0;
276 int qmc2LastListIndex = 0;
277 QAbstractItemView::ScrollHint qmc2CursorPositioningMode = QAbstractItemView::PositionAtTop;
278 QFont *qmc2StartupDefaultFont = 0;
279 int qmc2SoftwareSnapPosition = 0;
280 QSplashScreen *qmc2SplashScreen = 0;
281 int qmc2DefaultLaunchMode = QMC2_LAUNCH_MODE_INDEPENDENT;
282 QCache<QString, ImagePixmap> qmc2ImagePixmapCache;
283 QList<QTreeWidgetItem *> qmc2ExpandedMachineListItems;
284 QPalette qmc2CustomPalette;
285 QMap<QString, QPalette> qmc2StandardPalettes;
286 bool qmc2CategoryInfoUsed = false;
287 bool qmc2VersionInfoUsed = false;
288 bool qmc2TemplateCheck = false;
289 QMap<QWidget *, Qt::WindowStates> qmc2AutoMinimizedWidgets;
290 QTime qmc2StartupTimer;
291 
292 // game status colors
293 QColor MainWindow::qmc2StatusColorGreen = QColor("#00cc00");
294 QColor MainWindow::qmc2StatusColorYellowGreen = QColor("#799632");
295 QColor MainWindow::qmc2StatusColorRed = QColor("#f90000");
296 QColor MainWindow::qmc2StatusColorBlue = QColor("#0000f9");
297 QColor MainWindow::qmc2StatusColorGrey = QColor("#7f7f7f");
298 QList<MachineListViewer *> MainWindow::machineListViewers;
299 
300 // extern global variables
301 extern QHash<QString, QStringList> systemSoftwareListHash;
302 extern QHash<QString, QStringList> systemSoftwareFilterHash;
303 #if defined(QMC2_OS_WIN)
304 extern QMap<HWND, QString> winWindowMap;
305 #endif
306 extern QHash<QString, QString> softwareParentHash;
307 
308 #define userDataDb	qmc2MachineList->userDataDb()
309 
MainWindow(QWidget * parent)310 MainWindow::MainWindow(QWidget *parent) :
311 	QMainWindow(parent, qmc2TemplateCheck ? Qt::Tool | Qt::FramelessWindowHint : (Qt::WindowFlags)0),
312 #if QMC2_USE_PHONON_API
313 	phononAudioPlayer(0),
314 	phononAudioOutput(0),
315 #endif
316 	m_ignoreSelectionChange(false),
317 	m_ignoreDetailTabChange(false),
318 #if defined(QMC2_YOUTUBE_ENABLED)
319 	m_videoInfoMapLoaded(false),
320 #endif
321 	m_focusSearchResults(false),
322 	m_lastMlvSender(0),
323 	m_attachedViewer(0),
324 	m_searchBoxKeyEventFilter(0)
325 {
326 	setUpdatesEnabled(false);
327 	setVisible(false);
328 
329 	qmc2Config->setValue(QString(QMC2_FRONTEND_PREFIX + "InstanceRunning"), true);
330 	qmc2StartupDefaultFont = new QFont(qApp->font());
331 	desktopGeometry = qApp->desktop()->geometry();
332 	isActiveState = launchForeignID = negatedMatch = isCreatingSoftList = searchActive = stopSearch = lastPageSoftware = false;
333 	comboBoxEmuSelector = 0;
334 	proxyStyle = 0;
335 	swlDb = 0;
336 	videoSnapAllowedFormatExtensions << ".mp4" << ".avi";
337 	FileIconProvider::setCacheSize(QMC2_FILEICONPROVIDER_CACHE_SIZE);
338 
339 	// remember the default style
340 	defaultStyle = QApplication::style()->objectName();
341 
342 	// connections for style/style-sheet/palette setup requests
343 	connect(this, SIGNAL(styleSetupRequested(QString)), this, SLOT(setupStyle(QString)));
344 	connect(this, SIGNAL(styleSheetSetupRequested(QString)), this, SLOT(setupStyleSheet(QString)));
345 	connect(this, SIGNAL(paletteSetupRequested(QString)), this, SLOT(setupPalette(QString)));
346 
347 	setupUi(this);
348 
349 #if !defined(QMC2_WIP_ENABLED)
350 	actionNewFilteredView->setVisible(false);
351 #endif
352 
353 	criticalActions << actionRebuildROM << actionRebuildROMTagged;
354 	rebuildRomActions << actionRebuildROM << actionRebuildROMTagged;
355 
356 	// palette-editor related
357 	PaletteEditor::colorNames << "Window" << "WindowText" << "Base" << "AlternateBase" << "Text" << "BrightText" << "Button"
358 		<< "ButtonText" << "ToolTipBase" << "ToolTipText" << "Light" << "Midlight" << "Dark" << "Mid"
359 		<< "Shadow" << "Highlight" << "HighlightedText" << "Link" << "LinkVisited";
360 	BrushEditor::patternNames << "NoBrush" << "SolidPattern" << "Dense1Pattern" << "Dense2Pattern" << "Dense3Pattern" << "Dense4Pattern"
361 		<< "Dense5Pattern" << "Dense6Pattern" << "Dense7Pattern" << "HorPattern" << "VerPattern" << "CrossPattern"
362 		<< "BDiagPattern" << "FDiagPattern" << "DiagCrossPattern";
363 	BrushEditor::gradientTypeNames << "Linear" << "Radial" << "Conical";
364 	BrushEditor::gradientSpreadNames << "PadSpread" << "RepeatSpread" << "ReflectSpread";
365 
366 	progressBarSearch->setVisible(false);
367 	progressBarSearch->setFormat(tr("Searching machines - %p%"));
368 
369 	qmc2ActiveViews << treeWidgetMachineList << treeWidgetHierarchy << treeWidgetCategoryView << treeWidgetVersionView;
370 
371 #if defined(QMC2_OS_MAC)
372 	// we cannot use a native menu-bar on Mac OS X since we have multiple and this conflicts with it
373 	menuBar()->setNativeMenuBar(false);
374 #endif
375 
376 	// enable menu tear-off
377 	foreach (QMenu *menu, menuBar()->findChildren<QMenu *>())
378 		menu->setTearOffEnabled(true);
379 
380 	// toolbar's search combo-box
381 	comboBoxToolbarSearch = new QComboBox(this);
382 	comboBoxToolbarSearch->setLineEdit(new IconLineEdit(QIcon(QString::fromUtf8(":/data/img/find.png")), QMC2_ALIGN_LEFT, comboBoxToolbarSearch));
383 	comboBoxToolbarSearch->setEditable(true);
384 	comboBoxToolbarSearch->setInsertPolicy(QComboBox::InsertAtTop);
385 	comboBoxToolbarSearch->lineEdit()->setPlaceholderText(tr("Enter search string"));
386 	comboBoxToolbarSearch->setToolTip(tr("Search for machines (not case-sensitive)"));
387 	comboBoxToolbarSearch->setStatusTip(tr("Search for machines"));
388 	comboBoxToolbarSearch->setToolTip(comboBoxToolbarSearch->toolTip() + " - " + tr("note: the special characters $, (, ), *, +, ., ?, [, ], ^, {, |, } and \\ must be escaped when they are meant literally!"));
389 	comboBoxToolbarSearch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
390 	comboBoxToolbarSearch->installEventFilter(m_searchBoxKeyEventFilter);
391 	widgetActionToolbarSearch = new QWidgetAction(this);
392 	widgetActionToolbarSearch->setDefaultWidget(comboBoxToolbarSearch);
393 	widgetActionToolbarSearch->setObjectName("WATS");
394 	toolbar->addSeparator();
395 	toolbar->addAction(widgetActionToolbarSearch);
396 	connect(comboBoxToolbarSearch, SIGNAL(activated(const QString &)), this, SLOT(comboBoxToolbarSearch_activated(const QString &)));
397 	connect(comboBoxToolbarSearch, SIGNAL(editTextChanged(const QString &)), this, SLOT(comboBoxToolbarSearch_editTextChanged(const QString &)));
398 
399 	// save splitter widgets at index 0 for later comparison
400 	hSplitterWidget0 = hSplitter->widget(0);
401 	vSplitterWidget0 = vSplitter->widget(0);
402 
403 	// disable the menu-bar's default context menu (may be irritating)
404 	menuBar()->setContextMenuPolicy(Qt::PreventContextMenu);
405 
406 	// loading animation
407 	loadAnimMovie = new QMovie(QString::fromUtf8(":/data/img/loadanim.gif"), QByteArray(), this);
408 	loadAnimMovie->setCacheMode(QMovie::CacheAll);
409 	loadAnimMovie->setSpeed(QMC2_LOADANIM_SPEED);
410 	loadAnimMovie->stop();
411 	nullMovie = new QMovie();
412 
413 	// replace loading animation labels with aspect-ratio keeping ones
414 	gridLayoutMachineListPage->removeWidget(labelLoadingMachineList);
415 	delete labelLoadingMachineList;
416 	labelLoadingMachineList = new AspectRatioLabel(this);
417 	labelLoadingMachineList->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
418 	labelLoadingMachineList->setMovie(loadAnimMovie);
419 	gridLayoutMachineListPage->addWidget(labelLoadingMachineList, 1, 0);
420 	labelLoadingMachineList->setVisible(false);
421 
422 	gridLayoutHierarchyPage->removeWidget(labelLoadingHierarchy);
423 	delete labelLoadingHierarchy;
424 	labelLoadingHierarchy = new AspectRatioLabel(this);
425 	labelLoadingHierarchy->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
426 	labelLoadingHierarchy->setMovie(loadAnimMovie);
427 	gridLayoutHierarchyPage->addWidget(labelLoadingHierarchy, 1, 0);
428 	labelLoadingHierarchy->setVisible(false);
429 
430 	gridLayoutCategoryPage->removeWidget(labelCreatingCategoryView);
431 	delete labelCreatingCategoryView;
432 	labelCreatingCategoryView = new AspectRatioLabel(this);
433 	labelCreatingCategoryView->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
434 	labelCreatingCategoryView->setMovie(loadAnimMovie);
435 	gridLayoutCategoryPage->addWidget(labelCreatingCategoryView, 1, 0);
436 	labelCreatingCategoryView->setVisible(false);
437 
438 	gridLayoutVersionPage->removeWidget(labelCreatingVersionView);
439 	delete labelCreatingVersionView;
440 	labelCreatingVersionView = new AspectRatioLabel(this);
441 	labelCreatingVersionView->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
442 	labelCreatingVersionView->setMovie(loadAnimMovie);
443 	gridLayoutVersionPage->addWidget(labelCreatingVersionView, 1, 0);
444 	labelCreatingVersionView->setVisible(false);
445 
446 	gridLayoutAttachedViewsPage->removeWidget(labelLoadingAttachedViews);
447 	delete labelLoadingAttachedViews;
448 	labelLoadingAttachedViews = new AspectRatioLabel(this);
449 	labelLoadingAttachedViews->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
450 	labelLoadingAttachedViews->setMovie(loadAnimMovie);
451 	gridLayoutAttachedViewsPage->addWidget(labelLoadingAttachedViews, 1, 0);
452 	labelLoadingAttachedViews->setVisible(false);
453 
454 	checkBoxAudioFade->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
455 
456 	treeWidgetMachineList->setMouseTracking(true);
457 	treeWidgetHierarchy->setMouseTracking(true);
458 	treeWidgetCategoryView->setMouseTracking(true);
459 	treeWidgetVersionView->setMouseTracking(true);
460 
461 	labelMachineStatus->setVisible(false);
462 	labelMachineStatus->setPalette(qmc2StatusColorBlue);
463 
464 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
465 	embedderCornerWidget = new QWidget(tabWidgetEmbeddedEmulators);
466 	embedderCornerLayout = new QHBoxLayout(embedderCornerWidget);
467 	embedderCornerLayout->setContentsMargins(0, 0, 0, 0);
468 
469 #if defined(QMC2_OS_UNIX)
470 	toolButtonEmbedderAutoPause = new QToolButton(embedderCornerWidget);
471 	toolButtonEmbedderAutoPause->setIcon(QIcon(QString::fromUtf8(":/data/img/sleep.png")));
472 	toolButtonEmbedderAutoPause->setToolTip(tr("Toggle automatic pausing of embedded emulators (hold down for menu)"));
473 	toolButtonEmbedderAutoPause->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
474 	toolButtonEmbedderAutoPause->setToolButtonStyle(Qt::ToolButtonIconOnly);
475 	toolButtonEmbedderAutoPause->setAutoRaise(true);
476 	toolButtonEmbedderAutoPause->setCheckable(true);
477 	toolButtonEmbedderAutoPause->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/Embedder/AutoPause", false).toBool());
478 	embedderCornerLayout->addWidget(toolButtonEmbedderAutoPause);
479 
480 	menuAutoPause = new QMenu(0);
481 	QString apMenuString = tr("Scan the pause key used by the emulator");
482 	QAction *apMenuAction = menuAutoPause->addAction(tr("Scan pause key..."));
483 	apMenuAction->setIcon(QIcon(QString::fromUtf8(":/data/img/keyboard.png")));
484 	apMenuAction->setToolTip(apMenuString); apMenuAction->setStatusTip(apMenuString);
485 	connect(apMenuAction, SIGNAL(triggered()), this, SLOT(action_embedderScanPauseKey_triggered()));
486 	toolButtonEmbedderAutoPause->setMenu(menuAutoPause);
487 #endif
488 
489 	toolButtonEmbedderMaximizeToggle = new QToolButton(embedderCornerWidget);
490 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/Embedder/Maximize", false).toBool() )
491 		toolButtonEmbedderMaximizeToggle->setIcon(QIcon(QString::fromUtf8(":/data/img/minimize.png")));
492 	else
493 		toolButtonEmbedderMaximizeToggle->setIcon(QIcon(QString::fromUtf8(":/data/img/maximize.png")));
494 	toolButtonEmbedderMaximizeToggle->setToolTip(tr("Toggle maximization of embedded emulator windows"));
495 	toolButtonEmbedderMaximizeToggle->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
496 	toolButtonEmbedderMaximizeToggle->setToolButtonStyle(Qt::ToolButtonIconOnly);
497 	toolButtonEmbedderMaximizeToggle->setAutoRaise(true);
498 	toolButtonEmbedderMaximizeToggle->setCheckable(true);
499 	toolButtonEmbedderMaximizeToggle->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/Embedder/Maximize", false).toBool());
500 	connect(toolButtonEmbedderMaximizeToggle, SIGNAL(toggled(bool)), this, SLOT(toolButtonEmbedderMaximizeToggle_toggled(bool)));
501 	embedderCornerLayout->addWidget(toolButtonEmbedderMaximizeToggle);
502 
503 	embedderCornerWidget->setLayout(embedderCornerLayout);
504 	tabWidgetEmbeddedEmulators->setCornerWidget(embedderCornerWidget, Qt::TopRightCorner);
505 
506 	widgetEmbeddedEmus = tabWidgetMachineList->widget(tabWidgetMachineList->indexOf(tabEmbeddedEmus));
507 #else
508 	actionPlayEmbedded->setVisible(false);
509 	actionPlayEmbeddedTagged->setVisible(false);
510 #endif
511 	tabWidgetEmbeddedEmulators->removeTab(0);
512 	tabWidgetMachineList->removeTab(tabWidgetMachineList->indexOf(tabEmbeddedEmus));
513 
514 #if !defined(QMC2_YOUTUBE_ENABLED)
515 	actionClearYouTubeCache->setVisible(false);
516 #endif
517 #if QMC2_MULTIMEDIA_ENABLED
518 	toolButtonAudioSetupEffects->setVisible(false);
519 #endif
520 #if QT_VERSION < 0x050000
521 	lcdNumberSearchResults->setNumDigits(5);
522 #else
523 	lcdNumberSearchResults->setDigitCount(5);
524 #endif
525 
526 	qmc2ProjectMESSCache.setMaxCost(QMC2_PROJECTMESS_CACHE_SIZE);
527 	messDevCfgTimer.setSingleShot(true);
528 
529 	floatToggleButtonSoftwareDetail = new QToolButton(tabWidgetSoftwareDetail);
530 	floatToggleButtonSoftwareDetail->setCheckable(true);
531 	floatToggleButtonSoftwareDetail->setChecked(true);
532 	floatToggleButtonSoftwareDetail->setToolTip(tr("Dock / undock this widget"));
533 	floatToggleButtonSoftwareDetail->setIcon(QIcon(QString::fromUtf8(":/data/img/dock.png")));
534 	tabWidgetSoftwareDetail->setCornerWidget(floatToggleButtonSoftwareDetail, Qt::TopRightCorner);
535 
536 	comboBoxSearch->setToolTip(comboBoxSearch->toolTip() + " - " + tr("note: the special characters $, (, ), *, +, ., ?, [, ], ^, {, |, } and \\ must be escaped when they are meant literally!"));
537 	setWindowTitle(windowTitle() + " [Qt " + qVersion() + "]");
538 
539 	// tabs are movable
540 	QTabBar *tabBar;
541 	tabWidgetMachineList->setMovable(true);
542 	tabBar = tabWidgetMachineList->findChild<QTabBar *>();
543 	if ( tabBar )
544 		connect(tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabWidgetMachineList_tabMoved(int, int)));
545 	tabWidgetMachineDetail->setMovable(true);
546 	tabBar = tabWidgetMachineDetail->findChild<QTabBar *>();
547 	if ( tabBar )
548 		connect(tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabWidgetMachineDetail_tabMoved(int, int)));
549 	tabWidgetLogsAndEmulators->setMovable(true);
550 	tabBar = tabWidgetLogsAndEmulators->findChild<QTabBar *>();
551 	if ( tabBar )
552 		connect(tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabWidgetLogsAndEmulators_tabMoved(int, int)));
553 	tabWidgetSoftwareDetail->setMovable(true);
554 	tabBar = tabWidgetSoftwareDetail->findChild<QTabBar *>();
555 	if ( tabBar )
556 		connect(tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabWidgetSoftwareDetail_tabMoved(int, int)));
557 
558 	qmc2Options->checkBoxShowMachineName->setText(tr("Show machine/software titles"));
559 	qmc2Options->checkBoxShowMachineName->setToolTip(tr("Show machine- or software-titles at the bottom of all images"));
560 	qmc2Options->checkBoxShowMachineNameOnlyWhenRequired->setToolTip(tr("Show machine- or software-titles only when the machine list is not visible due to the current layout"));
561 
562 	qmc2MachineList = new MachineList(this);
563 	labelMachineListStatus->setText(qmc2MachineList->status());
564 	connect(qmc2MachineList->iconCacheDb(), SIGNAL(log(const QString &)), this, SLOT(logFE(const QString &)));
565 
566 	statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar").toBool());
567 
568 	// machine image widgets
569 	QHBoxLayout *previewLayout = new QHBoxLayout,
570 		    *flyerLayout = new QHBoxLayout,
571 		    *cabinetLayout = new QHBoxLayout,
572 		    *controllerLayout = new QHBoxLayout,
573 		    *marqueeLayout = new QHBoxLayout,
574 		    *titleLayout = new QHBoxLayout,
575 		    *pcbLayout = new QHBoxLayout;
576 
577 	qmc2Preview = new Preview(tabPreview);
578 	previewLayout->addWidget(qmc2Preview);
579 	previewLayout->setContentsMargins(0, 0, 0, 0);
580 	tabPreview->setLayout(previewLayout);
581 	qmc2Flyer = new Flyer(tabFlyer);
582 	flyerLayout->addWidget(qmc2Flyer);
583 	flyerLayout->setContentsMargins(0, 0, 0, 0);
584 	tabFlyer->setLayout(flyerLayout);
585 	qmc2Cabinet = new Cabinet(tabCabinet);
586 	cabinetLayout->addWidget(qmc2Cabinet);
587 	cabinetLayout->setContentsMargins(0, 0, 0, 0);
588 	tabCabinet->setLayout(cabinetLayout);
589 	qmc2Controller = new Controller(tabController);
590 	controllerLayout->addWidget(qmc2Controller);
591 	controllerLayout->setContentsMargins(0, 0, 0, 0);
592 	tabController->setLayout(controllerLayout);
593 	qmc2Marquee = new Marquee(tabMarquee);
594 	marqueeLayout->addWidget(qmc2Marquee);
595 	marqueeLayout->setContentsMargins(0, 0, 0, 0);
596 	tabMarquee->setLayout(marqueeLayout);
597 	qmc2Title = new Title(tabTitle);
598 	titleLayout->addWidget(qmc2Title);
599 	titleLayout->setContentsMargins(0, 0, 0, 0);
600 	tabTitle->setLayout(titleLayout);
601 	qmc2PCB = new PCB(tabPCB);
602 	pcbLayout->addWidget(qmc2PCB);
603 	pcbLayout->setContentsMargins(0, 0, 0, 0);
604 	tabPCB->setLayout(pcbLayout);
605 
606 	// remove column-width restrictions
607 	treeWidgetMachineList->header()->setMinimumSectionSize(0);
608 	treeWidgetHierarchy->header()->setMinimumSectionSize(0);
609 	treeWidgetCategoryView->header()->setMinimumSectionSize(0);
610 	treeWidgetVersionView->header()->setMinimumSectionSize(0);
611 
612 	// restore layout
613 	if ( !qmc2TemplateCheck ) {
614 		menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
615 		QSize hSplitterSize = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/hSplitter").toSize();
616 		QSize vSplitterSize = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/vSplitter").toSize();
617 		QSize vSplitterSizeSoftwareDetail = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/vSplitterSoftwareDetail").toSize();
618 		if ( hSplitterSize.width() > 0 || hSplitterSize.height() > 0 )
619 			hSplitterSizes << hSplitterSize.width() << hSplitterSize.height();
620 		else
621 			hSplitterSizes << 100 << 100;
622 		if ( vSplitterSize.width() > 0 || vSplitterSize.height() > 0 )
623 			vSplitterSizes << vSplitterSize.width() << vSplitterSize.height();
624 		else
625 			vSplitterSizes << 100 << 100;
626 		if ( vSplitterSizeSoftwareDetail.width() > 0 || vSplitterSizeSoftwareDetail.height() > 0 )
627 			vSplitterSizesSoftwareDetail << vSplitterSizeSoftwareDetail.width() << vSplitterSizeSoftwareDetail.height();
628 		else
629 			vSplitterSizesSoftwareDetail << 100 << 100;
630 		hSplitter->setSizes(hSplitterSizes);
631 		vSplitter->setSizes(vSplitterSizes);
632 		treeWidgetHierarchy->header()->setDefaultAlignment(Qt::AlignLeft);
633 		treeWidgetMachineList->header()->restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListHeaderState").toByteArray());
634 		treeWidgetHierarchy->header()->restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/HierarchyHeaderState").toByteArray());
635 		treeWidgetCategoryView->header()->restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/CategoryViewHeaderState").toByteArray());
636 		treeWidgetCategoryView->setColumnHidden(QMC2_MACHINELIST_COLUMN_CATEGORY, true);
637 		treeWidgetVersionView->header()->restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/VersionViewHeaderState").toByteArray());
638 		treeWidgetVersionView->setColumnHidden(QMC2_MACHINELIST_COLUMN_VERSION, true);
639 		treeWidgetEmulators->header()->restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/EmulatorControlHeaderState").toByteArray());
640 		actionFullscreenToggle->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Fullscreen", false).toBool());
641 		tabWidgetMachineList->setTabPosition((QTabWidget::TabPosition)qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MachineList/TabPosition", QTabWidget::North).toInt());
642 		tabWidgetMachineDetail->setTabPosition((QTabWidget::TabPosition)qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MachineDetail/TabPosition", QTabWidget::North).toInt());
643 		tabWidgetLogsAndEmulators->setTabPosition((QTabWidget::TabPosition)qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/LogsAndEmulators/TabPosition", QTabWidget::North).toInt());
644 		tabWidgetSoftwareDetail->setTabPosition((QTabWidget::TabPosition)qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/SoftwareDetail/TabPosition", QTabWidget::North).toInt());
645 		floatToggleButtonSoftwareDetail->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailDocked", true).toBool());
646 	} else {
647 		QList<int> splitterSizes;
648 		splitterSizes << 100 << 100;
649 		hSplitter->setSizes(splitterSizes);
650 		vSplitter->setSizes(splitterSizes);
651 		hSplitterSizes = splitterSizes;
652 		vSplitterSizes = splitterSizes;
653 		vSplitterSizesSoftwareDetail = splitterSizes;
654 		floatToggleButtonSoftwareDetail->setChecked(true);
655 	}
656 
657 	on_actionFullscreenToggle_triggered();
658 	update_rebuildRomActions_visibility();
659 
660 	actionSearchInternalBrowser->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "WebSearch/InternalBrowser", false).toBool());
661 	on_actionSearchInternalBrowser_triggered(actionSearchInternalBrowser->isChecked());
662 	actionManualInternalViewer->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "PdfViewer/Internal", false).toBool());
663 	on_actionManualInternalViewer_triggered(actionManualInternalViewer->isChecked());
664 
665 	// context menus
666 	QAction *action;
667 	QString s;
668 
669 	qmc2EmulatorMenu = new QMenu(0);
670 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
671 	s = tr("Embed emulator widget");
672 	action = qmc2EmulatorMenu->addAction(tr("&Embed"));
673 	action->setToolTip(s); action->setStatusTip(s);
674 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
675 	connect(action, SIGNAL(triggered()), this, SLOT(action_embedEmulator_triggered()));
676 #endif
677 	s = tr("Copy emulator command line to clipboard");
678 	action = qmc2EmulatorMenu->addAction(tr("&Copy command"));
679 	action->setToolTip(s); action->setStatusTip(s);
680 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/editcopy.png")));
681 	connect(action, SIGNAL(triggered()), this, SLOT(action_copyEmulatorCommand_triggered()));
682 	qmc2EmulatorMenu->addSeparator();
683 	s = tr("Kill selected emulator(s) (sends KILL signal to emulator process(es))");
684 	action = qmc2EmulatorMenu->addAction(tr("&Kill"));
685 	action->setToolTip(s); action->setStatusTip(s);
686 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/kill.png")));
687 	connect(action, SIGNAL(triggered()), this, SLOT(action_killEmulator_triggered()));
688 
689 	qmc2ForeignIDsMenu = new QMenu(0);
690 	s = tr("Play selected machine");
691 	action = qmc2ForeignIDsMenu->addAction(tr("&Play"));
692 	contextMenuPlayActions.append(action);
693 	action->setToolTip(s); action->setStatusTip(s);
694 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/launch.png")));
695 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlay_triggered()));
696 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
697 	s = tr("Play selected machine (embedded)");
698 	action = qmc2ForeignIDsMenu->addAction(tr("Play &embedded"));
699 	contextMenuPlayActions.append(action);
700 	action->setToolTip(s); action->setStatusTip(s);
701 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
702 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlayEmbedded_triggered()));
703 #endif
704 
705 	qmc2MachineMenu = new QMenu(0);
706 	s = tr("Play selected machine");
707 	action = qmc2MachineMenu->addAction(tr("&Play"));
708 	contextMenuPlayActions.append(action);
709 	action->setToolTip(s); action->setStatusTip(s);
710 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/launch.png")));
711 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlay_triggered()));
712 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
713 	s = tr("Play selected machine (embedded)");
714 	action = qmc2MachineMenu->addAction(tr("Play &embedded"));
715 	contextMenuPlayActions.append(action);
716 	action->setToolTip(s); action->setStatusTip(s);
717 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
718 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlayEmbedded_triggered()));
719 #endif
720 	s = tr("Add current machine to favorites");
721 	action = qmc2MachineMenu->addAction(tr("To &favorites"));
722 	action->setToolTip(s); action->setStatusTip(s);
723 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/favorites.png")));
724 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionToFavorites_triggered()));
725 	qmc2MachineMenu->addSeparator();
726 	s = tr("Check current machine's ROM state");
727 	action = qmc2MachineMenu->addAction(tr("Check &ROM state"));
728 	action->setToolTip(s); action->setStatusTip(s);
729 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rom.png")));
730 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionCheckCurrentROM_triggered()));
731 	s = tr("Analyse current machine's ROM set with the ROMAlyzer");
732 	action = qmc2MachineMenu->addAction(tr("&Analyse ROM..."));
733 	criticalActions << action;
734 	action->setToolTip(s); action->setStatusTip(s);
735 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/romalyzer.png")));
736 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionAnalyseCurrentROM_triggered()));
737 	s = tr("Rebuild current machine's ROM set with the ROMAlyzer");
738 	action = qmc2MachineMenu->addAction(tr("&Rebuild ROM..."));
739 	criticalActions << action;
740 	rebuildRomActions << action;
741 	action->setToolTip(s); action->setStatusTip(s);
742 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rebuild.png")));
743 	connect(action, SIGNAL(triggered()), this, SLOT(actionRebuildRom_triggered()));
744 	qmc2MachineMenu->addSeparator();
745 	qmc2MachineMenu->addMenu(menuRank);
746 	qmc2MachineMenu->addMenu(menuSearchWeb);
747 	qmc2MachineMenu->addMenu(menuManual);
748 
749 	qmc2SearchMenu = new QMenu(0);
750 	s = tr("Play selected machine");
751 	action = qmc2SearchMenu->addAction(tr("&Play"));
752 	contextMenuPlayActions.append(action);
753 	action->setToolTip(s); action->setStatusTip(s);
754 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/launch.png")));
755 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlay_triggered()));
756 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
757 	s = tr("Play selected machine (embedded)");
758 	action = qmc2SearchMenu->addAction(tr("Play &embedded"));
759 	contextMenuPlayActions.append(action);
760 	action->setToolTip(s); action->setStatusTip(s);
761 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
762 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlayEmbedded_triggered()));
763 #endif
764 	s = tr("Add current machine to favorites");
765 	action = qmc2SearchMenu->addAction(tr("To &favorites"));
766 	action->setToolTip(s); action->setStatusTip(s);
767 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/favorites.png")));
768 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionToFavorites_triggered()));
769 	qmc2SearchMenu->addSeparator();
770 	s = tr("Check current machine's ROM state");
771 	action = qmc2SearchMenu->addAction(tr("Check &ROM state"));
772 	action->setToolTip(s); action->setStatusTip(s);
773 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rom.png")));
774 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionCheckCurrentROM_triggered()));
775 	s = tr("Analyse current machine's ROM set with the ROMAlyzer");
776 	action = qmc2SearchMenu->addAction(tr("&Analyse ROM..."));
777 	criticalActions << action;
778 	action->setToolTip(s); action->setStatusTip(s);
779 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/romalyzer.png")));
780 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionAnalyseCurrentROM_triggered()));
781 	s = tr("Rebuild current machine's ROM set with the ROMAlyzer");
782 	action = qmc2SearchMenu->addAction(tr("&Rebuild ROM..."));
783 	criticalActions << action;
784 	rebuildRomActions << action;
785 	action->setToolTip(s); action->setStatusTip(s);
786 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rebuild.png")));
787 	connect(action, SIGNAL(triggered()), this, SLOT(actionRebuildRom_triggered()));
788 
789 	qmc2SearchMenu->addSeparator();
790 	qmc2SearchMenu->addMenu(menuRank);
791 	qmc2SearchMenu->addMenu(menuSearchWeb);
792 	qmc2SearchMenu->addMenu(menuManual);
793 
794 	qmc2FavoritesMenu = new QMenu(0);
795 	s = tr("Play selected machine");
796 	action = qmc2FavoritesMenu->addAction(tr("&Play"));
797 	contextMenuPlayActions.append(action);
798 	action->setToolTip(s); action->setStatusTip(s);
799 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/launch.png")));
800 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlay_triggered()));
801 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
802 	s = tr("Play selected machine (embedded)");
803 	action = qmc2FavoritesMenu->addAction(tr("Play &embedded"));
804 	contextMenuPlayActions.append(action);
805 	action->setToolTip(s); action->setStatusTip(s);
806 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
807 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlayEmbedded_triggered()));
808 #endif
809 	qmc2FavoritesMenu->addSeparator();
810 	s = tr("Check current machine's ROM state");
811 	action = qmc2FavoritesMenu->addAction(tr("Check &ROM state"));
812 	action->setToolTip(s); action->setStatusTip(s);
813 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rom.png")));
814 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionCheckCurrentROM_triggered()));
815 	s = tr("Analyse current machine's ROM set with the ROMAlyzer");
816 	action = qmc2FavoritesMenu->addAction(tr("&Analyse ROM..."));
817 	criticalActions << action;
818 	action->setToolTip(s); action->setStatusTip(s);
819 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/romalyzer.png")));
820 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionAnalyseCurrentROM_triggered()));
821 	s = tr("Rebuild current machine's ROM set with the ROMAlyzer");
822 	action = qmc2FavoritesMenu->addAction(tr("&Rebuild ROM..."));
823 	criticalActions << action;
824 	rebuildRomActions << action;
825 	action->setToolTip(s); action->setStatusTip(s);
826 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rebuild.png")));
827 	connect(action, SIGNAL(triggered()), this, SLOT(actionRebuildRom_triggered()));
828 	qmc2FavoritesMenu->addSeparator();
829 	qmc2FavoritesMenu->addMenu(menuRank);
830 	qmc2FavoritesMenu->addMenu(menuSearchWeb);
831 	qmc2FavoritesMenu->addMenu(menuManual);
832 	qmc2FavoritesMenu->addSeparator();
833 	s = tr("Remove from favorites");
834 	action = qmc2FavoritesMenu->addAction(tr("&Remove"));
835 	action->setToolTip(s); action->setStatusTip(s);
836 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/editdelete.png")));
837 	connect(action, SIGNAL(triggered()), this, SLOT(action_removeFromFavorites_triggered()));
838 	s = tr("Clear all favorites");
839 	action = qmc2FavoritesMenu->addAction(tr("&Clear"));
840 	action->setToolTip(s); action->setStatusTip(s);
841 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/broom.png")));
842 	connect(action, SIGNAL(triggered()), this, SLOT(action_clearAllFavorites_triggered()));
843 	s = tr("Save favorites now");
844 	action = qmc2FavoritesMenu->addAction(tr("&Save"));
845 	action->setToolTip(s); action->setStatusTip(s);
846 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/filesave.png")));
847 	connect(action, SIGNAL(triggered()), this, SLOT(action_saveFavorites_triggered()));
848 
849 	qmc2PlayedMenu = new QMenu(0);
850 	s = tr("Play selected machine");
851 	action = qmc2PlayedMenu->addAction(tr("&Play"));
852 	contextMenuPlayActions.append(action);
853 	action->setToolTip(s); action->setStatusTip(s);
854 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/launch.png")));
855 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlay_triggered()));
856 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
857 	s = tr("Play selected machine (embedded)");
858 	action = qmc2PlayedMenu->addAction(tr("Play &embedded"));
859 	contextMenuPlayActions.append(action);
860 	action->setToolTip(s); action->setStatusTip(s);
861 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/embed.png")));
862 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionPlayEmbedded_triggered()));
863 #endif
864 	s = tr("Add current machine to favorites");
865 	action = qmc2PlayedMenu->addAction(tr("To &favorites"));
866 	action->setToolTip(s); action->setStatusTip(s);
867 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/favorites.png")));
868 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionToFavorites_triggered()));
869 	qmc2PlayedMenu->addSeparator();
870 	s = tr("Check current machine's ROM state");
871 	action = qmc2PlayedMenu->addAction(tr("Check &ROM state"));
872 	action->setToolTip(s); action->setStatusTip(s);
873 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rom.png")));
874 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionCheckCurrentROM_triggered()));
875 	s = tr("Analyse current machine's ROM set with the ROMAlyzer");
876 	action = qmc2PlayedMenu->addAction(tr("&Analyse ROM..."));
877 	criticalActions << action;
878 	action->setToolTip(s); action->setStatusTip(s);
879 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/romalyzer.png")));
880 	connect(action, SIGNAL(triggered()), this, SLOT(on_actionAnalyseCurrentROM_triggered()));
881 	s = tr("Rebuild current machine's ROM set with the ROMAlyzer");
882 	action = qmc2PlayedMenu->addAction(tr("&Rebuild ROM..."));
883 	criticalActions << action;
884 	rebuildRomActions << action;
885 	action->setToolTip(s); action->setStatusTip(s);
886 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/rebuild.png")));
887 	connect(action, SIGNAL(triggered()), this, SLOT(actionRebuildRom_triggered()));
888 	qmc2PlayedMenu->addSeparator();
889 	qmc2PlayedMenu->addMenu(menuRank);
890 	qmc2PlayedMenu->addMenu(menuSearchWeb);
891 	qmc2PlayedMenu->addMenu(menuManual);
892 	qmc2PlayedMenu->addSeparator();
893 	s = tr("Remove from played");
894 	action = qmc2PlayedMenu->addAction(tr("&Remove"));
895 	action->setToolTip(s); action->setStatusTip(s);
896 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/editdelete.png")));
897 	connect(action, SIGNAL(triggered()), this, SLOT(action_removeFromPlayed_triggered()));
898 	s = tr("Clear all played");
899 	action = qmc2PlayedMenu->addAction(tr("&Clear"));
900 	action->setToolTip(s); action->setStatusTip(s);
901 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/broom.png")));
902 	connect(action, SIGNAL(triggered()), this, SLOT(action_clearAllPlayed_triggered()));
903 	s = tr("Save play-history now");
904 	action = qmc2PlayedMenu->addAction(tr("&Save"));
905 	action->setToolTip(s); action->setStatusTip(s);
906 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/filesave.png")));
907 	connect(action, SIGNAL(triggered()), this, SLOT(action_savePlayed_triggered()));
908 
909 	QMenu *m;
910 
911 	// tab widget position menus
912 	menuTabWidgetMachineList = new QMenu(0);
913 	m = new QMenu(tr("Tab position"), 0);
914 	m->setIcon(QIcon(QString::fromUtf8(":/data/img/tabwidget.png")));
915 	menuTabWidgetMachineList->addMenu(m);
916 	s = tr("Set tab position north");
917 	action = m->addAction(tr("&North"));
918 	action->setToolTip(s); action->setStatusTip(s);
919 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/north.png")));
920 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineList_North_activated()));
921 	s = tr("Set tab position south");
922 	action = m->addAction(tr("&South"));
923 	action->setToolTip(s); action->setStatusTip(s);
924 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/south.png")));
925 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineList_South_activated()));
926 	s = tr("Set tab position west");
927 	action = m->addAction(tr("&West"));
928 	action->setToolTip(s); action->setStatusTip(s);
929 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/west.png")));
930 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineList_West_activated()));
931 	s = tr("Set tab position east");
932 	action = m->addAction(tr("&East"));
933 	action->setToolTip(s); action->setStatusTip(s);
934 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/east.png")));
935 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineList_East_activated()));
936 	menuTabWidgetMachineList->addSeparator();
937 	s = tr("Component setup");
938 	action = menuTabWidgetMachineList->addAction(tr("Component setup..."));
939 	action->setToolTip(s); action->setStatusTip(s);
940 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/work.png")));
941 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineList_Setup_activated()));
942 
943 	menuTabWidgetMachineDetail = new QMenu(0);
944 	m = new QMenu(tr("Tab position"), 0);
945 	m->setIcon(QIcon(QString::fromUtf8(":/data/img/tabwidget.png")));
946 	menuTabWidgetMachineDetail->addMenu(m);
947 	s = tr("Set tab position north");
948 	action = m->addAction(tr("&North"));
949 	action->setToolTip(s); action->setStatusTip(s);
950 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/north.png")));
951 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineDetail_North_activated()));
952 	s = tr("Set tab position south");
953 	action = m->addAction(tr("&South"));
954 	action->setToolTip(s); action->setStatusTip(s);
955 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/south.png")));
956 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineDetail_South_activated()));
957 	s = tr("Set tab position west");
958 	action = m->addAction(tr("&West"));
959 	action->setToolTip(s); action->setStatusTip(s);
960 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/west.png")));
961 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineDetail_West_activated()));
962 	s = tr("Set tab position east");
963 	action = m->addAction(tr("&East"));
964 	action->setToolTip(s); action->setStatusTip(s);
965 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/east.png")));
966 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineDetail_East_activated()));
967 	menuTabWidgetMachineDetail->addSeparator();
968 	s = tr("Component setup");
969 	action = menuTabWidgetMachineDetail->addAction(tr("Component setup..."));
970 	action->setToolTip(s); action->setStatusTip(s);
971 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/work.png")));
972 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetMachineDetail_Setup_activated()));
973 
974 	menuTabWidgetLogsAndEmulators = new QMenu(0);
975 	m = new QMenu(tr("Tab position"), 0);
976 	m->setIcon(QIcon(QString::fromUtf8(":/data/img/tabwidget.png")));
977 	menuTabWidgetLogsAndEmulators->addMenu(m);
978 	s = tr("Set tab position north");
979 	action = m->addAction(tr("&North"));
980 	action->setToolTip(s); action->setStatusTip(s);
981 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/north.png")));
982 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetLogsAndEmulators_North_activated()));
983 	s = tr("Set tab position south");
984 	action = m->addAction(tr("&South"));
985 	action->setToolTip(s); action->setStatusTip(s);
986 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/south.png")));
987 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetLogsAndEmulators_South_activated()));
988 	s = tr("Set tab position west");
989 	action = m->addAction(tr("&West"));
990 	action->setToolTip(s); action->setStatusTip(s);
991 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/west.png")));
992 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetLogsAndEmulators_West_activated()));
993 	s = tr("Set tab position east");
994 	action = m->addAction(tr("&East"));
995 	action->setToolTip(s); action->setStatusTip(s);
996 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/east.png")));
997 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetLogsAndEmulators_East_activated()));
998 	menuTabWidgetLogsAndEmulators->addSeparator();
999 	s = tr("Component setup");
1000 	action = menuTabWidgetLogsAndEmulators->addAction(tr("Component setup..."));
1001 	action->setToolTip(s); action->setStatusTip(s);
1002 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/work.png")));
1003 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetLogsAndEmulators_Setup_activated()));
1004 
1005 	menuTabWidgetSoftwareDetail = new QMenu(0);
1006 	m = new QMenu(tr("Tab position"), 0);
1007 	m->setIcon(QIcon(QString::fromUtf8(":/data/img/tabwidget.png")));
1008 	menuTabWidgetSoftwareDetail->addMenu(m);
1009 	s = tr("Set tab position north");
1010 	action = m->addAction(tr("&North"));
1011 	action->setToolTip(s); action->setStatusTip(s);
1012 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/north.png")));
1013 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetSoftwareDetail_North_activated()));
1014 	s = tr("Set tab position south");
1015 	action = m->addAction(tr("&South"));
1016 	action->setToolTip(s); action->setStatusTip(s);
1017 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/south.png")));
1018 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetSoftwareDetail_South_activated()));
1019 	s = tr("Set tab position west");
1020 	action = m->addAction(tr("&West"));
1021 	action->setToolTip(s); action->setStatusTip(s);
1022 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/west.png")));
1023 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetSoftwareDetail_West_activated()));
1024 	s = tr("Set tab position east");
1025 	action = m->addAction(tr("&East"));
1026 	action->setToolTip(s); action->setStatusTip(s);
1027 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/east.png")));
1028 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetSoftwareDetail_East_activated()));
1029 	menuTabWidgetSoftwareDetail->addSeparator();
1030 	s = tr("Component setup");
1031 	action = menuTabWidgetSoftwareDetail->addAction(tr("Component setup..."));
1032 	action->setToolTip(s); action->setStatusTip(s);
1033 	action->setIcon(QIcon(QString::fromUtf8(":/data/img/work.png")));
1034 	connect(action, SIGNAL(triggered()), this, SLOT(menuTabWidgetSoftwareDetail_Setup_activated()));
1035 
1036 	QHeaderView *header;
1037 
1038 	menuMachineListHeader = new QMenu(0);
1039 	header = treeWidgetMachineList->header();
1040 	action = menuMachineListHeader->addAction(tr("Machine / Attribute"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MACHINE);
1041 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_MACHINE));
1042 	action = menuMachineListHeader->addAction(tr("Tag"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_TAG);
1043 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_TAG));
1044 	action = menuMachineListHeader->addAction(tr("Icon / Value"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_ICON);
1045 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_ICON));
1046 	action = menuMachineListHeader->addAction(tr("Year"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_YEAR);
1047 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_YEAR));
1048 	action = menuMachineListHeader->addAction(tr("Manufacturer"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MANU);
1049 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_MANU));
1050 	action = menuMachineListHeader->addAction(tr("Name"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_NAME);
1051 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_NAME));
1052 	action = menuMachineListHeader->addAction(tr("ROM types"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RTYPES);
1053 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_RTYPES));
1054 	action = menuMachineListHeader->addAction(tr("Players"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_PLAYERS);
1055 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_PLAYERS));
1056 	action = menuMachineListHeader->addAction(tr("Driver status"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_DRVSTAT);
1057 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_DRVSTAT));
1058 	action = menuMachineListHeader->addAction(tr("Source file"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_SRCFILE);
1059 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_SRCFILE));
1060 	action = menuMachineListHeader->addAction(tr("Rank"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RANK);
1061 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK));
1062 	action = menuMachineListHeader->addAction(tr("Category"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_CATEGORY);
1063 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_CATEGORY));
1064 	actionMenuMachineListHeaderCategory = action;
1065 	action = menuMachineListHeader->addAction(tr("Version"), this, SLOT(actionMachineListHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_VERSION);
1066 	action->setChecked(!treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_VERSION));
1067 	actionMenuMachineListHeaderVersion = action;
1068 	menuMachineListHeader->addSeparator();
1069 	action = menuMachineListHeader->addAction(QIcon(":data/img/reset.png"), tr("Reset"), this, SLOT(actionMachineListHeader_triggered())); action->setData(QMC2_MACHINELIST_RESET);
1070 	header->setContextMenuPolicy(Qt::CustomContextMenu);
1071 	connect(header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(treeWidgetMachineListHeader_customContextMenuRequested(const QPoint &)));
1072 
1073 	menuHierarchyHeader = new QMenu(0);
1074 	header = treeWidgetHierarchy->header();
1075 	action = menuHierarchyHeader->addAction(tr("Machine / Clones"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MACHINE);
1076 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_MACHINE));
1077 	action = menuHierarchyHeader->addAction(tr("Tag"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_TAG);
1078 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_TAG));
1079 	action = menuHierarchyHeader->addAction(tr("Icon"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_ICON);
1080 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_ICON));
1081 	action = menuHierarchyHeader->addAction(tr("Year"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_YEAR);
1082 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_YEAR));
1083 	action = menuHierarchyHeader->addAction(tr("Manufacturer"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MANU);
1084 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_MANU));
1085 	action = menuHierarchyHeader->addAction(tr("Name"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_NAME);
1086 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_NAME));
1087 	action = menuHierarchyHeader->addAction(tr("ROM types"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RTYPES);
1088 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_RTYPES));
1089 	action = menuHierarchyHeader->addAction(tr("Players"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_PLAYERS);
1090 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_PLAYERS));
1091 	action = menuHierarchyHeader->addAction(tr("Driver status"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_DRVSTAT);
1092 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_DRVSTAT));
1093 	action = menuHierarchyHeader->addAction(tr("Source file"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_SRCFILE);
1094 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_SRCFILE));
1095 	action = menuHierarchyHeader->addAction(tr("Rank"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RANK);
1096 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK));
1097 	action = menuHierarchyHeader->addAction(tr("Category"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_CATEGORY);
1098 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_CATEGORY));
1099 	actionMenuHierarchyHeaderCategory = action;
1100 	action = menuHierarchyHeader->addAction(tr("Version"), this, SLOT(actionHierarchyHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_VERSION);
1101 	action->setChecked(!treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_VERSION));
1102 	actionMenuHierarchyHeaderVersion = action;
1103 	menuHierarchyHeader->addSeparator();
1104 	action = menuHierarchyHeader->addAction(QIcon(":data/img/reset.png"), tr("Reset"), this, SLOT(actionHierarchyHeader_triggered())); action->setData(QMC2_MACHINELIST_RESET);
1105 	header->setContextMenuPolicy(Qt::CustomContextMenu);
1106 	connect(header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(treeWidgetHierarchyHeader_customContextMenuRequested(const QPoint &)));
1107 
1108 	menuCategoryHeader = new QMenu(0);
1109 	header = treeWidgetCategoryView->header();
1110 	action = menuCategoryHeader->addAction(tr("Category / Machine"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MACHINE);
1111 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_MACHINE));
1112 	action = menuCategoryHeader->addAction(tr("Tag"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_TAG);
1113 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_TAG));
1114 	action = menuCategoryHeader->addAction(tr("Icon"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_ICON);
1115 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_ICON));
1116 	action = menuCategoryHeader->addAction(tr("Year"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_YEAR);
1117 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_YEAR));
1118 	action = menuCategoryHeader->addAction(tr("Manufacturer"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MANU);
1119 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_MANU));
1120 	action = menuCategoryHeader->addAction(tr("Name"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_NAME);
1121 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_NAME));
1122 	action = menuCategoryHeader->addAction(tr("ROM types"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RTYPES);
1123 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RTYPES));
1124 	action = menuCategoryHeader->addAction(tr("Players"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_PLAYERS);
1125 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_PLAYERS));
1126 	action = menuCategoryHeader->addAction(tr("Driver status"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_DRVSTAT);
1127 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_DRVSTAT));
1128 	action = menuCategoryHeader->addAction(tr("Source file"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_SRCFILE);
1129 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_SRCFILE));
1130 	action = menuCategoryHeader->addAction(tr("Rank"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RANK);
1131 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK));
1132 	action = menuCategoryHeader->addAction(tr("Version"), this, SLOT(actionCategoryHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_VERSION);
1133 	action->setChecked(!treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_VERSION));
1134 	actionMenuCategoryHeaderVersion = action;
1135 	menuCategoryHeader->addSeparator();
1136 	action = menuCategoryHeader->addAction(QIcon(":data/img/reset.png"), tr("Reset"), this, SLOT(actionCategoryHeader_triggered())); action->setData(QMC2_MACHINELIST_RESET);
1137 	header->setContextMenuPolicy(Qt::CustomContextMenu);
1138 	connect(header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(treeWidgetCategoryViewHeader_customContextMenuRequested(const QPoint &)));
1139 
1140 	menuVersionHeader = new QMenu(0);
1141 	header = treeWidgetVersionView->header();
1142 	action = menuVersionHeader->addAction(tr("Version / Machine"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MACHINE);
1143 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_MACHINE));
1144 	action = menuVersionHeader->addAction(tr("Tag"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_TAG);
1145 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_TAG));
1146 	action = menuVersionHeader->addAction(tr("Icon"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_ICON);
1147 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_ICON));
1148 	action = menuVersionHeader->addAction(tr("Year"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_YEAR);
1149 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_YEAR));
1150 	action = menuVersionHeader->addAction(tr("Manufacturer"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_MANU);
1151 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_MANU));
1152 	action = menuVersionHeader->addAction(tr("Name"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_NAME);
1153 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_NAME));
1154 	action = menuVersionHeader->addAction(tr("ROM types"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RTYPES);
1155 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RTYPES));
1156 	action = menuVersionHeader->addAction(tr("Players"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_PLAYERS);
1157 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_PLAYERS));
1158 	action = menuVersionHeader->addAction(tr("Driver status"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_DRVSTAT);
1159 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_DRVSTAT));
1160 	action = menuVersionHeader->addAction(tr("Source file"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_SRCFILE);
1161 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_SRCFILE));
1162 	action = menuVersionHeader->addAction(tr("Rank"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_RANK);
1163 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK));
1164 	action = menuVersionHeader->addAction(tr("Category"), this, SLOT(actionVersionHeader_triggered())); action->setCheckable(true); action->setData(QMC2_MACHINELIST_COLUMN_CATEGORY);
1165 	action->setChecked(!treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_CATEGORY));
1166 	actionMenuVersionHeaderCategory = action;
1167 	menuVersionHeader->addSeparator();
1168 	action = menuVersionHeader->addAction(QIcon(":data/img/reset.png"), tr("Reset"), this, SLOT(actionVersionHeader_triggered())); action->setData(QMC2_MACHINELIST_RESET);
1169 	header->setContextMenuPolicy(Qt::CustomContextMenu);
1170 	connect(header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(treeWidgetVersionViewHeader_customContextMenuRequested(const QPoint &)));
1171 
1172 	m_searchBoxKeyEventFilter = new SearchBoxKeyEventFilter(this);
1173 
1174 	// other actions
1175 	comboBoxSearch->setLineEdit(new IconLineEdit(QIcon(QString::fromUtf8(":/data/img/find.png")), QMC2_ALIGN_LEFT, comboBoxSearch));
1176 	connect(actionViewFullDetail, SIGNAL(triggered()), this, SLOT(viewFullDetail()));
1177 	connect(actionViewParentClones, SIGNAL(triggered()), this, SLOT(viewParentClones()));
1178 	connect(actionViewByCategory, SIGNAL(triggered()), this, SLOT(viewByCategory()));
1179 	connect(actionViewByVersion, SIGNAL(triggered()), this, SLOT(viewByVersion()));
1180 	actionCustomView = new QAction(this);
1181 	connect(actionCustomView, SIGNAL(triggered()), this, SLOT(actionCustomView_triggered()));
1182 	addAction(actionCustomView);
1183 	connect(&searchTimer, SIGNAL(timeout()), this, SLOT(comboBoxSearch_editTextChanged_delayed()));
1184 	connect(&updateTimer, SIGNAL(timeout()), this, SLOT(treeWidgetMachineList_itemSelectionChanged_delayed()));
1185 	connect(&activityCheckTimer, SIGNAL(timeout()), this, SLOT(checkActivity()));
1186 	activityState = false;
1187 	comboBoxSearch->lineEdit()->setPlaceholderText(tr("Enter search string"));
1188 	comboBoxSearch->installEventFilter(m_searchBoxKeyEventFilter);
1189 
1190 	// search options menus
1191 	menuSearchOptions = new QMenu(this);
1192 	s = tr("Negate search");
1193 	actionNegateSearch = menuSearchOptions->addAction(s);
1194 	actionNegateSearch->setToolTip(s); actionNegateSearch->setStatusTip(s);
1195 	actionNegateSearch->setIcon(QIcon(QString::fromUtf8(":/data/img/find_negate.png")));
1196 	actionNegateSearch->setCheckable(true);
1197 	bool negated = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/NegateSearch", false).toBool();
1198 	actionNegateSearch->setChecked(negated);
1199 	negateSearchTriggered(negated);
1200 	menuSearchOptions->addSeparator();
1201 	s = tr("Include BIOS sets");
1202 	actionSearchIncludeBiosSets = menuSearchOptions->addAction(s);
1203 	actionSearchIncludeBiosSets->setToolTip(s); actionSearchIncludeBiosSets->setStatusTip(s);
1204 	actionSearchIncludeBiosSets->setCheckable(true);
1205 	bool includeBiosSets = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SearchIncludeBiosSets", true).toBool();
1206 	actionSearchIncludeBiosSets->setChecked(includeBiosSets);
1207 	connect(actionSearchIncludeBiosSets, SIGNAL(triggered(bool)), this, SLOT(searchIncludeBiosSetsTriggered(bool)));
1208 	s = tr("Include device sets");
1209 	actionSearchIncludeDeviceSets = menuSearchOptions->addAction(s);
1210 	actionSearchIncludeDeviceSets->setToolTip(s); actionSearchIncludeDeviceSets->setStatusTip(s);
1211 	actionSearchIncludeDeviceSets->setCheckable(true);
1212 	bool includeDeviceSets = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SearchIncludeDeviceSets", true).toBool();
1213 	actionSearchIncludeDeviceSets->setChecked(includeDeviceSets);
1214 	connect(actionSearchIncludeDeviceSets, SIGNAL(triggered(bool)), this, SLOT(searchIncludeDeviceSetsTriggered(bool)));
1215 	connect(actionNegateSearch, SIGNAL(triggered(bool)), this, SLOT(negateSearchTriggered(bool)));
1216 	IconLineEdit *ileSearch = ((IconLineEdit *)comboBoxSearch->lineEdit());
1217 	connect(ileSearch, SIGNAL(returnPressed()), this, SLOT(comboBoxSearch_editTextChanged_delayed()));
1218 	IconLineEdit *ileToolbarSearch = ((IconLineEdit *)comboBoxToolbarSearch->lineEdit());
1219 	connect(ileToolbarSearch, SIGNAL(returnPressed()), this, SLOT(comboBoxToolbarSearch_activated()));
1220 	ileSearch->button()->setPopupMode(QToolButton::InstantPopup);
1221 	ileToolbarSearch->button()->setPopupMode(QToolButton::InstantPopup);
1222 	ileSearch->button()->setMenu(menuSearchOptions);
1223 	ileToolbarSearch->button()->setMenu(menuSearchOptions);
1224 
1225 	// rank locking
1226 	RankItemWidget::ranksLocked = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/RanksLocked", false).toBool();
1227 	if ( RankItemWidget::ranksLocked ) {
1228 		actionLockRanks->setIcon(QIcon(QString::fromUtf8(":/data/img/unlock.png")));
1229 		actionLockRanks->setText(tr("Unlock ranks"));
1230 		actionLockRanks->setToolTip(tr("Unlock ranks"));
1231 		actionLockRanks->setStatusTip(tr("Unlock ranks"));
1232 	} else {
1233 		actionLockRanks->setIcon(QIcon(QString::fromUtf8(":/data/img/lock.png")));
1234 		actionLockRanks->setText(tr("Lock ranks"));
1235 		actionLockRanks->setToolTip(tr("Lock ranks"));
1236 		actionLockRanks->setStatusTip(tr("Lock ranks"));
1237 	}
1238 	menuRank_enableActions(!RankItemWidget::ranksLocked);
1239 
1240 	// restore toolbar state
1241 	restoreState(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ToolbarState", QByteArray()).toByteArray());
1242 #if defined(QMC2_OS_MAC)
1243 	setUnifiedTitleAndToolBarOnMac(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/UnifiedTitleAndToolBarOnMac", false).toBool());
1244 #endif
1245 
1246 #if QMC2_JOYSTICK == 1
1247 	joyIndex = -1;
1248 #endif
1249 
1250 	// download manager widget
1251 	checkBoxRemoveFinishedDownloads->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Downloads/RemoveFinished", false).toBool());
1252 
1253 	// setup ROM state filter selector menu & toggle actions / short cuts
1254 	qmc2StatesTogglesEnabled = false;
1255 	menuRomStatusFilter = new QMenu(toolButtonSelectRomFilter);
1256 	romStateFilter = new RomStateFilter(this);
1257 	stateFilterAction = new QWidgetAction(menuRomStatusFilter);
1258 	stateFilterAction->setDefaultWidget(romStateFilter);
1259 	menuRomStatusFilter->addAction(stateFilterAction);
1260 	toolButtonSelectRomFilter->setMenu(menuRomStatusFilter);
1261 
1262 	// initialize ROM state toggles
1263 	romStateFilter->toolButtonCorrect->setChecked(qmc2Filter[QMC2_ROMSTATE_INT_C]);
1264 	romStateFilter->toolButtonMostlyCorrect->setChecked(qmc2Filter[QMC2_ROMSTATE_INT_M]);
1265 	romStateFilter->toolButtonIncorrect->setChecked(qmc2Filter[QMC2_ROMSTATE_INT_I]);
1266 	romStateFilter->toolButtonNotFound->setChecked(qmc2Filter[QMC2_ROMSTATE_INT_N]);
1267 	romStateFilter->toolButtonUnknown->setChecked(qmc2Filter[QMC2_ROMSTATE_INT_U]);
1268 
1269 	// connect header click signals
1270 	connect(treeWidgetMachineList->header(), SIGNAL(sectionClicked(int)), this, SLOT(treeWidgetMachineList_headerSectionClicked(int)));
1271 	connect(treeWidgetHierarchy->header(), SIGNAL(sectionClicked(int)), this, SLOT(treeWidgetHierarchy_headerSectionClicked(int)));
1272 #if QT_VERSION < 0x050000
1273 	treeWidgetMachineList->header()->setClickable(true);
1274 	treeWidgetHierarchy->header()->setClickable(true);
1275 #else
1276 	treeWidgetMachineList->header()->setSectionsClickable(true);
1277 	treeWidgetHierarchy->header()->setSectionsClickable(true);
1278 #endif
1279 	connect(treeWidgetCategoryView->header(), SIGNAL(sectionClicked(int)), this, SLOT(treeWidgetCategoryView_headerSectionClicked(int)));
1280 #if QT_VERSION < 0x050000
1281 	treeWidgetCategoryView->header()->setClickable(true);
1282 #else
1283 	treeWidgetCategoryView->header()->setSectionsClickable(true);
1284 #endif
1285 	connect(treeWidgetVersionView->header(), SIGNAL(sectionClicked(int)), this, SLOT(treeWidgetVersionView_headerSectionClicked(int)));
1286 #if QT_VERSION < 0x050000
1287 	treeWidgetVersionView->header()->setClickable(true);
1288 #else
1289 	treeWidgetVersionView->header()->setSectionsClickable(true);
1290 #endif
1291 
1292 	// connections for dock/undock buttons
1293 	connect(floatToggleButtonSoftwareDetail, SIGNAL(toggled(bool)), this, SLOT(floatToggleButtonSoftwareDetail_toggled(bool)));
1294 
1295 	// setup the global network access manager
1296 	qmc2NetworkAccessManager = new NetworkAccessManager(0, this);
1297 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "WebBrowser/RestoreCookies", true).toBool() )
1298 		qmc2NetworkAccessManager->setCookieJar(new CookieJar(qmc2NetworkAccessManager));
1299 
1300 	// URL replacement regexp
1301 	QString urlChar = QLatin1String("\\+\\-\\w\\./#@&;:=\\?~%_,\\!\\$\\*");
1302 	urlSectionRegExp = QString("[%1]+").arg(urlChar);
1303 
1304 	connect(treeWidgetMachineList->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(treeWidgetMachineList_verticalScrollChanged(int)));
1305 	m_mlRankUpdateTimer.setSingleShot(true);
1306 	connect(&m_mlRankUpdateTimer, SIGNAL(timeout()), this, SLOT(treeWidgetMachineList_updateRanks()));
1307 	connect(treeWidgetHierarchy->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(treeWidgetHierarchy_verticalScrollChanged(int)));
1308 	m_hlRankUpdateTimer.setSingleShot(true);
1309 	connect(&m_hlRankUpdateTimer, SIGNAL(timeout()), this, SLOT(treeWidgetHierarchy_updateRanks()));
1310 	connect(treeWidgetCategoryView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(treeWidgetCategoryView_verticalScrollChanged(int)));
1311 	m_clRankUpdateTimer.setSingleShot(true);
1312 	connect(&m_clRankUpdateTimer, SIGNAL(timeout()), this, SLOT(treeWidgetCategoryView_updateRanks()));
1313 	connect(treeWidgetVersionView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(treeWidgetVersionView_verticalScrollChanged(int)));
1314 	m_vlRankUpdateTimer.setSingleShot(true);
1315 	connect(&m_vlRankUpdateTimer, SIGNAL(timeout()), this, SLOT(treeWidgetVersionView_updateRanks()));
1316 
1317 	// rank related
1318 	RankItemWidget::rankSingle = QImage(QString::fromUtf8(":/data/img/rank.png"));
1319 	RankItemWidget::rankSingleFlat = QImage(QString::fromUtf8(":/data/img/rank_flat.png"));
1320 	RankItemWidget::rankBackround = QImage(QString::fromUtf8(":/data/img/rank_bg.png"));
1321 	RankItemWidget::rankGradient = QLinearGradient(0, 0, RankItemWidget::rankBackround.width() - 1, 0);
1322 	RankItemWidget::rankGradient.setColorAt(0, QColor(255, 255, 255, 100));
1323 	RankItemWidget::rankGradient.setColorAt(1, Qt::transparent);
1324 	RankItemWidget::useColorRankImage = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ColorRankImage", false).toBool();
1325 	RankItemWidget::useFlatRankImage = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/FlatRankImage", false).toBool();
1326 	RankItemWidget::rankImageColor = QColor(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/RankImageColor", "#646464").toString());
1327 	if ( RankItemWidget::useColorRankImage )
1328 		on_actionRankImagePlain_triggered(true);
1329 	else if ( RankItemWidget::useFlatRankImage )
1330 		on_actionRankImageFlat_triggered(true);
1331 	else
1332 		on_actionRankImageGradient_triggered(true);
1333 	connect(menuRank, SIGNAL(aboutToShow()), this, SLOT(menuRank_aboutToShow()));
1334 
1335 	// prepare to receive MAME output notifications from the process manager
1336 	connect(qmc2ProcessManager, SIGNAL(mameOutputNotifier(int, const QString &, const QString &)), this, SLOT(processOutputNotifier(int, const QString &, const QString &)));
1337 
1338 	// Qt bug workaround
1339 	connect(this, SIGNAL(updateDetailTabBar(int)), this, SLOT(detailTabBarUpdate(int)));
1340 
1341 	QTimer::singleShot(0, this, SLOT(init()));
1342 }
1343 
~MainWindow()1344 MainWindow::~MainWindow()
1345 {
1346 	if ( qmc2StartupDefaultFont )
1347 		delete qmc2StartupDefaultFont;
1348 	delete loadAnimMovie;
1349 	delete nullMovie;
1350 }
1351 
log(int logTarget,const QString & msg)1352 void MainWindow::log(int logTarget, const QString &msg)
1353 {
1354 	if ( !qmc2GuiReady )
1355 		return;
1356 	QString message(msg);
1357 	QString timeString(QTime::currentTime().toString("hh:mm:ss.zzz") + ": ");
1358 	switch ( logTarget ) {
1359 		case QMC2_LOG_FRONTEND:
1360 			if ( !qmc2LogFrontendMutex.tryLock(QMC2_LOG_MUTEX_LOCK_TIMEOUT) )
1361 				return;
1362 			if ( message.compare(qmc2LastFrontendLogMessage) == 0 ) {
1363 				qmc2FrontendLogMessageRepeatCount++;
1364 				qmc2LogFrontendMutex.unlock();
1365 				return;
1366 			} else {
1367 				qmc2LastFrontendLogMessage = message;
1368 				if ( qmc2FrontendLogMessageRepeatCount > 0 )
1369 					message = tr("last message repeated %n time(s)", "", qmc2FrontendLogMessageRepeatCount) + '\n' + timeString + qmc2LastFrontendLogMessage;
1370 				qmc2FrontendLogMessageRepeatCount = 0;
1371 			}
1372 			break;
1373 		case QMC2_LOG_EMULATOR:
1374 			if( !qmc2LogEmulatorMutex.tryLock(QMC2_LOG_MUTEX_LOCK_TIMEOUT) )
1375 				return;
1376 			if ( message.compare(qmc2LastEmulatorLogMessage) == 0 ) {
1377 				qmc2EmulatorLogMessageRepeatCount++;
1378 				qmc2LogEmulatorMutex.unlock();
1379 				return;
1380 			} else {
1381 				qmc2LastEmulatorLogMessage = message;
1382 				if ( qmc2EmulatorLogMessageRepeatCount > 0 )
1383 					message = tr("last message repeated %n time(s)", "", qmc2EmulatorLogMessageRepeatCount) + '\n' + timeString + qmc2LastEmulatorLogMessage;
1384 				qmc2EmulatorLogMessageRepeatCount = 0;
1385 			}
1386 			break;
1387 		default:
1388 			return;
1389 	}
1390 	message.prepend(timeString);
1391 	switch ( logTarget ) {
1392 		case QMC2_LOG_FRONTEND:
1393 			textBrowserFrontendLog->appendPlainText(message);
1394 			if ( !qmc2FrontendLogFile ) {
1395 #if defined(QMC2_SDLMAME)
1396 				if ( (qmc2FrontendLogFile = new QFile(qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/LogFile", Options::configPath() + "/qmc2-sdlmame.log").toString(), this)) == 0 ) {
1397 					qmc2LogFrontendMutex.unlock();
1398 					return;
1399 				}
1400 #elif defined(QMC2_MAME)
1401 				if ( (qmc2FrontendLogFile = new QFile(qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/LogFile", Options::configPath() + "/qmc2-mame.log").toString(), this)) == 0 ) {
1402 					qmc2LogFrontendMutex.unlock();
1403 					return;
1404 				}
1405 #endif
1406 			}
1407 			if ( !qmc2FrontendLogFile->isOpen() ) {
1408 				if ( qmc2FrontendLogFile->open(QIODevice::WriteOnly | QIODevice::Text) )
1409 					qmc2FrontendLogStream.setDevice(qmc2FrontendLogFile);
1410 				else {
1411 					qmc2LogFrontendMutex.unlock();
1412 					return;
1413 				}
1414 			}
1415 			qmc2FrontendLogStream << message << '\n';
1416 			qmc2FrontendLogStream.flush();
1417 			qmc2LogFrontendMutex.unlock();
1418 			break;
1419 		case QMC2_LOG_EMULATOR:
1420 			textBrowserEmulatorLog->appendPlainText(message);
1421 			if ( !qmc2EmulatorLogFile ) {
1422 				if ( (qmc2EmulatorLogFile = new QFile(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/LogFile", Options::configPath() + "/mame.log").toString(), this)) == 0 ) {
1423 					qmc2LogEmulatorMutex.unlock();
1424 					return;
1425 				}
1426 			}
1427 			if ( !qmc2EmulatorLogFile->isOpen() ) {
1428 				if ( qmc2EmulatorLogFile->open(QIODevice::WriteOnly | QIODevice::Text) )
1429 					qmc2EmulatorLogStream.setDevice(qmc2EmulatorLogFile);
1430 				else {
1431 					qmc2LogEmulatorMutex.unlock();
1432 					return;
1433 				}
1434 			}
1435 			qmc2EmulatorLogStream << message << '\n';
1436 			qmc2EmulatorLogStream.flush();
1437 			qmc2LogEmulatorMutex.unlock();
1438 			break;
1439 		default:
1440 			break;
1441 	}
1442 }
1443 
logScrollToEnd(int logTarget)1444 void MainWindow::logScrollToEnd(int logTarget)
1445 {
1446 	switch ( logTarget ) {
1447 		case QMC2_LOG_FRONTEND:
1448 			textBrowserFrontendLog->horizontalScrollBar()->setValue(textBrowserFrontendLog->horizontalScrollBar()->minimum());
1449 		        textBrowserFrontendLog->verticalScrollBar()->setValue(textBrowserFrontendLog->verticalScrollBar()->maximum());
1450 			break;
1451 		case QMC2_LOG_EMULATOR:
1452 			textBrowserEmulatorLog->horizontalScrollBar()->setValue(textBrowserEmulatorLog->horizontalScrollBar()->minimum());
1453 		        textBrowserEmulatorLog->verticalScrollBar()->setValue(textBrowserEmulatorLog->verticalScrollBar()->maximum());
1454 			break;
1455 		default:
1456 			break;
1457 	}
1458 }
1459 
tabWidgetMachineList_tabMoved(int from,int to)1460 void MainWindow::tabWidgetMachineList_tabMoved(int from, int to)
1461 {
1462 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(0);
1463 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
1464 
1465 	if ( !componentInfo )
1466 		return;
1467 
1468 	int adjustedFrom = from;
1469 	int adjustedTo = to;
1470 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
1471 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
1472 	if ( embedIndex >= 0 ) {
1473 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 ) {
1474 			if ( embedIndex <= adjustedFrom )
1475 				adjustedFrom++;
1476 			if ( embedIndex <= adjustedTo )
1477 				adjustedTo++;
1478 		}
1479 	}
1480 #endif
1481 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
1482 	if ( foreignIndex >= 0 ) {
1483 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 ) {
1484 			if ( foreignIndex <= adjustedFrom )
1485 				adjustedFrom++;
1486 			if ( foreignIndex <= adjustedTo )
1487 				adjustedTo++;
1488 		}
1489 	}
1490 
1491 	int fromFeature = componentInfo->appliedFeatureList().at(adjustedFrom);
1492 	componentInfo->appliedFeatureList().removeAt(adjustedFrom);
1493 	componentInfo->appliedFeatureList().insert(adjustedTo, fromFeature);
1494 	fromFeature = componentInfo->activeFeatureList().at(adjustedFrom);
1495 	componentInfo->activeFeatureList().removeAt(adjustedFrom);
1496 	componentInfo->activeFeatureList().insert(adjustedTo, fromFeature);
1497 
1498 	QListWidgetItem *takenItem = qmc2ComponentSetup->listWidgetActiveFeatures->takeItem(adjustedFrom);
1499 	if ( takenItem )
1500 		qmc2ComponentSetup->listWidgetActiveFeatures->insertItem(adjustedTo, takenItem);
1501 
1502 	QStringList activeIndexList;
1503 	for (int i = 0; i < componentInfo->appliedFeatureList().count(); i++)
1504 		activeIndexList << QString::number(componentInfo->appliedFeatureList().at(i));
1505 
1506 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Component1/ActiveFeatures", activeIndexList);
1507 }
1508 
tabWidgetMachineDetail_tabMoved(int from,int to)1509 void MainWindow::tabWidgetMachineDetail_tabMoved(int from, int to)
1510 {
1511 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(1);
1512 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
1513 
1514 	if ( !componentInfo )
1515 		return;
1516 
1517 	int fromFeature = componentInfo->appliedFeatureList().at(from);
1518 	componentInfo->appliedFeatureList().removeAt(from);
1519 	componentInfo->appliedFeatureList().insert(to, fromFeature);
1520 	fromFeature = componentInfo->activeFeatureList().at(from);
1521 	componentInfo->activeFeatureList().removeAt(from);
1522 	componentInfo->activeFeatureList().insert(to, fromFeature);
1523 
1524 	QListWidgetItem *takenItem = qmc2ComponentSetup->listWidgetActiveFeatures->takeItem(from);
1525 	if ( takenItem )
1526 		qmc2ComponentSetup->listWidgetActiveFeatures->insertItem(to, takenItem);
1527 
1528 	QStringList activeIndexList;
1529 	for (int i = 0; i < componentInfo->appliedFeatureList().count(); i++)
1530 		activeIndexList << QString::number(componentInfo->appliedFeatureList().at(i));
1531 
1532 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Component2/ActiveFeatures", activeIndexList);
1533 }
1534 
tabWidgetLogsAndEmulators_tabMoved(int from,int to)1535 void MainWindow::tabWidgetLogsAndEmulators_tabMoved(int from, int to)
1536 {
1537 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(2);
1538 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component3");
1539 
1540 	if ( !componentInfo )
1541 		return;
1542 
1543 	int fromFeature = componentInfo->appliedFeatureList().at(from);
1544 	componentInfo->appliedFeatureList().removeAt(from);
1545 	componentInfo->appliedFeatureList().insert(to, fromFeature);
1546 	fromFeature = componentInfo->activeFeatureList().at(from);
1547 	componentInfo->activeFeatureList().removeAt(from);
1548 	componentInfo->activeFeatureList().insert(to, fromFeature);
1549 
1550 	QListWidgetItem *takenItem = qmc2ComponentSetup->listWidgetActiveFeatures->takeItem(from);
1551 	if ( takenItem )
1552 		qmc2ComponentSetup->listWidgetActiveFeatures->insertItem(to, takenItem);
1553 
1554 	QStringList activeIndexList;
1555 	for (int i = 0; i < componentInfo->appliedFeatureList().count(); i++)
1556 		activeIndexList << QString::number(componentInfo->appliedFeatureList().at(i));
1557 
1558 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Component3/ActiveFeatures", activeIndexList);
1559 }
1560 
tabWidgetSoftwareDetail_tabMoved(int from,int to)1561 void MainWindow::tabWidgetSoftwareDetail_tabMoved(int from, int to)
1562 {
1563 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(3);
1564 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component4");
1565 
1566 	if ( !componentInfo )
1567 		return;
1568 
1569 	int fromFeature = componentInfo->appliedFeatureList().at(from);
1570 	componentInfo->appliedFeatureList().removeAt(from);
1571 	componentInfo->appliedFeatureList().insert(to, fromFeature);
1572 	fromFeature = componentInfo->activeFeatureList().at(from);
1573 	componentInfo->activeFeatureList().removeAt(from);
1574 	componentInfo->activeFeatureList().insert(to, fromFeature);
1575 
1576 	QListWidgetItem *takenItem = qmc2ComponentSetup->listWidgetActiveFeatures->takeItem(from);
1577 	if ( takenItem )
1578 		qmc2ComponentSetup->listWidgetActiveFeatures->insertItem(to, takenItem);
1579 
1580 	QStringList activeIndexList;
1581 	for (int i = 0; i < componentInfo->appliedFeatureList().count(); i++)
1582 		activeIndexList << QString::number(componentInfo->appliedFeatureList().at(i));
1583 
1584 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Component4/ActiveFeatures", activeIndexList);
1585 }
1586 
on_actionPlayEmbedded_triggered(bool)1587 void MainWindow::on_actionPlayEmbedded_triggered(bool)
1588 {
1589 	qmc2StartEmbedded = true;
1590 	on_actionPlay_triggered();
1591 }
1592 
on_actionPlay_triggered(bool)1593 void MainWindow::on_actionPlay_triggered(bool)
1594 {
1595 	if ( qmc2EarlyReloadActive )
1596 		return;
1597 
1598 	if ( !qmc2CurrentItem && qmc2DemoMachine.isEmpty() )
1599 		return;
1600 
1601 	if ( qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
1602 		return;
1603 
1604 	if ( qmc2CriticalSection ) {
1605 		QTimer::singleShot(10, this, SLOT(on_actionPlay_triggered()));
1606 		return;
1607 	}
1608 
1609 	QString machineName;
1610 
1611 	if ( !qmc2DemoMachine.isEmpty() )
1612 		machineName = qmc2DemoMachine;
1613 	else if ( !qmc2CurrentItem )
1614 		return;
1615 	else
1616 		machineName = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME);
1617 
1618 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
1619 	if ( !componentInfo )
1620 		return;
1621 
1622 	if ( qmc2DemoMachine.isEmpty() ) {
1623 		qmc2LastConfigItem = 0;
1624 		if ( componentInfo->appliedFeatureList().at(tabWidgetMachineDetail->currentIndex()) == QMC2_SYSTEM_NOTES_INDEX )
1625 			m_ignoreDetailTabChange = true;
1626 		on_tabWidgetMachineDetail_currentChanged(componentInfo->appliedFeatureList().indexOf(QMC2_CONFIG_INDEX));
1627 		m_ignoreDetailTabChange = false;
1628 	}
1629 
1630 	// check if a foreign emulator is to be used and if it CAN be used; if yes (both), start it instead of the default emulator...
1631 	qmc2Config->beginGroup(QMC2_EMULATOR_PREFIX + "RegisteredEmulators");
1632 	QStringList registeredEmulators(qmc2Config->childGroups());
1633 	qmc2Config->endGroup();
1634 	bool foreignEmulator = false;
1635 	if ( !registeredEmulators.isEmpty() && qmc2DemoMachine.isEmpty() ) {
1636 		if ( !launchForeignID ) {
1637 			if ( tabWidgetMachineList->currentIndex() == tabWidgetMachineList->indexOf(tabForeignEmulators) ) {
1638 				QTreeWidgetItem *item = treeWidgetForeignIDs->currentItem();
1639 				if ( item && item->isSelected() ) {
1640 					QStringList foreignInfo(item->whatsThis(0).split('\t'));
1641 					if ( foreignInfo.count() > 2 ) {
1642 						// 0:emuName -- 1:id -- 2:description
1643 						foreignEmuName = foreignInfo.at(0);
1644 						foreignID = foreignInfo.at(1);
1645 						foreignDescription = foreignInfo.at(2);
1646 						launchForeignID = true;
1647 					}
1648 				}
1649 			}
1650 		}
1651 		if ( launchForeignID ) {
1652 			foreignEmulator = true;
1653 			QString emuCommand(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/Executable").arg(foreignEmuName), QString()).toString());
1654 			QString emuWorkDir(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/WorkingDirectory").arg(foreignEmuName), QString()).toString());
1655 			QString argString(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/Arguments").arg(foreignEmuName), QString()).toString());
1656 			QStringList emuArgs;
1657 			if ( foreignID == tr("N/A") )
1658 				argString.replace("$ID$", "").replace("$DESCRIPTION$", "");
1659 			else
1660 				argString.replace("$ID$", foreignID).replace("$DESCRIPTION$", foreignDescription);
1661 			QRegExp rx("([^\\s]+|[^\\s]*\"[^\"]+\"[^\\s]*)");
1662 			int i = 0;
1663 			while ( (i = rx.indexIn(argString, i)) != -1 ) {
1664 				emuArgs << rx.cap(1).trimmed().remove("\"");
1665 				i += rx.matchedLength();
1666 			}
1667 			qmc2ProcessManager->process(qmc2ProcessManager->start(emuCommand, emuArgs, true, emuWorkDir));
1668 		} else if ( qmc2Config->contains(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator") ) {
1669 			QString selectedEmulator(qmc2Config->value(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator").toString());
1670 			if ( !selectedEmulator.isEmpty() && registeredEmulators.contains(selectedEmulator) ) {
1671 				foreignEmulator = true;
1672 				QString emuCommand(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/Executable").arg(selectedEmulator), QString()).toString());
1673 				QString emuWorkDir(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/WorkingDirectory").arg(selectedEmulator), QString()).toString());
1674 				QString argString(qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "RegisteredEmulators/%1/Arguments").arg(selectedEmulator), QString()).toString());
1675 				QStringList emuArgs;
1676 				argString.replace("$ID$", machineName).replace("$DESCRIPTION$", qmc2MachineListItemHash.value(machineName)->text(QMC2_MACHINELIST_COLUMN_MACHINE));
1677 				QRegExp rx("([^\\s]+|[^\\s]*\"[^\"]+\"[^\\s]*)");
1678 				int i = 0;
1679 				while ( (i = rx.indexIn(argString, i)) != -1 ) {
1680 					emuArgs << rx.cap(1).trimmed().remove("\"");
1681 					i += rx.matchedLength();
1682 				}
1683 				qmc2ProcessManager->process(qmc2ProcessManager->start(emuCommand, emuArgs, true, emuWorkDir));
1684 			}
1685 		}
1686 	}
1687 
1688 	qmc2DriverName = machineName;
1689 
1690 	if ( foreignEmulator ) {
1691 		qmc2AutoMinimizedWidgets.clear();
1692 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MinimizeOnEmuLaunch", false).toBool() && !qmc2StartEmbedded ) {
1693 			foreach (QWidget *w, qApp->topLevelWidgets()) {
1694 				if ( w->isVisible() ) {
1695 					qmc2AutoMinimizedWidgets[w] = w->windowState();
1696 					w->showMinimized();
1697 				}
1698 			}
1699 		}
1700 		launchForeignID = false;
1701 		return;
1702 	}
1703 
1704 	if ( qmc2MachineList->isDevice(machineName) ) {
1705 		log(QMC2_LOG_FRONTEND, tr("sorry, devices cannot run standalone"));
1706 		return;
1707 	}
1708 
1709 	launchForeignID = false;
1710 	QStringList args;
1711 	QString sectionTitle;
1712 	EmulatorOptions *emuOptions = qmc2EmulatorOptions;
1713 
1714 	EmulatorOptions *demoOpts = 0;
1715 	if ( !qmc2DemoMachine.isEmpty() ) {
1716 		demoOpts = new EmulatorOptions(QMC2_EMULATOR_PREFIX + "Configuration/" + machineName, 0);
1717 		demoOpts->load();
1718 		emuOptions = demoOpts;
1719 	}
1720 
1721 	foreach (sectionTitle, emuOptions->optionsMap.uniqueKeys()) {
1722 		int i;
1723 		for (i = 0; i < emuOptions->optionsMap.value(sectionTitle).count(); i++) {
1724 			EmulatorOption option(emuOptions->optionsMap.value(sectionTitle).at(i));
1725 			QString globalOptionKey(QMC2_EMULATOR_PREFIX + "Configuration/Global/" + option.name);
1726 			bool enforceDefault = qmc2Config->value(QMC2_EMULATOR_PREFIX + "Configuration/Global/EnforceDefault/" + option.name, false).toBool() || qmc2Config->value(QMC2_EMULATOR_PREFIX + "Configuration/" + machineName + "/EnforceDefault/" + option.name, false).toBool();
1727 			switch ( option.type ) {
1728 				case QMC2_EMUOPT_TYPE_INT: {
1729 					int  v = option.value.toInt();
1730 					int dv = option.dvalue.toInt();
1731 					int gv = qmc2Config->value(globalOptionKey, dv).toInt();
1732 					if ( !option.valid )
1733 						v = gv;
1734 					if ( enforceDefault || v != dv )
1735 						args << QString("-%1").arg(option.name) << QString("%1").arg(v);
1736 					break;
1737 				}
1738 
1739 				case QMC2_EMUOPT_TYPE_FLOAT: {
1740 					double  v = option.value.toDouble();
1741 					double dv = option.dvalue.toDouble();
1742 					double gv = qmc2Config->value(globalOptionKey, dv).toDouble();
1743 					if ( !option.valid )
1744 						v = gv;
1745 					if ( enforceDefault || v != dv ) {
1746 						QString val;
1747 						val.setNum(v, 'f', option.decimals);
1748 						args << QString("-%1").arg(option.name) << val;
1749 					}
1750 					break;
1751 				}
1752 
1753 				case QMC2_EMUOPT_TYPE_FLOAT2: {
1754 					QStringList subValues(option.value.split(','));
1755 					QStringList defaultSubValues(option.dvalue.split(','));
1756 					double v1, v2, dv1, dv2;
1757 					v1 = v2 = dv1 = dv2 = 0;
1758 					if ( subValues.count() > 0 )
1759 						v1 = subValues[0].toDouble();
1760 					if ( subValues.count() > 1 )
1761 						v2 = subValues[1].toDouble();
1762 					if ( defaultSubValues.count() > 0 )
1763 						dv1 = defaultSubValues[0].toDouble();
1764 					if ( defaultSubValues.count() > 1 )
1765 						dv2 = defaultSubValues[1].toDouble();
1766 					if ( enforceDefault || v1 != dv1 || v2 != dv2 )
1767 						args << QString("-%1").arg(option.name) << QString("%1,%2").arg(v1).arg(v2);
1768 					break;
1769 				}
1770 
1771 				case QMC2_EMUOPT_TYPE_FLOAT3: {
1772 					QStringList subValues(option.value.split(','));
1773 					QStringList defaultSubValues(option.dvalue.split(','));
1774 					double v1, v2, v3, dv1, dv2, dv3;
1775 					v1 = v2 = v3 = dv1 = dv2 = dv3 = 0;
1776 					if ( subValues.count() > 0 )
1777 						v1 = subValues[0].toDouble();
1778 					if ( subValues.count() > 1 )
1779 						v2 = subValues[1].toDouble();
1780 					if ( subValues.count() > 2 )
1781 						v3 = subValues[2].toDouble();
1782 					if ( defaultSubValues.count() > 0 )
1783 						dv1 = defaultSubValues[0].toDouble();
1784 					if ( defaultSubValues.count() > 1 )
1785 						dv2 = defaultSubValues[1].toDouble();
1786 					if ( defaultSubValues.count() > 2 )
1787 						dv3 = defaultSubValues[2].toDouble();
1788 					if ( enforceDefault || v1 != dv1 || v2 != dv2 || v3 != dv3 )
1789 						args << QString("-%1").arg(option.name) << QString("%1,%2,%3").arg(v1).arg(v2).arg(v3);
1790 					break;
1791 				}
1792 
1793 				case QMC2_EMUOPT_TYPE_BOOL: {
1794 					bool dv = EmulatorOptionDelegate::stringToBool(option.dvalue);
1795 					bool v = EmulatorOptionDelegate::stringToBool(option.value);
1796 					bool gv = qmc2Config->value(globalOptionKey, dv).toBool();
1797 					if ( !option.valid )
1798 						v = gv;
1799 					if ( enforceDefault || v != dv ) {
1800 						if ( v )
1801 							args << QString("-%1").arg(option.name);
1802 						else
1803 							args << QString("-no%1").arg(option.name);
1804 					}
1805 					break;
1806 				}
1807 
1808 				case QMC2_EMUOPT_TYPE_FILE:
1809 				case QMC2_EMUOPT_TYPE_DIRECTORY: {
1810 					QString  v = option.value;
1811 					QString dv = option.dvalue;
1812 					QString gv = qmc2Config->value(globalOptionKey, dv).toString();
1813 					if ( !option.valid )
1814 						v = gv;
1815 #if defined(QMC2_OS_WIN)
1816 					if ( enforceDefault || v != dv )
1817 						args << QString("-%1").arg(option.name) << QDir::toNativeSeparators(QDir::cleanPath(v));
1818 #else
1819 					if ( enforceDefault || v != dv )
1820 						args << QString("-%1").arg(option.name) << QDir::toNativeSeparators(v.replace("~", "$HOME"));
1821 #endif
1822 					break;
1823 				}
1824 
1825 				case QMC2_EMUOPT_TYPE_STRING:
1826 				default: {
1827 					QString  v = option.value;
1828 					QString dv = option.dvalue;
1829 					QString gv = qmc2Config->value(globalOptionKey, dv).toString();
1830 					if ( !option.valid )
1831 						v = gv;
1832 					if ( enforceDefault || v != dv )
1833 						args << QString("-%1").arg(option.name) << v;
1834 					break;
1835 				}
1836 			}
1837 		}
1838 	}
1839 
1840 	QStringList extraOpts;
1841 
1842 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
1843 	if ( qmc2StartEmbedded )
1844 		extraOpts << "enable-window" << "disable-maximize" << "enable-keepaspect" << "enable-rotate" << "disable-ror" << "disable-rol";
1845 #endif
1846 
1847 	if ( qmc2DemoModeDialog && !qmc2DemoMachine.isEmpty() ) {
1848 		args << "-str" << QString::number(qmc2DemoModeDialog->spinBoxSecondsToRun->value());
1849 		extraOpts << qmc2DemoArgs;
1850 	}
1851 
1852 	foreach (QString extraOpt, extraOpts) {
1853 		QStringList optParams(extraOpt.split('-', QString::SkipEmptyParts));
1854 		QString negOpt("-no" + optParams.at(1));
1855 		QString posOpt("-" + optParams.at(1));
1856 		if ( optParams.first() == "enable" ) {
1857 			if ( args.contains(negOpt) )
1858 				args.removeAll(negOpt);
1859 			if ( !args.contains(posOpt) )
1860 				args << posOpt;
1861 		} else {
1862 			if ( args.contains(posOpt) )
1863 				args.removeAll(posOpt);
1864 			if ( !args.contains(negOpt) )
1865 				args << negOpt;
1866 		}
1867 	}
1868 
1869 	if ( qmc2Options->outputNotifiersEnabled() )
1870 		args << "-output" << "console";
1871 
1872 	args << machineName;
1873 
1874 	QStringList softwareLists, softwareNames;
1875 
1876 	if ( qmc2SoftwareList && tabWidgetMachineDetail->currentIndex() == componentInfo->appliedFeatureList().indexOf(QMC2_SOFTWARE_LIST_INDEX) ) {
1877 		QStringList swlArgs(qmc2SoftwareList->arguments(&softwareLists, &softwareNames));
1878 		if ( swlArgs.count() > 1 ) {
1879 			if ( swlArgs.first() == "-snapname" ) {
1880 				args.removeLast();
1881 				args << swlArgs.at(0) << swlArgs.at(1);
1882 				args << machineName;
1883 				for (int a = 2; a < swlArgs.count(); a++)
1884 					args << swlArgs.at(a);
1885 			} else
1886 				args << swlArgs;
1887 		} else
1888 			args << swlArgs;
1889 	} else if ( qmc2DeviceConfigurator && tabWidgetMachineDetail->currentIndex() == componentInfo->appliedFeatureList().indexOf(QMC2_DEVICE_INDEX) ) {
1890 		switch ( qmc2DeviceConfigurator->tabWidgetDeviceSetup->currentIndex() ) {
1891 			case QMC2_DEVSETUP_TAB_FILECHOOSER: {
1892 				QString instance(qmc2DeviceConfigurator->comboBoxDeviceInstanceChooser->currentText());
1893 				QItemSelectionModel *selectionModel = qmc2DeviceConfigurator->treeViewFileChooser->selectionModel();
1894 				QModelIndexList indexList;
1895 				if ( selectionModel )
1896 					indexList = selectionModel->selectedIndexes();
1897 				if ( indexList.count() > 0 && instance != tr("No devices available") ) {
1898 					QList<QTreeWidgetItem *> allSlotItems;
1899 					for (int i = 0; i < qmc2DeviceConfigurator->treeWidgetSlotOptions->topLevelItemCount(); i++) {
1900 						QTreeWidgetItem *item = qmc2DeviceConfigurator->treeWidgetSlotOptions->topLevelItem(i);
1901 						allSlotItems << item;
1902 						//qmc2DeviceConfigurator->insertChildItems(item, allSlotItems);
1903 						// FIXME
1904 					}
1905 					foreach (QTreeWidgetItem *item, allSlotItems) {
1906 						QString slotName(item->text(QMC2_SLOTCONFIG_COLUMN_SLOT));
1907 						if ( !slotName.isEmpty() ) {
1908 							QComboBox *cb = (QComboBox *)qmc2DeviceConfigurator->treeWidgetSlotOptions->itemWidget(item, QMC2_SLOTCONFIG_COLUMN_OPTION);
1909 							if ( cb ) {
1910 								int defaultIndex = -1;
1911 								QString biosChoice;
1912 								QComboBox *cbBIOS = (QComboBox *)qmc2DeviceConfigurator->treeWidgetSlotOptions->itemWidget(item, QMC2_SLOTCONFIG_COLUMN_BIOS);
1913 								if ( cbBIOS ) {
1914 									QStringList biosInfoList(cbBIOS->currentText().split(' ', QString::SkipEmptyParts));
1915 									if ( biosInfoList.count() == 3 && biosInfoList[2] == tr("default") )
1916 										biosChoice = tr("N/A");
1917 									else
1918 										biosChoice = biosInfoList.first();
1919 									if ( biosChoice != tr("N/A") )
1920 										biosChoice = ",bios=" + biosChoice;
1921 									else
1922 										biosChoice.clear();
1923 								}
1924 								if ( qmc2DeviceConfigurator->slotPreselectionMap.contains(cb) )
1925 									defaultIndex = qmc2DeviceConfigurator->slotPreselectionMap.value(cb);
1926 								else if ( qmc2DeviceConfigurator->nestedSlotPreselectionMap.contains(cb) )
1927 									defaultIndex = qmc2DeviceConfigurator->nestedSlotPreselectionMap.value(cb);
1928 								QString slotDeviceString(QString("%1%2").arg(cb->currentText().split(' ', QString::SkipEmptyParts).first()).arg(biosChoice));
1929 								if ( cb->currentIndex() > 0 && defaultIndex == 0 )
1930 									args << QString("-%1").arg(slotName) << slotDeviceString;
1931 								else if ( cb->currentIndex() == 0 && defaultIndex > 0 )
1932 									args << QString("-%1").arg(slotName) << "\"\"";
1933 								else if ( cb->currentIndex() > 0 && defaultIndex > 0 && cb->currentIndex() != defaultIndex )
1934 									args << QString("-%1").arg(slotName) << slotDeviceString;
1935 								else if ( !biosChoice.isEmpty() )
1936 									args << QString("-%1").arg(slotName) << slotDeviceString;
1937 							}
1938 						}
1939 					}
1940 					bool doMapping = true;
1941 					if ( qmc2DeviceConfigurator->toolButtonChooserMergeMaps->isChecked() ) {
1942 						QString configName(qmc2DeviceConfigurator->lineEditConfigurationName->text());
1943 						QPair<QStringList, QStringList> valuePair = qmc2DeviceConfigurator->configurationMap.value(configName);
1944 						for (int i = 0; i < valuePair.first.count(); i++) {
1945 							if ( valuePair.first.at(i) == instance ) {
1946 								QString file(qmc2DeviceConfigurator->fileModel()->absolutePath(indexList.first()));
1947 #if defined(QMC2_OS_WIN)
1948 								args << QString("-%1").arg(instance) << file.replace('/', '\\');
1949 #else
1950 								args << QString("-%1").arg(instance) << file.replace("~", "$HOME");
1951 #endif
1952 								doMapping = false;
1953 							} else {
1954 #if defined(QMC2_OS_WIN)
1955 								args << QString("-%1").arg(valuePair.first[i]) << valuePair.second[i].replace('/', '\\');
1956 #else
1957 								args << QString("-%1").arg(valuePair.first[i]) << valuePair.second[i].replace("~", "$HOME");
1958 #endif
1959 							}
1960 						}
1961 					}
1962 					if ( doMapping ) {
1963 						QString file(qmc2DeviceConfigurator->fileModel()->absolutePath(indexList.first()));
1964 #if defined(QMC2_OS_WIN)
1965 						args << QString("-%1").arg(instance) << file.replace('/', '\\');
1966 #else
1967 						args << QString("-%1").arg(instance) << file.replace("~", "$HOME");
1968 #endif
1969 					}
1970 				}
1971 			}
1972 			break;
1973 
1974 		default: {
1975 				QString configName(qmc2DeviceConfigurator->lineEditConfigurationName->text());
1976 				if ( configName != tr("Default configuration") ) {
1977 					if ( qmc2DeviceConfigurator->configurationMap.contains(configName) ) {
1978 						QPair<QStringList, QStringList> valuePair = qmc2DeviceConfigurator->slotMap[configName];
1979 						for (int i = 0; i < valuePair.first.count(); i++) {
1980 							QString slotName(valuePair.first.at(i));
1981 							QString slotOption(valuePair.second.at(i));
1982 							QTreeWidgetItem *item;
1983 							//QComboBox *cb = qmc2DeviceConfigurator->comboBoxByName(slotName, &item);
1984 							QComboBox *cb = 0; // FIXME
1985 							if ( cb ) {
1986 								int defaultIndex = -1;
1987 								QString biosChoice;
1988 								if ( item ) {
1989 									QComboBox *cbBIOS = (QComboBox *)qmc2DeviceConfigurator->treeWidgetSlotOptions->itemWidget(item, QMC2_SLOTCONFIG_COLUMN_BIOS);
1990 									if ( cbBIOS ) {
1991 										QStringList biosInfoList(cbBIOS->currentText().split(' ', QString::SkipEmptyParts));
1992 										if ( biosInfoList.count() == 3 && biosInfoList.at(2) == tr("default") )
1993 											biosChoice = tr("N/A");
1994 										else
1995 											biosChoice = biosInfoList.first();
1996 										if ( biosChoice != tr("N/A") )
1997 											biosChoice = ",bios=" + biosChoice;
1998 										else
1999 											biosChoice.clear();
2000 									}
2001 								}
2002 								if ( qmc2DeviceConfigurator->slotPreselectionMap.contains(cb) )
2003 									defaultIndex = qmc2DeviceConfigurator->slotPreselectionMap.value(cb);
2004 								else if ( qmc2DeviceConfigurator->nestedSlotPreselectionMap.contains(cb) )
2005 									defaultIndex = qmc2DeviceConfigurator->nestedSlotPreselectionMap.value(cb);
2006 								QString slotDeviceString(QString("%1%2").arg(cb->currentText().split(' ', QString::SkipEmptyParts).first()).arg(biosChoice));
2007 								if ( cb->currentIndex() > 0 && defaultIndex == 0 )
2008 									args << QString("-%1").arg(slotName) << slotDeviceString;
2009 								else if ( cb->currentIndex() == 0 && defaultIndex > 0 )
2010 									args << QString("-%1").arg(slotName) << "\"\"";
2011 								else if ( cb->currentIndex() > 0 && defaultIndex > 0 && cb->currentIndex() != defaultIndex )
2012 									args << QString("-%1").arg(slotName) << slotDeviceString;
2013 								else if ( !biosChoice.isEmpty() )
2014 									args << QString("-%1").arg(slotName) << slotDeviceString;
2015 							}
2016 						}
2017 						valuePair = qmc2DeviceConfigurator->configurationMap[configName];
2018 						for (int i = 0; i < valuePair.first.count(); i++)
2019 #if defined(QMC2_OS_WIN)
2020 							args << QString("-%1").arg(valuePair.first.at(i)) << valuePair.second[i].replace('/', '\\');
2021 #else
2022 							args << QString("-%1").arg(valuePair.first.at(i)) << valuePair.second[i].replace("~", "$HOME");
2023 #endif
2024 					}
2025 				} else {
2026 					QList<QTreeWidgetItem *> allSlotItems;
2027 					for (int i = 0; i < qmc2DeviceConfigurator->treeWidgetSlotOptions->topLevelItemCount(); i++) {
2028 						QTreeWidgetItem *item = qmc2DeviceConfigurator->treeWidgetSlotOptions->topLevelItem(i);
2029 						allSlotItems << item;
2030 						//qmc2DeviceConfigurator->insertChildItems(item, allSlotItems);
2031 						// FIXME
2032 					}
2033 					foreach (QTreeWidgetItem *item, allSlotItems) {
2034 						QString slotName(item->text(QMC2_SLOTCONFIG_COLUMN_SLOT));
2035 						if ( !slotName.isEmpty() ) {
2036 							QComboBox *cb = (QComboBox *)qmc2DeviceConfigurator->treeWidgetSlotOptions->itemWidget(item, QMC2_SLOTCONFIG_COLUMN_OPTION);
2037 							if ( cb ) {
2038 								int defaultIndex = -1;
2039 								QString biosChoice;
2040 								QComboBox *cbBIOS = (QComboBox *)qmc2DeviceConfigurator->treeWidgetSlotOptions->itemWidget(item, QMC2_SLOTCONFIG_COLUMN_BIOS);
2041 								if ( cbBIOS ) {
2042 									QStringList biosInfoList(cbBIOS->currentText().split(' ', QString::SkipEmptyParts));
2043 									if ( biosInfoList.count() == 3 && biosInfoList.at(2) == tr("default") )
2044 										biosChoice = tr("N/A");
2045 									else
2046 										biosChoice = biosInfoList.first();
2047 									if ( biosChoice != tr("N/A") )
2048 										biosChoice = ",bios=" + biosChoice;
2049 									else
2050 										biosChoice.clear();
2051 								}
2052 								if ( qmc2DeviceConfigurator->slotPreselectionMap.contains(cb) )
2053 									defaultIndex = qmc2DeviceConfigurator->slotPreselectionMap.value(cb);
2054 								else if ( qmc2DeviceConfigurator->nestedSlotPreselectionMap.contains(cb) )
2055 									defaultIndex = qmc2DeviceConfigurator->nestedSlotPreselectionMap.value(cb);
2056 								QString slotDeviceString(QString("%1%2").arg(cb->currentText().split(' ', QString::SkipEmptyParts).first()).arg(biosChoice));
2057 								if ( cb->currentIndex() > 0 && defaultIndex == 0 )
2058 									args << QString("-%1").arg(slotName) << slotDeviceString;
2059 								else if ( cb->currentIndex() == 0 && defaultIndex > 0 )
2060 									args << QString("-%1").arg(slotName) << "\"\"";
2061 								else if ( cb->currentIndex() > 0 && defaultIndex > 0 && cb->currentIndex() != defaultIndex )
2062 									args << QString("-%1").arg(slotName) << slotDeviceString;
2063 								else if ( !biosChoice.isEmpty() )
2064 									args << QString("-%1").arg(slotName) << slotDeviceString;
2065 							}
2066 						}
2067 					}
2068 				}
2069 			}
2070 			break;
2071 		}
2072 	}
2073 
2074 	QString command(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/ExecutableFile", QString()).toString());
2075 	QString workingDirectory(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/WorkingDirectory", QString()).toString());
2076 	QStringList argsResolved(Settings::stResolve(args));
2077 
2078 	// start machine
2079 	qmc2ProcessManager->process(qmc2ProcessManager->start(command, argsResolved, true, workingDirectory, softwareLists, softwareNames));
2080 
2081 	qmc2AutoMinimizedWidgets.clear();
2082 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MinimizeOnEmuLaunch", false).toBool() && !qmc2StartEmbedded ) {
2083 		foreach (QWidget *w, qApp->topLevelWidgets()) {
2084 			if ( w->isVisible() ) {
2085 				qmc2AutoMinimizedWidgets[w] = w->windowState();
2086 				w->showMinimized();
2087 			}
2088 		}
2089 	}
2090 
2091 	if ( qmc2DemoMachine.isEmpty() ) {
2092 		// add machine to played list
2093 		listWidgetPlayed->blockSignals(true);
2094 		QTreeWidgetItem *mlItem = qmc2MachineListItemHash.value(machineName);
2095 		QList<QListWidgetItem *> matches = listWidgetPlayed->findItems(mlItem->text(QMC2_MACHINELIST_COLUMN_MACHINE), Qt::MatchExactly);
2096 		QListWidgetItem *playedItem;
2097 		if ( matches.count() > 0 )
2098 			playedItem = listWidgetPlayed->takeItem(listWidgetPlayed->row(matches[0]));
2099 		else {
2100 			playedItem = new QListWidgetItem();
2101 			playedItem->setText(mlItem->text(QMC2_MACHINELIST_COLUMN_MACHINE));
2102 			playedItem->setWhatsThis(mlItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2103 		}
2104 		listWidgetPlayed->insertItem(0, playedItem);
2105 		listWidgetPlayed->setCurrentItem(playedItem);
2106 		listWidgetPlayed->blockSignals(false);
2107 	} else {
2108 		if ( qmc2DemoModeDialog ) {
2109 			QProcess *proc = qmc2ProcessManager->process(qmc2ProcessManager->procCount - 1);
2110 			if ( proc ) {
2111 				connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), qmc2DemoModeDialog, SLOT(emuFinished(int, QProcess::ExitStatus)));
2112 				connect(proc, SIGNAL(started()), qmc2DemoModeDialog, SLOT(emuStarted()));
2113 			}
2114 			if ( demoOpts )
2115 				delete demoOpts;
2116 		}
2117 	}
2118 }
2119 
on_vSplitter_splitterMoved(int pos,int index)2120 void MainWindow::on_vSplitter_splitterMoved(int pos, int index)
2121 {
2122 	if ( qmc2SystemNotesEditor ) {
2123 		qmc2SystemNotesEditor->move(0, 0);
2124 		qmc2SystemNotesEditor->resize(qmc2SystemNotesEditor->parentWidget()->size());
2125 	}
2126 
2127 	QList<int> splitterSizes = vSplitter->sizes();
2128 	switch ( stackedWidgetSpecial->currentIndex() ) {
2129 		case QMC2_SPECIAL_SOFTWARE_PAGE:
2130 			vSplitterSizesSoftwareDetail = splitterSizes;
2131 			break;
2132 		case QMC2_SPECIAL_DEFAULT_PAGE:
2133 		default:
2134 			vSplitterSizes = splitterSizes;
2135 			break;
2136 	}
2137 }
2138 
on_hSplitter_splitterMoved(int pos,int index)2139 void MainWindow::on_hSplitter_splitterMoved(int pos, int index)
2140 {
2141 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
2142 	if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) != tabWidgetMachineList->currentIndex() || (tabWidgetMachineList->indexOf(tabEmbeddedEmus) == tabWidgetMachineList->currentIndex() && !toolButtonEmbedderMaximizeToggle->isChecked()) ) {
2143 		hSplitterSizes = hSplitter->sizes();
2144 	} else if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) == tabWidgetMachineList->currentIndex() && toolButtonEmbedderMaximizeToggle->isChecked() ) {
2145 		toolButtonEmbedderMaximizeToggle->setChecked(false);
2146 		menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
2147 		statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
2148 		toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
2149 	}
2150 #endif
2151 
2152 	// show / hide game status indicator
2153 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicator").toBool() ) {
2154 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicatorOnlyWhenRequired").toBool() ) {
2155 			if ( pos == 0 ) {
2156 				if ( !labelMachineStatus->isVisible() )
2157 					labelMachineStatus->setVisible(true);
2158 			} else {
2159 				if ( labelMachineStatus->isVisible() )
2160 					labelMachineStatus->setVisible(false);
2161 			}
2162 		} else {
2163 			if ( !labelMachineStatus->isVisible() )
2164 				labelMachineStatus->setVisible(true);
2165 		}
2166 	} else
2167 		if ( labelMachineStatus->isVisible() )
2168 			labelMachineStatus->setVisible(false);
2169 
2170 	if ( qmc2SystemNotesEditor ) {
2171 		qmc2SystemNotesEditor->move(0, 0);
2172 		qmc2SystemNotesEditor->resize(qmc2SystemNotesEditor->parentWidget()->size());
2173 	}
2174 }
2175 
on_actionToFavorites_triggered(bool)2176 void MainWindow::on_actionToFavorites_triggered(bool)
2177 {
2178 	if ( !qmc2CurrentItem )
2179 		return;
2180 
2181 	QString itemText(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE));
2182 	QString itemName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2183 
2184 	if ( itemText == MachineList::trWaitingForData )
2185 		return;
2186 
2187 	QList<QListWidgetItem *> matches(listWidgetFavorites->findItems(itemText, Qt::MatchExactly));
2188 	if ( matches.count() <= 0 ) {
2189 		QListWidgetItem *item = new QListWidgetItem(listWidgetFavorites);
2190 		item->setText(itemText);
2191 		item->setWhatsThis(itemName);
2192 		listWidgetFavorites->sortItems();
2193 	}
2194 }
2195 
on_actionReload_triggered(bool)2196 void MainWindow::on_actionReload_triggered(bool)
2197 {
2198 	if ( !qmc2StartingUp ) {
2199 		if ( qmc2FilterActive ) {
2200 			log(QMC2_LOG_FRONTEND, tr("please wait for ROM state filter to finish and try again"));
2201 			return;
2202 		}
2203 		if ( qmc2VerifyActive || qmc2VerifyTaggedActive ) {
2204 			log(QMC2_LOG_FRONTEND, tr("please wait for ROM verification to finish and try again"));
2205 			return;
2206 		}
2207 		if ( qmc2ImageCheckActive ) {
2208 			log(QMC2_LOG_FRONTEND, tr("please wait for image check to finish and try again"));
2209 			return;
2210 		}
2211 		if ( qmc2SampleCheckActive ) {
2212 			log(QMC2_LOG_FRONTEND, tr("please wait for sample check to finish and try again"));
2213 			return;
2214 		}
2215 		if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active() ) {
2216 			log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2217 			return;
2218 		}
2219 		if ( qmc2SoftwareROMAlyzer && qmc2SoftwareROMAlyzer->active() ) {
2220 			log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2221 			return;
2222 		}
2223 	} else if ( QMC2_CLI_OPT_CLEAR_ALL_CACHES ) {
2224 		qmc2ForceCacheRefresh = true;
2225 		on_actionClearAllEmulatorCaches_triggered(true);
2226 		qmc2ForceCacheRefresh = false;
2227 	}
2228 	if ( qmc2ReloadActive )
2229 		log(QMC2_LOG_FRONTEND, tr("machine list reload is already active"));
2230 	else {
2231 		qmc2LoadingInterrupted = false;
2232 		qmc2MachineList->enableWidgets(false);
2233 		if ( !qmc2LoadingInterrupted && (qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMameHistoryDat", false).toBool() || qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMessSysinfoDat", false).toBool()) )
2234 			loadMachineInfoDB();
2235 		if ( !qmc2LoadingInterrupted && (qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMameInfoDat", false).toBool() || qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMessInfoDat", false).toBool()) )
2236 			loadEmuInfoDB();
2237 		if ( !qmc2LoadingInterrupted && qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProcessSoftwareInfoDB", false).toBool() )
2238 			loadSoftwareInfoDB();
2239 		if ( !qmc2StartingUp && qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/SaveMachineSelection", true).toBool() ) {
2240 			if ( qmc2CurrentItem ) {
2241 				log(QMC2_LOG_FRONTEND, tr("saving machine selection"));
2242 				qmc2Config->setValue(QMC2_EMULATOR_PREFIX + "SelectedMachine", qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2243 			} else
2244 				qmc2Config->remove(QMC2_EMULATOR_PREFIX + "SelectedMachine");
2245 		}
2246 		if ( !qmc2LoadingInterrupted )
2247 			qmc2MachineList->load();
2248 		else
2249 			QTimer::singleShot(0, qmc2MachineList, SLOT(enableWidgets()));
2250 	}
2251 	static bool initialCall = true;
2252 	if ( initialCall )
2253 		QTimer::singleShot(0, this, SLOT(checkRomPath()));
2254 	initialCall = false;
2255 }
2256 
on_actionExitStop_triggered(bool)2257 void MainWindow::on_actionExitStop_triggered(bool)
2258 {
2259 	close();
2260 }
2261 
on_actionCheckCurrentROM_triggered(bool)2262 void MainWindow::on_actionCheckCurrentROM_triggered(bool)
2263 {
2264 	if ( qmc2FilterActive ) {
2265 		log(QMC2_LOG_FRONTEND, tr("please wait for ROM state filter to finish and try again"));
2266 	} else if ( qmc2VerifyActive ) {
2267 		log(QMC2_LOG_FRONTEND, tr("ROM verification already active"));
2268 	} else if ( qmc2ReloadActive ) {
2269 		log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2270 	} else if ( qmc2ImageCheckActive ) {
2271 		log(QMC2_LOG_FRONTEND, tr("please wait for image check to finish and try again"));
2272 	} else if ( qmc2SampleCheckActive ) {
2273 		log(QMC2_LOG_FRONTEND, tr("please wait for sample check to finish and try again"));
2274 	} else if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active() ) {
2275 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2276 	} else if ( qmc2SoftwareROMAlyzer && qmc2SoftwareROMAlyzer->active() ) {
2277 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2278 	} else
2279 		qmc2MachineList->verify(true);
2280 }
2281 
on_actionCheckROMs_triggered(bool)2282 void MainWindow::on_actionCheckROMs_triggered(bool)
2283 {
2284 	if ( qmc2FilterActive )
2285 		log(QMC2_LOG_FRONTEND, tr("please wait for ROM state filter to finish and try again"));
2286 	else if ( qmc2VerifyActive || qmc2VerifyTaggedActive )
2287 		log(QMC2_LOG_FRONTEND, tr("ROM verification already active"));
2288 	else if ( qmc2ReloadActive )
2289 		log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2290 	else if ( qmc2ImageCheckActive )
2291 		log(QMC2_LOG_FRONTEND, tr("please wait for image check to finish and try again"));
2292 	else if ( qmc2SampleCheckActive )
2293 		log(QMC2_LOG_FRONTEND, tr("please wait for sample check to finish and try again"));
2294 	else if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active() )
2295 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2296 	else if ( qmc2SoftwareROMAlyzer && qmc2SoftwareROMAlyzer->active() )
2297 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2298 	else {
2299 		if ( !qmc2MachineList->autoRomCheck ) {
2300 			switch ( QMessageBox::question(this,
2301 						tr("Confirm"),
2302 						tr("The ROM verification process may be very time-consuming.\nIt will overwrite existing cached data.\n\nDo you really want to check all ROM states now?"),
2303 						QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
2304 				case QMessageBox::Yes:
2305 					qmc2MachineList->verify();
2306 					break;
2307 
2308 				default:
2309 					break;
2310 			}
2311 		} else {
2312 			if ( qmc2AutomaticReload )
2313 				qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("automatic ROM check triggered"));
2314 			qmc2MachineList->verify();
2315 		}
2316 		qmc2MachineList->autoRomCheck = false;
2317 		qmc2AutomaticReload = false;
2318 	}
2319 }
2320 
on_actionExportROMStatus_triggered(bool)2321 void MainWindow::on_actionExportROMStatus_triggered(bool)
2322 {
2323 	if ( !qmc2ROMStatusExporter )
2324 		qmc2ROMStatusExporter = new ROMStatusExporter(this);
2325 
2326 	qmc2ROMStatusExporter->adjustIconSizes();
2327 
2328 	if ( qmc2ROMStatusExporter->isHidden() )
2329 		qmc2ROMStatusExporter->show();
2330 	else if ( qmc2ROMStatusExporter->isMinimized() )
2331 		qmc2ROMStatusExporter->showNormal();
2332 
2333 	QTimer::singleShot(0, qmc2ROMStatusExporter, SLOT(raise()));
2334 }
2335 
on_actionDemoMode_triggered(bool)2336 void MainWindow::on_actionDemoMode_triggered(bool)
2337 {
2338 	if ( !qmc2DemoModeDialog )
2339 		qmc2DemoModeDialog = new DemoModeDialog(this);
2340 
2341 	qmc2DemoModeDialog->adjustIconSizes();
2342 
2343 	if ( qmc2DemoModeDialog->isHidden() )
2344 		qmc2DemoModeDialog->show();
2345 	else if ( qmc2DemoModeDialog->isMinimized() )
2346 		qmc2DemoModeDialog->showNormal();
2347 
2348 	QTimer::singleShot(0, qmc2DemoModeDialog, SLOT(raise()));
2349 }
2350 
on_actionNewBrowserWindow_triggered(bool)2351 void MainWindow::on_actionNewBrowserWindow_triggered(bool)
2352 {
2353 	viewHtml();
2354 }
2355 
viewHtml(QString filePath)2356 void MainWindow::viewHtml(QString filePath)
2357 {
2358 	MiniWebBrowser *webBrowser = new MiniWebBrowser(0);
2359 	webBrowser->setAttribute(Qt::WA_DeleteOnClose);
2360 	if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "WebBrowser/Geometry") )
2361 		webBrowser->restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "WebBrowser/Geometry").toByteArray());
2362 	else {
2363 		webBrowser->adjustSize();
2364 		webBrowser->move(QApplication::desktop()->screen()->rect().center() - webBrowser->rect().center());
2365 	}
2366 	connect(webBrowser->webViewBrowser->page(), SIGNAL(windowCloseRequested()), webBrowser, SLOT(close()));
2367 	if ( !filePath.isEmpty() ) {
2368 		QFileInfo fi(filePath);
2369 		if ( fi.isReadable() ) {
2370 #if defined(QMC2_OS_WIN)
2371 			webBrowser->webViewBrowser->load("file:///" + fi.canonicalFilePath());
2372 #else
2373 			webBrowser->webViewBrowser->load("file://" + fi.canonicalFilePath());
2374 #endif
2375 		} else
2376 			qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("ERROR: can't load HTML file '%1'").arg(filePath));
2377 	}
2378 	webBrowser->show();
2379 }
2380 
on_actionNewPdfViewer_triggered(bool)2381 void MainWindow::on_actionNewPdfViewer_triggered(bool)
2382 {
2383 	viewPdf();
2384 }
2385 
on_actionNewFilteredView_triggered(bool)2386 void MainWindow::on_actionNewFilteredView_triggered(bool)
2387 {
2388 	MachineListViewer *mlv = new MachineListViewer;
2389 	machineListViewers.append(mlv);
2390 	connect(mlv, SIGNAL(selectionChanged(const QString &)), this, SLOT(machineListViewer_selectionChanged(const QString &)));
2391 	connect(mlv, SIGNAL(tagChanged(const QString &, bool)), this, SLOT(machineListViewer_tagChanged(const QString &, bool)));
2392 	connect(this, SIGNAL(selectionChanged(const QString &)), mlv, SLOT(mainSelectionChanged(const QString &)));
2393 	mlv->show();
2394 }
2395 
viewPdf(QString filePath)2396 void MainWindow::viewPdf(QString filePath)
2397 {
2398 	QString htmlPath = qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/DataDirectory").toString() + "/js/pdfjs/web/viewer.html";
2399 	QFileInfo fi(htmlPath);
2400 	if ( fi.isReadable() ) {
2401 		MiniWebBrowser *webBrowser = new MiniWebBrowser(0, true);
2402 		webBrowser->setAttribute(Qt::WA_DeleteOnClose);
2403 		if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "PdfViewer/Geometry") )
2404 			webBrowser->restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "PdfViewer/Geometry").toByteArray());
2405 		else {
2406 			webBrowser->adjustSize();
2407 			webBrowser->move(QApplication::desktop()->screen()->rect().center() - webBrowser->rect().center());
2408 		}
2409 		connect(webBrowser->webViewBrowser->page(), SIGNAL(windowCloseRequested()), webBrowser, SLOT(close()));
2410 		if ( !filePath.isEmpty() ) {
2411 #if defined(QMC2_OS_WIN)
2412 			webBrowser->webViewBrowser->load("file:///" + fi.canonicalFilePath() + QString("?file=file:///%1").arg(filePath));
2413 #else
2414 			webBrowser->webViewBrowser->load("file://" + fi.canonicalFilePath() + QString("?file=file://%1").arg(filePath));
2415 #endif
2416 		} else {
2417 #if defined(QMC2_OS_WIN)
2418 			webBrowser->webViewBrowser->load("file:///" + fi.canonicalFilePath() + QString("?file="));
2419 #else
2420 			webBrowser->webViewBrowser->load("file://" + fi.canonicalFilePath() + QString("?file="));
2421 #endif
2422 		}
2423 		webBrowser->show();
2424 	} else
2425 		qmc2MainWindow->log(QMC2_LOG_FRONTEND, tr("ERROR: can't load PDF viewer from '%1'").arg(htmlPath));
2426 }
2427 
on_actionCheckSamples_triggered(bool)2428 void MainWindow::on_actionCheckSamples_triggered(bool)
2429 {
2430 	if ( !qmc2SampleChecker )
2431 		qmc2SampleChecker = new SampleChecker(this);
2432 
2433 	if ( qmc2SampleChecker->isHidden() )
2434 		qmc2SampleChecker->show();
2435 	else if ( qmc2SampleChecker->isMinimized() )
2436 		qmc2SampleChecker->showNormal();
2437 
2438 	QTimer::singleShot(0, qmc2SampleChecker, SLOT(raise()));
2439 }
2440 
on_actionCheckImagesAndIcons_triggered(bool)2441 void MainWindow::on_actionCheckImagesAndIcons_triggered(bool)
2442 {
2443 	if ( !qmc2ImageChecker )
2444 		qmc2ImageChecker = new ImageChecker(this);
2445 
2446 	if ( qmc2ImageChecker->isHidden() )
2447 		qmc2ImageChecker->show();
2448 	else if ( qmc2ImageChecker->isMinimized() )
2449 		qmc2ImageChecker->showNormal();
2450 
2451 	QTimer::singleShot(0, qmc2ImageChecker, SLOT(raise()));
2452 }
2453 
on_actionSystemROMAlyzer_triggered(bool)2454 void MainWindow::on_actionSystemROMAlyzer_triggered(bool)
2455 {
2456 	if ( !qmc2SystemROMAlyzer )
2457 		qmc2SystemROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SYSTEM);
2458 
2459 	if ( !qmc2SystemROMAlyzer->active() )
2460 		qmc2SystemROMAlyzer->lineEditSets->setText("*");
2461 
2462 	if ( qmc2SystemROMAlyzer->isHidden() )
2463 		qmc2SystemROMAlyzer->show();
2464 	else if ( qmc2SystemROMAlyzer->isMinimized() )
2465 		qmc2SystemROMAlyzer->showNormal();
2466 
2467 	QTimer::singleShot(0, qmc2SystemROMAlyzer, SLOT(raise()));
2468 }
2469 
on_actionSoftwareROMAlyzer_triggered(bool)2470 void MainWindow::on_actionSoftwareROMAlyzer_triggered(bool)
2471 {
2472 	if ( !swlDb ) {
2473 		swlDb = new SoftwareListXmlDatabaseManager(qmc2MainWindow);
2474 		swlDb->setSyncMode(QMC2_DB_SYNC_MODE_OFF);
2475 		swlDb->setJournalMode(QMC2_DB_JOURNAL_MODE_MEMORY);
2476 	}
2477 
2478 	if ( !qmc2SoftwareROMAlyzer )
2479 		qmc2SoftwareROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SOFTWARE);
2480 
2481 	if ( !qmc2SoftwareROMAlyzer->active() ) {
2482 		qmc2SoftwareROMAlyzer->lineEditSoftwareLists->setText("*");
2483 		qmc2SoftwareROMAlyzer->lineEditSets->setText("*");
2484 	}
2485 
2486 	if ( qmc2SoftwareROMAlyzer->isHidden() )
2487 		qmc2SoftwareROMAlyzer->show();
2488 	else if ( qmc2SoftwareROMAlyzer->isMinimized() )
2489 		qmc2SoftwareROMAlyzer->showNormal();
2490 
2491 	QTimer::singleShot(0, qmc2SoftwareROMAlyzer, SLOT(raise()));
2492 }
2493 
on_actionRunRomTool_triggered(bool)2494 void MainWindow::on_actionRunRomTool_triggered(bool)
2495 {
2496 	if ( !qmc2CurrentItem )
2497 		return;
2498 
2499 	if ( qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
2500 		return;
2501 
2502 	QString command(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Tools/RomTool", QString()).toString());
2503 	QStringList args(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Tools/RomToolArguments", QString()).toString().split(' '));
2504 	QString wd(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Tools/RomToolWorkingDirectory", QString()).toString());
2505 	QString machineId(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2506 	QString gameDescription(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE));
2507 	QStringList newArgs;
2508 	foreach (QString argument, args)
2509 		newArgs << argument.replace("$ID$", machineId).replace("$DESCRIPTION$", gameDescription);
2510 	ToolExecutor romTool(this, command, newArgs, wd);
2511 	romTool.exec();
2512 }
2513 
on_actionAnalyseCurrentROM_triggered(bool)2514 void MainWindow::on_actionAnalyseCurrentROM_triggered(bool)
2515 {
2516 	if ( !qmc2CurrentItem )
2517 		return;
2518 
2519 	if ( qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
2520 		return;
2521 
2522 	if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active() ) {
2523 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current analysis and try again"));
2524 		return;
2525 	}
2526 
2527 	if ( !qmc2SystemROMAlyzer )
2528 		qmc2SystemROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SYSTEM);
2529 
2530 	qmc2SystemROMAlyzer->lineEditSets->setText(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2531 
2532 	if ( qmc2SystemROMAlyzer->isHidden() )
2533 		qmc2SystemROMAlyzer->show();
2534 	else if ( qmc2SystemROMAlyzer->isMinimized() )
2535 		qmc2SystemROMAlyzer->showNormal();
2536 
2537 	if ( qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabAnalyzer && qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabLog )
2538 		qmc2SystemROMAlyzer->tabWidgetAnalysis->setCurrentWidget(qmc2SystemROMAlyzer->tabAnalyzer);
2539 
2540 	QTimer::singleShot(0, qmc2SystemROMAlyzer, SLOT(raise()));
2541 	QTimer::singleShot(0, qmc2SystemROMAlyzer->pushButtonAnalyze, SLOT(click()));
2542 }
2543 
actionRebuildRom_triggered(bool)2544 void MainWindow::actionRebuildRom_triggered(bool)
2545 {
2546 	if ( !qmc2CurrentItem )
2547 		return;
2548 
2549 	if ( qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
2550 		return;
2551 
2552 	if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->rebuilderActive() ) {
2553 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current rebuild and try again"));
2554 		return;
2555 	}
2556 
2557 	bool initial = false;
2558 	if ( !qmc2SystemROMAlyzer ) {
2559 		qmc2SystemROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SYSTEM);
2560 		initial = true;
2561 	}
2562 
2563 	if ( qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabCollectionRebuilder )
2564 		qmc2SystemROMAlyzer->tabWidgetAnalysis->setCurrentWidget(qmc2SystemROMAlyzer->tabCollectionRebuilder);
2565 
2566 	if ( qmc2SystemROMAlyzer->isHidden() )
2567 		qmc2SystemROMAlyzer->show();
2568 	else if ( qmc2SystemROMAlyzer->isMinimized() )
2569 		qmc2SystemROMAlyzer->showNormal();
2570 
2571 	QTimer::singleShot(0, qmc2SystemROMAlyzer, SLOT(raise()));
2572 
2573 	CollectionRebuilder *cr = qmc2SystemROMAlyzer->collectionRebuilder();
2574 	if ( cr ) {
2575 		cr->comboBoxXmlSource->setCurrentIndex(0);
2576 		cr->setIgnoreCheckpoint(true);
2577 		cr->checkBoxFilterExpression->setChecked(true);
2578 		cr->comboBoxFilterSyntax->setCurrentIndex(4);
2579 		cr->comboBoxFilterType->setCurrentIndex(0);
2580 		cr->toolButtonExactMatch->setChecked(true);
2581 		cr->checkBoxFilterStates->setChecked(false);
2582 		cr->lineEditFilterExpression->setText(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
2583 		if ( !initial )
2584 			cr->plainTextEditLog->clear();
2585 		QTimer::singleShot(0, cr->pushButtonStartStop, SLOT(click()));
2586 	}
2587 }
2588 
update_rebuildRomActions_visibility()2589 void MainWindow::update_rebuildRomActions_visibility()
2590 {
2591 	bool enable = false;
2592 	if ( qmc2SystemROMAlyzer )
2593 		enable = (qmc2SystemROMAlyzer->groupBoxCheckSumDatabase->isChecked() && qmc2SystemROMAlyzer->groupBoxSetRewriter->isChecked());
2594 	else
2595 		enable = (qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMAlyzer/EnableCheckSumDb", false).toBool() && qmc2Config->value(QMC2_FRONTEND_PREFIX + "ROMAlyzer/EnableSetRewriter", false).toBool());
2596 	foreach (QAction *a, rebuildRomActions)
2597 		a->setVisible(enable);
2598 }
2599 
on_actionClearImageCache_triggered(bool)2600 void MainWindow::on_actionClearImageCache_triggered(bool)
2601 {
2602 	qmc2ImagePixmapCache.clear();
2603 	log(QMC2_LOG_FRONTEND, tr("image cache cleared"));
2604 }
2605 
on_actionClearIconCache_triggered(bool)2606 void MainWindow::on_actionClearIconCache_triggered(bool)
2607 {
2608 	qmc2IconHash.clear();
2609 	qmc2IconsPreloaded = false;
2610 #if defined(QMC2_LIBARCHIVE_ENABLED)
2611 	if ( QMC2_ICON_FILETYPE_ARCHIVE )
2612 		foreach (ArchiveFile *archiveFile, qmc2IconArchiveMap)
2613 			archiveFile->reopen();
2614 #endif
2615 	log(QMC2_LOG_FRONTEND, tr("icon cache cleared"));
2616 }
2617 
on_actionClearProjectMESSCache_triggered(bool)2618 void MainWindow::on_actionClearProjectMESSCache_triggered(bool)
2619 {
2620 	QString cacheStatus(tr("freed %n byte(s) in %1", "", qmc2ProjectMESSCache.totalCost()).arg(tr("%n entry(s)", "", qmc2ProjectMESSCache.count())));
2621 	qmc2ProjectMESSCache.clear();
2622 	log(QMC2_LOG_FRONTEND, tr("ProjectMESS in-memory cache cleared (%1)").arg(cacheStatus));
2623 }
2624 
2625 #if defined(QMC2_YOUTUBE_ENABLED)
on_actionClearYouTubeCache_triggered(bool)2626 void MainWindow::on_actionClearYouTubeCache_triggered(bool)
2627 {
2628 	QDir youTubeCacheDir(qmc2Config->value(QMC2_FRONTEND_PREFIX + "YouTubeWidget/CacheDirectory").toString());
2629 	quint64 removedBytes = 0, removedFiles = 0;
2630 	if ( youTubeCacheDir.exists() ) {
2631 		QStringList youTubeCacheFiles(youTubeCacheDir.entryList(QStringList("*")));
2632 		foreach (QString youTubeCacheFile, youTubeCacheFiles) {
2633 			QFileInfo fi(youTubeCacheDir.filePath(youTubeCacheFile));
2634 			qint64 fSize = fi.size();
2635 			if ( youTubeCacheDir.remove(youTubeCacheFile) ) {
2636 				removedBytes += fSize;
2637 				removedFiles++;
2638 			}
2639 			qApp->processEvents();
2640 		}
2641 	}
2642 	QString removalInfo(tr("removed %n byte(s) in %1", "", removedBytes).arg(tr("%n file(s)", "", removedFiles)));
2643 	log(QMC2_LOG_FRONTEND, tr("YouTube on-disk cache cleared (%1)").arg(removalInfo));
2644 }
2645 #endif
2646 
on_actionClearROMStateCache_triggered(bool)2647 void MainWindow::on_actionClearROMStateCache_triggered(bool)
2648 {
2649 	if ( !qmc2ForceCacheRefresh ) {
2650 		if ( qmc2ReloadActive ) {
2651 			log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2652 			return;
2653 		}
2654 		if ( qmc2VerifyActive || qmc2VerifyTaggedActive ) {
2655 			log(QMC2_LOG_FRONTEND, tr("please wait for ROM verification to finish and try again"));
2656 			return;
2657 		}
2658 	}
2659 	QString fileName(qmc2Config->value("MAME/FilesAndDirectories/ROMStateCacheFile", Options::configPath() + "/mame.rsc").toString());
2660 	QFile f(fileName);
2661 	if ( f.exists() ) {
2662 		if ( f.remove() )
2663 			log(QMC2_LOG_FRONTEND, tr("ROM state cache file '%1' removed").arg(fileName));
2664 		else
2665 			log(QMC2_LOG_FRONTEND, tr("WARNING: cannot remove the ROM state cache file '%1', please check permissions").arg(fileName));
2666 	}
2667 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/AutoTriggerROMCheck").toBool() ) {
2668 		qmc2MachineList->autoRomCheck = qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/AutoTriggerROMCheck").toBool();
2669 		log(QMC2_LOG_FRONTEND, tr("triggering an automatic ROM check on next reload"));
2670 	}
2671 }
2672 
on_actionClearMachineListCache_triggered(bool)2673 void MainWindow::on_actionClearMachineListCache_triggered(bool)
2674 {
2675 	if ( !qmc2ForceCacheRefresh ) {
2676 		if ( qmc2ReloadActive ) {
2677 			log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2678 			return;
2679 		}
2680 	}
2681 	QString fileName(qmc2Config->value("MAME/FilesAndDirectories/MachineListCacheFile", Options::configPath() + "/mame.mlc").toString());
2682 	QFile f(fileName);
2683 	if ( f.exists() ) {
2684 		if ( f.remove() )
2685 			log(QMC2_LOG_FRONTEND, tr("machine list cache file '%1' removed").arg(fileName));
2686 		else
2687 			log(QMC2_LOG_FRONTEND, tr("WARNING: cannot remove the machine list cache file '%1', please check permissions").arg(fileName));
2688 	}
2689 	foreach (MachineListViewer *v, machineListViewers)
2690 		v->disconnectFromDb();
2691 	qmc2MachineList->machineListDb()->setLogActive(true);
2692 	qmc2MachineList->machineListDb()->recreateDatabase();
2693 	qmc2MachineList->machineListDb()->setLogActive(false);
2694 	foreach (MachineListViewer *v, machineListViewers)
2695 		v->connectToDb();
2696 }
2697 
on_actionClearXMLCache_triggered(bool)2698 void MainWindow::on_actionClearXMLCache_triggered(bool)
2699 {
2700 	if ( !qmc2ForceCacheRefresh ) {
2701 		if ( qmc2ReloadActive ) {
2702 			log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2703 			return;
2704 		}
2705 	}
2706 	qmc2MachineList->xmlDb()->recreateDatabase();
2707 	systemSoftwareListHash.clear();
2708 	systemSoftwareFilterHash.clear();
2709 }
2710 
on_actionClearSoftwareListCache_triggered(bool)2711 void MainWindow::on_actionClearSoftwareListCache_triggered(bool)
2712 {
2713 	if ( !qmc2ForceCacheRefresh ) {
2714 		if ( qmc2ReloadActive ) {
2715 			log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
2716 			return;
2717 		}
2718 	}
2719 	if ( !swlDb ) {
2720 		swlDb = new SoftwareListXmlDatabaseManager(qmc2MainWindow);
2721 		swlDb->setSyncMode(QMC2_DB_SYNC_MODE_OFF);
2722 		swlDb->setJournalMode(QMC2_DB_JOURNAL_MODE_MEMORY);
2723 	}
2724 	swlDb->recreateDatabase();
2725 	if ( qmc2ImageChecker )
2726 		QTimer::singleShot(0, qmc2ImageChecker, SLOT(updateCornerWidget()));
2727 }
2728 
on_actionClearAllEmulatorCaches_triggered(bool complete)2729 void MainWindow::on_actionClearAllEmulatorCaches_triggered(bool complete)
2730 {
2731 	actionClearROMStateCache->trigger();
2732 	actionClearMachineListCache->trigger();
2733 	actionClearXMLCache->trigger();
2734 	actionClearSoftwareListCache->trigger();
2735 	if ( complete )
2736 		qmc2Config->remove(QMC2_EMULATOR_PREFIX + "Cache");
2737 }
2738 
on_actionRecreateTemplateMap_triggered(bool)2739 void MainWindow::on_actionRecreateTemplateMap_triggered(bool)
2740 {
2741 	if ( qmc2GlobalEmulatorOptions != 0 ) {
2742 		qmc2GlobalEmulatorOptions->createTemplateMap();
2743 		qmc2GlobalEmulatorOptions->clear();
2744 		qmc2GlobalEmulatorOptions->createMap();
2745 		qmc2GlobalEmulatorOptions->load();
2746 	}
2747 }
2748 
on_actionCheckTemplateMap_triggered(bool)2749 void MainWindow::on_actionCheckTemplateMap_triggered(bool)
2750 {
2751 	if ( qmc2GlobalEmulatorOptions != 0 )
2752 		qmc2GlobalEmulatorOptions->checkTemplateMap();
2753 }
2754 
on_actionOptions_triggered(bool)2755 void MainWindow::on_actionOptions_triggered(bool)
2756 {
2757 	if ( qmc2Options->isHidden() )
2758 		qmc2Options->show();
2759 	else if ( qmc2Options->isMinimized() )
2760 		qmc2Options->showNormal();
2761 	QTimer::singleShot(0, qmc2Options, SLOT(raise()));
2762 }
2763 
on_actionRelaunchSetupWizard_triggered(bool)2764 void MainWindow::on_actionRelaunchSetupWizard_triggered(bool)
2765 {
2766 	qmc2ReconfigureRestartRequested = true;
2767 	QTimer::singleShot(0, this, SLOT(close()));
2768 }
2769 
on_actionFullscreenToggle_triggered(bool)2770 void MainWindow::on_actionFullscreenToggle_triggered(bool)
2771 {
2772 	static quint64 lastFullScreenSwitchTime = 0;
2773 
2774 #if defined(QMC2_YOUTUBE_ENABLED)
2775 	if ( qmc2YouTubeWidget )
2776 		if ( qmc2YouTubeWidget->videoWidget()->isFullScreen() ) {
2777 #if QT_VERSION < 0x050000
2778 			qmc2YouTubeWidget->videoWidget()->setFullScreen(false);
2779 #else
2780 			qmc2YouTubeWidget->switchToWindowed();
2781 #endif
2782 			qmc2YouTubeWidget->clearMessage();
2783 			qApp->processEvents();
2784 			if ( windowState() & Qt::WindowFullScreen )
2785 				actionFullscreenToggle->setChecked(true);
2786 			else
2787 				actionFullscreenToggle->setChecked(false);
2788 			return;
2789 		}
2790 #endif
2791 
2792 	// avoid switching too quickly...
2793 	quint64 now = QDateTime::currentDateTime().toMSecsSinceEpoch();
2794 	if ( now - lastFullScreenSwitchTime < QMC2_FULLSCREEN_SWITCH_DELAY )
2795 		return;
2796 	lastFullScreenSwitchTime = now;
2797 
2798 	if ( !qmc2EarlyStartup ) {
2799 		// saftey checks
2800 		if ( windowState() & Qt::WindowFullScreen )
2801 			actionFullscreenToggle->setChecked(false);
2802 		else
2803 			actionFullscreenToggle->setChecked(true);
2804 	}
2805 
2806 	bool feLogScrollBarMaximum = (textBrowserFrontendLog->verticalScrollBar()->value() == textBrowserFrontendLog->verticalScrollBar()->maximum());
2807 	bool emuLogScrollBarMaximum = (textBrowserEmulatorLog->verticalScrollBar()->value() == textBrowserEmulatorLog->verticalScrollBar()->maximum());
2808 
2809 	qApp->processEvents();
2810 
2811 	if ( actionFullscreenToggle->isChecked() ) {
2812 		if ( isVisible() && !(windowState() & Qt::WindowFullScreen) ) {
2813 			if ( isMaximized() )
2814 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Maximized", true);
2815 			else {
2816 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry", saveGeometry());
2817 #if QT_VERSION < 0x050000
2818 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position", pos());
2819 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size", size());
2820 #endif
2821 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Maximized", false);
2822 			}
2823 		} else {
2824 #if QT_VERSION < 0x050000
2825 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size") )
2826 				resize(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size").toSize());
2827 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position") )
2828 				move(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position").toPoint());
2829 #endif
2830 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry") )
2831 				restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry").toByteArray());
2832 		}
2833 		// we need to tweak full screen startup to ensure that raising the window works
2834 		if ( qmc2EarlyStartup ) {
2835 			setUpdatesEnabled(true);
2836 			showNormal();
2837 			raise();
2838 		}
2839 		showFullScreen();
2840 		if ( qmc2EarlyStartup ) {
2841 			qApp->processEvents();
2842 			setUpdatesEnabled(false);
2843 		}
2844 	} else {
2845 #if defined(QMC2_YOUTUBE_ENABLED)
2846 		bool youTubeWasPlaying = false;
2847 		if ( qmc2YouTubeWidget )
2848 			youTubeWasPlaying = qmc2YouTubeWidget->isPlaying();
2849 #endif
2850 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Maximized", false).toBool() )
2851 			showMaximized();
2852 		else {
2853 #if QT_VERSION < 0x050000
2854 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size") )
2855 				resize(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size").toSize());
2856 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position") )
2857 				move(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position").toPoint());
2858 #endif
2859 			if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry") )
2860 				restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry").toByteArray());
2861 			showNormal();
2862 		}
2863 #if defined(QMC2_YOUTUBE_ENABLED)
2864 		if ( qmc2YouTubeWidget && youTubeWasPlaying ) {
2865 			qApp->processEvents();
2866 			if ( !qmc2YouTubeWidget->isPlaying() )
2867 				QTimer::singleShot(0, qmc2YouTubeWidget->videoPlayer(), SLOT(play()));
2868 		}
2869 #endif
2870 	}
2871 
2872 	activateWindow();
2873 	raise();
2874 
2875 	if ( feLogScrollBarMaximum )
2876 		textBrowserFrontendLog->verticalScrollBar()->setValue(textBrowserFrontendLog->verticalScrollBar()->maximum());
2877 	if ( emuLogScrollBarMaximum )
2878 		textBrowserEmulatorLog->verticalScrollBar()->setValue(textBrowserEmulatorLog->verticalScrollBar()->maximum());
2879 }
2880 
on_actionDocumentation_triggered(bool)2881 void MainWindow::on_actionDocumentation_triggered(bool)
2882 {
2883 	if ( !qmc2DocBrowser ) {
2884 		qmc2DocBrowser = new DocBrowser(this);
2885 		qmc2DocBrowser->browser->spinBoxZoom->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/DocBrowser/Zoom", 100).toInt());
2886 		QString searchPath(qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/DataDirectory").toString() + "doc/html/" + qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Language", "us").toString());
2887 		QFileInfo fi(searchPath + "/index.html");
2888 		if ( !fi.exists() || !fi.isFile() || fi.isSymLink() ) // fall back to US English if there's no language-specific index file
2889 			searchPath = qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/DataDirectory").toString() + "doc/html/us";
2890 #if defined(QMC2_OS_WIN)
2891 		QDir searchDir(searchPath);
2892 		QUrl docUrl("file:///" + searchDir.absolutePath() + "/index.html");
2893 #else
2894 		QUrl docUrl("file://" + searchPath + "/index.html");
2895 #endif
2896 		qmc2DocBrowser->browser->webViewBrowser->load(docUrl);
2897 	}
2898 	if ( qmc2DocBrowser->isMinimized() )
2899 		qmc2DocBrowser->showNormal();
2900 	else
2901 		qmc2DocBrowser->show();
2902 
2903 	qmc2DocBrowser->raise();
2904 }
2905 
on_actionAbout_triggered(bool)2906 void MainWindow::on_actionAbout_triggered(bool)
2907 {
2908 	if ( !qmc2About )
2909 		qmc2About = new About(this);
2910 	qmc2About->show();
2911 	qmc2About->raise();
2912 }
2913 
on_actionHomepage_triggered(bool)2914 void MainWindow::on_actionHomepage_triggered(bool)
2915 {
2916 	QDesktopServices::openUrl(QUrl::fromUserInput("http://qmc2.batcom-it.net/"));
2917 }
2918 
on_actionWiki_triggered(bool)2919 void MainWindow::on_actionWiki_triggered(bool)
2920 {
2921 	QDesktopServices::openUrl(QUrl::fromUserInput("http://wiki.batcom-it.net/index.php?title=The_'ultimate'_guide_to_QMC2"));
2922 }
2923 
on_actionForum_triggered(bool)2924 void MainWindow::on_actionForum_triggered(bool)
2925 {
2926 	QDesktopServices::openUrl(QUrl::fromUserInput("http://forums.bannister.org/ubbthreads.php?ubb=postlist&Board=12"));
2927 }
2928 
on_actionBugTracker_triggered(bool)2929 void MainWindow::on_actionBugTracker_triggered(bool)
2930 {
2931 	QDesktopServices::openUrl(QUrl::fromUserInput("http://tracker.batcom-it.net/view_all_bug_page.php?project_id=1"));
2932 }
2933 
on_actionAboutQt_triggered(bool)2934 void MainWindow::on_actionAboutQt_triggered(bool)
2935 {
2936 	QMessageBox::aboutQt(this, tr("About Qt"));
2937 }
2938 
on_actionArcadeSetup_triggered(bool)2939 void MainWindow::on_actionArcadeSetup_triggered(bool)
2940 {
2941 	ArcadeModeSetup	arcadeModeSetup(this);
2942 	arcadeModeSetup.exec();
2943 }
2944 
on_actionLaunchArcade_triggered(bool)2945 void MainWindow::on_actionLaunchArcade_triggered(bool)
2946 {
2947 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ExecutableFile").toString().isEmpty() ) {
2948 		log(QMC2_LOG_FRONTEND, tr("INFORMATION: the arcade mode has to be set up first, launching the respective dialog instead"));
2949 		on_actionArcadeSetup_triggered(false);
2950 		return;
2951 	}
2952 
2953 	QStringList args;
2954 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/Theme").toString().isEmpty() )
2955 		args << "-theme" << qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/Theme").toString();
2956 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ConsoleType").toString().isEmpty() )
2957 		args << "-console" << qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ConsoleType").toString();
2958 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/GraphicsSystem").toString().isEmpty() )
2959 		args << "-graphicssystem" << qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/GraphicsSystem").toString();
2960 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ConfigurationPath").toString().isEmpty() )
2961 		args << "-config_path" << QDir::toNativeSeparators(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ConfigurationPath").toString());
2962 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/DebugKeys").toBool() )
2963 		args << "-debugkeys";
2964 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/NoJoy").toBool() )
2965 		args << "-nojoy";
2966 	else {
2967 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/Joy").toBool() )
2968 			args << "-joy" << QString::number(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/JoyIndex", 0).toInt());
2969 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/DebugJoy").toBool() )
2970 			args << "-debugjoy";
2971 	}
2972 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/DebugQt").toBool() )
2973 		args << "-debugqt";
2974 
2975 	QString commandString(QDir::toNativeSeparators(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ExecutableFile").toString()));
2976 	foreach (QString arg, args)
2977 		commandString += ' ' + arg;
2978 
2979 	log(QMC2_LOG_FRONTEND, tr("arcade mode: launching QMC2 Arcade, command = '%1'").arg(commandString));
2980 
2981 	if ( !QProcess::startDetached(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/ExecutableFile", QString()).toString(), args, qmc2Config->value(QMC2_FRONTEND_PREFIX + "Arcade/WorkingDirectory", QString()).toString()) )
2982 		log(QMC2_LOG_FRONTEND, tr("WARNING: failed launching QMC2 Arcade"));
2983 }
2984 
on_comboBoxSearch_editTextChanged(const QString & text)2985 void MainWindow::on_comboBoxSearch_editTextChanged(const QString &text)
2986 {
2987 	comboBoxToolbarSearch->lineEdit()->blockSignals(true);
2988 	int cPos = comboBoxToolbarSearch->lineEdit()->cursorPosition();
2989 	comboBoxToolbarSearch->lineEdit()->setText(text);
2990 	comboBoxToolbarSearch->lineEdit()->setCursorPosition(cPos);
2991 	comboBoxToolbarSearch->lineEdit()->blockSignals(false);
2992 	if ( searchActive )
2993 		stopSearch = true;
2994 	m_focusSearchResults = false;
2995 	searchTimer.start(QMC2_SEARCH_DELAY);
2996 }
2997 
comboBoxSearch_editTextChanged_delayed()2998 void MainWindow::comboBoxSearch_editTextChanged_delayed()
2999 {
3000 	static QString lastSearchText;
3001 	static bool lastNegatedMatch = false;
3002 	static bool lastIncludeBioses = actionSearchIncludeBiosSets->isChecked();
3003 	static bool lastIncludeDevices = actionSearchIncludeDeviceSets->isChecked();
3004 
3005 	searchTimer.stop();
3006 
3007 	if ( qmc2CleaningUp )
3008 		return;
3009 
3010 	if ( searchActive ) {
3011 		stopSearch = true;
3012 		searchTimer.start(QMC2_SEARCH_DELAY/10);
3013 		return;
3014 	} else
3015 		stopSearch = false;
3016 
3017 	if ( tabWidgetMachineList->currentWidget() != tabSearch )
3018 		return;
3019 
3020 	if ( treeWidgetMachineList->topLevelItemCount() == 1 )
3021 		if ( treeWidgetMachineList->topLevelItem(0)->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
3022 			return;
3023 
3024 	QString pattern(comboBoxSearch->currentText());
3025 	bool includeBioses = actionSearchIncludeBiosSets->isChecked();
3026 	bool includeDevices = actionSearchIncludeDeviceSets->isChecked();
3027 
3028 	if ( pattern.isEmpty() ) {
3029 		listWidgetSearch->clear();
3030 		lastSearchText.clear();
3031 		lastNegatedMatch = negatedMatch;
3032 		lastIncludeBioses = includeBioses;
3033 		lastIncludeDevices = includeDevices;
3034 		qmc2MachineList->numMatchedMachines = listWidgetSearch->count();
3035 		labelMachineListStatus->setText(qmc2MachineList->status());
3036 		lcdNumberSearchResults->display(qmc2MachineList->numMatchedMachines);
3037 		return;
3038 	} else if ( listWidgetSearch->count() == 0 )
3039 		lastSearchText.clear();
3040 
3041 	if ( pattern == lastSearchText && lastNegatedMatch == negatedMatch && lastIncludeBioses == includeBioses && lastIncludeDevices == includeDevices ) {
3042 		if ( m_focusSearchResults )
3043 			listWidgetSearch->setFocus();
3044 		m_focusSearchResults = false;
3045 		return;
3046 	}
3047 
3048 	QString patternCopy(pattern);
3049 
3050 	// easy pattern match
3051 	int pos = 0;
3052 	QRegExp rxAsterisk("(\\*)");
3053 	while ( (pos = rxAsterisk.indexIn(pattern, pos)) != -1 ) {
3054 		int matchedLength = rxAsterisk.matchedLength();
3055 		if ( pos > 0 ) {
3056 			if ( pattern[pos - 1] != '\\' ) {
3057 				pattern.replace(pos, 1, ".*");
3058 				matchedLength = 2;
3059 			}
3060 		} else {
3061 			pattern.replace(pos, 1, ".*");
3062 			matchedLength = 2;
3063 		}
3064 		pos += matchedLength;
3065 	}
3066 
3067 	pos = 0;
3068 	QRegExp rxQuestionMark("(\\?)");
3069 	while ( (pos = rxQuestionMark.indexIn(pattern, pos)) != -1 ) {
3070 		if ( pos > 0 ) {
3071 			if ( pattern[pos - 1] != '\\' )
3072 				pattern.replace(pos, 1, ".");
3073 		} else
3074 			pattern.replace(pos, 1, ".");
3075 		pos += rxQuestionMark.matchedLength();
3076 	}
3077 
3078 	pattern.replace(' ', ".* .*").replace(".*^", QString()).replace("$.*", QString());
3079 	listWidgetSearch->clear();
3080 
3081 	QRegExp patternRx(pattern, Qt::CaseInsensitive, QRegExp::RegExp2);
3082 	if ( !patternRx.isValid() ) {
3083 		lastSearchText.clear();
3084 		lastNegatedMatch = negatedMatch;
3085 		lastIncludeBioses = includeBioses;
3086 		lastIncludeDevices = includeDevices;
3087 		qmc2MachineList->numMatchedMachines = listWidgetSearch->count();
3088 		labelMachineListStatus->setText(qmc2MachineList->status());
3089 		lcdNumberSearchResults->display(qmc2MachineList->numMatchedMachines);
3090 		return;
3091 	}
3092 
3093 	searchActive = true;
3094 	lastSearchText = patternCopy;
3095 
3096 	progressBarSearch->setVisible(true);
3097 	progressBarSearch->setRange(0, qmc2MachineListItemHash.count());
3098 	progressBarSearch->setValue(0);
3099 
3100 	QString currentItemName;
3101 	if ( qmc2CurrentItem )
3102 		currentItemName = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME);
3103 
3104 	if ( m_sortedItemMap.isEmpty() ) {
3105 		// we want to build the sorted item map only once
3106 		QHashIterator<QString, QTreeWidgetItem *> hashIt(qmc2MachineListItemHash);
3107 		while ( hashIt.hasNext() ) {
3108 			hashIt.next();
3109 			m_sortedItemMap.insert(hashIt.key(), hashIt.value());
3110 		}
3111 	}
3112 
3113 	QList<QListWidgetItem *> itemList;
3114 	QListWidgetItem *currentItemPendant = 0;
3115 	QMapIterator<QString, QTreeWidgetItem *> mapIt(m_sortedItemMap);
3116 	int counter = 0;
3117 	while ( mapIt.hasNext() && !stopSearch && !qmc2CleaningUp ) {
3118 		progressBarSearch->setValue(progressBarSearch->value() + 1);
3119 		mapIt.next();
3120 		QString itemName(mapIt.key());
3121 		if ( !includeBioses )
3122 		       if ( qmc2MachineList->isBios(itemName) )
3123 				continue;
3124 		if ( !includeDevices )
3125 			if ( qmc2MachineList->isDevice(itemName) )
3126 				continue;
3127 		QString itemText(mapIt.value()->text(QMC2_MACHINELIST_COLUMN_MACHINE));
3128 		bool matched = itemText.indexOf(patternRx) > -1 || itemName.indexOf(patternRx) > -1;
3129 		if ( negatedMatch )
3130 			matched = !matched;
3131 		if ( matched ) {
3132 			QListWidgetItem *newItem = new QListWidgetItem();
3133 			newItem->setText(itemText);
3134 			newItem->setWhatsThis(itemName);
3135 			itemList << newItem;
3136 			if ( currentItemPendant == 0 )
3137 				if ( currentItemName == itemName )
3138 					currentItemPendant = newItem;
3139 		}
3140 		if ( counter++ % QMC2_SEARCH_RESULT_UPDATE == 0 ) {
3141 			foreach (QListWidgetItem *item, itemList)
3142 				listWidgetSearch->addItem(item);
3143 			itemList.clear();
3144 			qmc2MachineList->numMatchedMachines = listWidgetSearch->count();
3145 			labelMachineListStatus->setText(qmc2MachineList->status());
3146 			lcdNumberSearchResults->display(qmc2MachineList->numMatchedMachines);
3147 			if ( currentItemPendant ) {
3148 				listWidgetSearch->setCurrentItem(currentItemPendant, QItemSelectionModel::ClearAndSelect);
3149 				listWidgetSearch->scrollToItem(currentItemPendant, qmc2CursorPositioningMode);
3150 			}
3151 			qApp->processEvents();
3152 		}
3153 	}
3154 
3155 	if ( !stopSearch && !qmc2CleaningUp ) {
3156 		foreach (QListWidgetItem *item, itemList)
3157 			listWidgetSearch->addItem(item);
3158 		qmc2MachineList->numMatchedMachines = listWidgetSearch->count();
3159 		labelMachineListStatus->setText(qmc2MachineList->status());
3160 		lcdNumberSearchResults->display(qmc2MachineList->numMatchedMachines);
3161 		if ( currentItemPendant ) {
3162 			listWidgetSearch->setCurrentItem(currentItemPendant, QItemSelectionModel::ClearAndSelect);
3163 			listWidgetSearch->scrollToItem(currentItemPendant, qmc2CursorPositioningMode);
3164 		} else if ( listWidgetSearch->count() > 0 ) {
3165 			currentItemPendant = listWidgetSearch->item(0);
3166 			listWidgetSearch->setCurrentItem(currentItemPendant, QItemSelectionModel::ClearAndSelect);
3167 			listWidgetSearch->scrollToItem(currentItemPendant, qmc2CursorPositioningMode);
3168 		}
3169 	} else
3170 		lastSearchText.clear();
3171 
3172 	lastNegatedMatch = negatedMatch;
3173 	lastIncludeBioses = includeBioses;
3174 	lastIncludeDevices = includeDevices;
3175 
3176 	progressBarSearch->setVisible(false);
3177 	progressBarSearch->reset();
3178 
3179 	if ( m_focusSearchResults )
3180 		listWidgetSearch->setFocus();
3181 
3182 	searchActive = m_focusSearchResults = false;
3183 }
3184 
on_comboBoxSearch_activated(const QString & text)3185 void MainWindow::on_comboBoxSearch_activated(const QString &text)
3186 {
3187 	if ( tabWidgetMachineList->currentWidget() != tabSearch ) {
3188 		tabWidgetMachineList->blockSignals(true);
3189 		tabWidgetMachineList->setCurrentWidget(tabSearch);
3190 		tabWidgetMachineList->blockSignals(false);
3191 	}
3192 	int index = comboBoxToolbarSearch->findText(text);
3193 	if ( index < 0 ) {
3194 		comboBoxToolbarSearch->insertItem(0, text);
3195 		comboBoxToolbarSearch->setCurrentIndex(0);
3196 		if ( comboBoxToolbarSearch->count() > QMC2_MACHINE_SEARCH_HISTORY_LENGTH )
3197 			comboBoxToolbarSearch->removeItem(QMC2_MACHINE_SEARCH_HISTORY_LENGTH);
3198 	} else {
3199 		comboBoxToolbarSearch->blockSignals(true);
3200 		comboBoxToolbarSearch->removeItem(index);
3201 		comboBoxToolbarSearch->insertItem(0, text);
3202 		comboBoxToolbarSearch->setCurrentIndex(0);
3203 		comboBoxToolbarSearch->blockSignals(false);
3204 	}
3205 	index = comboBoxSearch->findText(text);
3206 	if ( index >= 0 ) {
3207 		comboBoxSearch->removeItem(index);
3208 		comboBoxSearch->insertItem(0, text);
3209 		comboBoxSearch->setCurrentIndex(0);
3210 	}
3211 	if ( comboBoxSearch->count() > QMC2_MACHINE_SEARCH_HISTORY_LENGTH )
3212 		comboBoxSearch->removeItem(QMC2_MACHINE_SEARCH_HISTORY_LENGTH);
3213 	m_focusSearchResults = true;
3214 	comboBoxSearch_editTextChanged_delayed();
3215 }
3216 
on_listWidgetSearch_currentItemChanged(QListWidgetItem * current,QListWidgetItem * previous)3217 void MainWindow::on_listWidgetSearch_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
3218 {
3219 	static bool isActive = false;
3220 	if ( isActive )
3221 		return;
3222 	isActive = true;
3223 	QTreeWidgetItem *mlItem = 0;
3224 	if ( current )
3225 		mlItem = qmc2MachineListItemHash.value(current->whatsThis());
3226 	if ( mlItem ) {
3227 		qmc2CheckItemVisibility = false;
3228 		treeWidgetMachineList->clearSelection();
3229 		qmc2CurrentItem = mlItem;
3230 		treeWidgetMachineList->setCurrentItem(mlItem);
3231 	}
3232 	isActive = false;
3233 }
3234 
on_listWidgetSearch_itemPressed(QListWidgetItem * current)3235 void MainWindow::on_listWidgetSearch_itemPressed(QListWidgetItem *current)
3236 {
3237 	on_listWidgetSearch_currentItemChanged(current, 0);
3238 }
3239 
on_listWidgetSearch_itemSelectionChanged()3240 void MainWindow::on_listWidgetSearch_itemSelectionChanged()
3241 {
3242 	QList<QListWidgetItem *> selected(listWidgetSearch->selectedItems());
3243 	if ( !selected.isEmpty() )
3244 		on_listWidgetSearch_currentItemChanged(selected.first(), 0);
3245 }
3246 
on_listWidgetSearch_itemActivated(QListWidgetItem * item)3247 void MainWindow::on_listWidgetSearch_itemActivated(QListWidgetItem *item)
3248 {
3249 	if ( item == 0 )
3250 		return;
3251 
3252 	QList<QTreeWidgetItem *> matchItemList = treeWidgetMachineList->findItems(item->text(), Qt::MatchExactly);
3253 	if ( !matchItemList.isEmpty() ) {
3254 		QTreeWidgetItem *matchItem = matchItemList[0];
3255 		qmc2CheckItemVisibility = false;
3256 		treeWidgetMachineList->clearSelection();
3257 		treeWidgetMachineList->setCurrentItem(matchItem);
3258 		treeWidgetMachineList->scrollToItem(matchItem, qmc2CursorPositioningMode);
3259 		qmc2CurrentItem = matchItem;
3260 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/PlayOnSublistActivation").toBool() ) {
3261 			if ( qmc2DemoModeDialog )
3262 				if ( qmc2DemoModeDialog->demoModeRunning )
3263 					return;
3264 			switch ( qmc2DefaultLaunchMode ) {
3265 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3266 				case QMC2_LAUNCH_MODE_EMBEDDED:
3267 					QTimer::singleShot(0, this, SLOT(on_actionPlayEmbedded_triggered()));
3268 					break;
3269 #endif
3270 				case QMC2_LAUNCH_MODE_INDEPENDENT:
3271 				default:
3272 					QTimer::singleShot(0, this, SLOT(on_actionPlay_triggered()));
3273 					break;
3274 			}
3275 		} else {
3276 			tabWidgetMachineList->setCurrentWidget(tabMachineList);
3277 			if ( !qmc2ReloadActive )
3278 				treeWidgetMachineList->expandItem(matchItem);
3279 		}
3280 	} else
3281 		log(QMC2_LOG_FRONTEND, tr("ERROR: no match found (?)"));
3282 }
3283 
on_listWidgetFavorites_itemSelectionChanged()3284 void MainWindow::on_listWidgetFavorites_itemSelectionChanged()
3285 {
3286 	QList<QListWidgetItem *> selected(listWidgetFavorites->selectedItems());
3287 	if ( !selected.isEmpty() )
3288 		on_listWidgetSearch_currentItemChanged(selected.first(), 0);
3289 }
3290 
on_listWidgetFavorites_itemActivated(QListWidgetItem * item)3291 void MainWindow::on_listWidgetFavorites_itemActivated(QListWidgetItem *item)
3292 {
3293 	on_listWidgetSearch_itemActivated(item);
3294 }
3295 
on_listWidgetPlayed_itemSelectionChanged()3296 void MainWindow::on_listWidgetPlayed_itemSelectionChanged()
3297 {
3298 	QList<QListWidgetItem *> selected(listWidgetPlayed->selectedItems());
3299 	if ( !selected.isEmpty() )
3300 		on_listWidgetSearch_currentItemChanged(selected.first(), 0);
3301 }
3302 
on_listWidgetPlayed_itemActivated(QListWidgetItem * item)3303 void MainWindow::on_listWidgetPlayed_itemActivated(QListWidgetItem *item)
3304 {
3305 	on_listWidgetSearch_itemActivated(item);
3306 }
3307 
on_tabWidgetMachineList_currentChanged(int currentIndex)3308 void MainWindow::on_tabWidgetMachineList_currentChanged(int currentIndex)
3309 {
3310 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3311 	static int lastTabWidgetMachineListIndex = -1;
3312 #endif
3313 
3314 	if ( !qmc2EarlyStartup ) {
3315 		menuMachineListHeader->hide();
3316 		menuHierarchyHeader->hide();
3317 		menuCategoryHeader->hide();
3318 		menuVersionHeader->hide();
3319 	}
3320 
3321 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
3322 	if ( componentInfo->appliedFeatureList().count() <= currentIndex || currentIndex < 0 )
3323 		return;
3324 
3325 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3326 	if ( hSplitterSizes.count() > 1 && componentInfo->appliedFeatureList().at(currentIndex) != QMC2_EMBED_INDEX )
3327 		hSplitter->setSizes(hSplitterSizes);
3328 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
3329 	if ( embedIndex >= 0 && embedIndex <= currentIndex )
3330 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
3331 			currentIndex++;
3332 #endif
3333 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
3334 	if ( foreignIndex >= 0 && foreignIndex <= currentIndex )
3335 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
3336 			currentIndex++;
3337 	switch ( componentInfo->appliedFeatureList().at(currentIndex) ) {
3338 		case QMC2_MACHINELIST_INDEX:
3339 			actionToggleTagCursorDown->setVisible(true);
3340 			actionToggleTagCursorUp->setVisible(true);
3341 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3342 			if ( lastTabWidgetMachineListIndex >= 0 )
3343 				if ( componentInfo->appliedFeatureList().at(lastTabWidgetMachineListIndex) != QMC2_EMBED_INDEX )
3344 					QTimer::singleShot(0, this, SLOT(scrollToCurrentItem()));
3345 			menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
3346 			statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
3347 			toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
3348 #else
3349 			QTimer::singleShot(0, this, SLOT(scrollToCurrentItem()));
3350 #endif
3351 			on_comboBoxViewSelect_currentIndexChanged(comboBoxViewSelect->currentIndex());
3352 			if ( !qmc2MachineList->initialLoad ) {
3353 				switch ( stackedWidgetView->currentIndex() ) {
3354 					case QMC2_VIEWHIERARCHY_INDEX:
3355 						treeWidgetHierarchy->activateWindow();
3356 						treeWidgetHierarchy->setFocus();
3357 						QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetHierarchy_verticalScrollChanged()));
3358 						break;
3359 					case QMC2_VIEWCATEGORY_INDEX:
3360 						treeWidgetCategoryView->activateWindow();
3361 						treeWidgetCategoryView->setFocus();
3362 						QTimer::singleShot(0, this, SLOT(viewByCategory()));
3363 						break;
3364 					case QMC2_VIEWVERSION_INDEX:
3365 						treeWidgetVersionView->activateWindow();
3366 						treeWidgetVersionView->setFocus();
3367 						QTimer::singleShot(0, this, SLOT(viewByVersion()));
3368 						break;
3369 					case QMC2_VIEWCUSTOM_INDEX:
3370 						if ( attachedViewer() ) {
3371 							attachedViewer()->activateWindow();
3372 							attachedViewer()->treeView->setFocus();
3373 						}
3374 						break;
3375 					case QMC2_VIEWMACHINELIST_INDEX:
3376 					default:
3377 						treeWidgetMachineList->activateWindow();
3378 						treeWidgetMachineList->setFocus();
3379 						QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetMachineList_verticalScrollChanged()));
3380 						break;
3381 				}
3382 			}
3383 			break;
3384 
3385 		case QMC2_SEARCH_INDEX:
3386 			actionToggleTagCursorDown->setVisible(false);
3387 			actionToggleTagCursorUp->setVisible(false);
3388 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3389 			if ( lastTabWidgetMachineListIndex >= 0 )
3390 				if ( componentInfo->appliedFeatureList().at(lastTabWidgetMachineListIndex) != QMC2_EMBED_INDEX )
3391 					QTimer::singleShot(0, this, SLOT(checkCurrentSearchSelection()));
3392 			menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
3393 			statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
3394 			toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
3395 #else
3396 			QTimer::singleShot(0, this, SLOT(checkCurrentSearchSelection()));
3397 #endif
3398 			if ( listWidgetSearch->count() > 0 ) {
3399 				listWidgetSearch->activateWindow();
3400 				listWidgetSearch->setFocus();
3401 			} else {
3402 				comboBoxSearch->activateWindow();
3403 				comboBoxSearch->setFocus();
3404 			}
3405 			break;
3406 
3407 		case QMC2_FAVORITES_INDEX:
3408 			actionToggleTagCursorDown->setVisible(false);
3409 			actionToggleTagCursorUp->setVisible(false);
3410 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3411 			if ( lastTabWidgetMachineListIndex >= 0 )
3412 				if ( componentInfo->appliedFeatureList().at(lastTabWidgetMachineListIndex) != QMC2_EMBED_INDEX )
3413 					QTimer::singleShot(0, this, SLOT(checkCurrentFavoritesSelection()));
3414 			menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
3415 			statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
3416 			toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
3417 #else
3418 			QTimer::singleShot(0, this, SLOT(checkCurrentFavoritesSelection()));
3419 #endif
3420 			if ( listWidgetFavorites->count() > 0 ) {
3421 				listWidgetFavorites->activateWindow();
3422 				listWidgetFavorites->setFocus();
3423 			}
3424 			break;
3425 
3426 		case QMC2_PLAYED_INDEX:
3427 			actionToggleTagCursorDown->setVisible(false);
3428 			actionToggleTagCursorUp->setVisible(false);
3429 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3430 			if ( lastTabWidgetMachineListIndex >= 0 )
3431 				if ( componentInfo->appliedFeatureList().at(lastTabWidgetMachineListIndex) != QMC2_EMBED_INDEX )
3432 					QTimer::singleShot(0, this, SLOT(checkCurrentPlayedSelection()));
3433 			menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
3434 			statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
3435 			toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
3436 #else
3437 			QTimer::singleShot(0, this, SLOT(checkCurrentPlayedSelection()));
3438 #endif
3439 			if ( listWidgetPlayed->count() > 0 ) {
3440 				listWidgetPlayed->activateWindow();
3441 				listWidgetPlayed->setFocus();
3442 			}
3443 			break;
3444 
3445 		case QMC2_FOREIGN_INDEX:
3446 			actionToggleTagCursorDown->setVisible(true);
3447 			actionToggleTagCursorUp->setVisible(true);
3448 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3449 			menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
3450 			statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
3451 			toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
3452 #else
3453 			QTimer::singleShot(0, this, SLOT(scrollToCurrentItem()));
3454 #endif
3455 			if ( treeWidgetForeignIDs->topLevelItemCount() > 0 ) {
3456 				treeWidgetForeignIDs->activateWindow();
3457 				treeWidgetForeignIDs->setFocus();
3458 			}
3459 			break;
3460 
3461 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3462 		case QMC2_EMBED_INDEX:
3463 			actionToggleTagCursorDown->setVisible(false);
3464 			actionToggleTagCursorUp->setVisible(false);
3465 			if ( toolButtonEmbedderMaximizeToggle->isChecked() ) {
3466 				menuBar()->hide();
3467 				statusBar()->hide();
3468 				toolbar->hide();
3469 				qApp->processEvents();
3470 				hSplitterSizes = hSplitter->sizes();
3471 				QList<int> maximizedSizes;
3472 				if ( hSplitter->widget(0) == hSplitterWidget0 )
3473 					maximizedSizes << desktopGeometry.width() << 0;
3474 				else
3475 					maximizedSizes << 0 << desktopGeometry.width();
3476 				hSplitter->setSizes(maximizedSizes);
3477 			}
3478 			break;
3479 #endif
3480 
3481 		default:
3482 			break;
3483 	}
3484 
3485 	ImageWidget::updateArtwork();
3486 
3487 	// show / hide machine status indicator
3488 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicator").toBool() ) {
3489 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicatorOnlyWhenRequired").toBool() ) {
3490 			if ( componentInfo->appliedFeatureList().at(currentIndex) != QMC2_MACHINELIST_INDEX )
3491 				labelMachineStatus->setVisible(true);
3492 			else
3493 				labelMachineStatus->setVisible(false);
3494 		} else
3495 			labelMachineStatus->setVisible(true);
3496 	} else
3497 		labelMachineStatus->setVisible(false);
3498 
3499 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3500 	lastTabWidgetMachineListIndex = currentIndex;
3501 #endif
3502 }
3503 
on_tabWidgetLogsAndEmulators_currentChanged(int currentIndex)3504 void MainWindow::on_tabWidgetLogsAndEmulators_currentChanged(int currentIndex)
3505 {
3506 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component3");
3507 	if ( componentInfo->appliedFeatureList().count() <= currentIndex || currentIndex < 0 )
3508 		return;
3509 	switch ( componentInfo->appliedFeatureList().at(currentIndex) ) {
3510 		case QMC2_FRONTENDLOG_INDEX:
3511 			logScrollToEnd(QMC2_LOG_FRONTEND);
3512 			break;
3513 
3514 		case QMC2_EMULATORLOG_INDEX:
3515 			logScrollToEnd(QMC2_LOG_EMULATOR);
3516 			break;
3517 
3518 		default:
3519 			break;
3520 	}
3521 }
3522 
on_tabWidgetSoftwareDetail_currentChanged(int currentIndex)3523 void MainWindow::on_tabWidgetSoftwareDetail_currentChanged(int currentIndex)
3524 {
3525 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component4");
3526 	if ( !qmc2SoftwareList )
3527 		return;
3528 	if ( !qmc2SoftwareList->currentItem )
3529 		return;
3530 	if ( !tabWidgetSoftwareDetail->isVisible() )
3531 		return;
3532 	int left, top, right, bottom;
3533 	gridLayout->getContentsMargins(&left, &top, &right, &bottom);
3534 	switch ( componentInfo->appliedFeatureList().at(currentIndex) ) {
3535 		case QMC2_SWINFO_SNAPSHOT_PAGE:
3536 			if ( qmc2SoftwareNotesEditor )
3537 				qmc2SoftwareNotesEditor->hideTearOffMenus();
3538 			if ( !qmc2SoftwareSnapshot ) {
3539 				qmc2SoftwareSnapshot = new SoftwareSnapshot(tabSnapshot);
3540 				QHBoxLayout *layout = new QHBoxLayout;
3541 				layout->addWidget(qmc2SoftwareSnapshot);
3542 				layout->setContentsMargins(0, 0, 0, 0);
3543 				tabSnapshot->setLayout(layout);
3544 			}
3545 			break;
3546 		case QMC2_SWINFO_PROJECTMESS_PAGE:
3547 			if ( qmc2SoftwareNotesEditor )
3548 				qmc2SoftwareNotesEditor->hideTearOffMenus();
3549 			if ( qmc2SoftwareList->currentItem != qmc2LastProjectMESSItem ) {
3550 				if ( !qmc2ProjectMESS ) {
3551 					QVBoxLayout *layout = new QVBoxLayout;
3552 					layout->setContentsMargins(left, top, right, bottom);
3553 					qmc2ProjectMESS = new MiniWebBrowser(tabSoftwareProjectMESS);
3554 					layout->addWidget(qmc2ProjectMESS);
3555 					tabSoftwareProjectMESS->setLayout(layout);
3556 					connect(qmc2ProjectMESS->webViewBrowser, SIGNAL(loadStarted()), this, SLOT(projectMessLoadStarted()));
3557 				}
3558 				QString entryName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME);
3559 				QString entryTitle = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_TITLE);
3560 				QString listName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST);
3561 				QString projectMessUrl = qmc2Config->value(QMC2_FRONTEND_PREFIX + "ProjectMESS/BaseURL", QMC2_PROJECT_MESS_BASE_URL).toString().arg(entryName).arg(listName);
3562 				qmc2ProjectMESS->webViewBrowser->setStatusTip(tr("ProjectMESS page for '%1' / '%2'").arg(listName).arg(entryTitle));
3563 				if ( !qmc2ProjectMESSCache.contains(listName + "_" + entryName) ) {
3564 					QColor color = qmc2ProjectMESS->webViewBrowser->palette().color(QPalette::WindowText);
3565 					qmc2ProjectMESS->webViewBrowser->setHtml(
3566 								QString("<html><head></head><body><center><p><font color=\"#%1%2%3\"<b>").arg(color.red()).arg(color.green()).arg(color.blue()) +
3567 									tr("Fetching ProjectMESS page for '%1' / '%2', please wait...").arg(listName).arg(entryTitle) + "</font></b></p><p>" +
3568 									QString("(<a href=\"%1\">%1</a>)").arg(projectMessUrl) + "</p></center></body></html>",
3569 								QUrl(projectMessUrl));
3570 					connect(qmc2ProjectMESS->webViewBrowser, SIGNAL(loadFinished(bool)), this, SLOT(projectMessLoadFinished(bool)));
3571 					qmc2ProjectMESS->webViewBrowser->load(QUrl(projectMessUrl));
3572 				} else {
3573 					// FIXME: There's currently a bug in QWebView::setHtml() so that it executes JavaScript twice.
3574 					qmc2ProjectMESS->webViewBrowser->setHtml(QString(QMC2_UNCOMPRESS(*qmc2ProjectMESSCache[listName + "_" + entryName])), QUrl(projectMessUrl));
3575 					qmc2ProjectMESS->webViewBrowser->load(QUrl(projectMessUrl));
3576 				}
3577 				qmc2ProjectMESS->homeUrl = QUrl(projectMessUrl);
3578 				qmc2LastProjectMESSItem = qmc2SoftwareList->currentItem;
3579 			}
3580 			break;
3581 		case QMC2_SWINFO_NOTES_PAGE:
3582 			if ( qmc2SoftwareList->currentItem != qmc2LastSoftwareNotesItem ) {
3583 				if ( !qmc2SoftwareNotesEditor ) {
3584 					QVBoxLayout *layout = new QVBoxLayout;
3585 					layout->setContentsMargins(left, top, right, bottom);
3586 					qmc2SoftwareNotesEditor = new HtmlEditor("SoftwareNotes", true, tabNotes);
3587 					layout->addWidget(qmc2SoftwareNotesEditor);
3588 					tabNotes->setLayout(layout);
3589 				} else {
3590 					qmc2SoftwareNotesEditor->save();
3591 					qmc2SoftwareNotesEditor->loadedContent.clear();
3592 					qmc2SoftwareNotesEditor->checkRevertStatus();
3593 				}
3594 
3595 				QString entryName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME);
3596 				QString listName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST);
3597 				QString softwareParent = softwareParentHash[listName + ":" + entryName];
3598 				if ( !softwareParent.isEmpty() ) {
3599 					QStringList softwareParentWords(softwareParent.split(':'));
3600 					if ( softwareParentWords.count() > 1 )
3601 						softwareParent = softwareParentWords[1];
3602 					else
3603 						softwareParent.clear();
3604 				}
3605 
3606 				QString softwareNotesFolder = qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/SoftwareNotesFolder").toString();
3607 				QString softwareNotesTemplate = qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/SoftwareNotesTemplate").toString();
3608 				bool useSoftwareNotesTemplate = qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/UseSoftwareNotesTemplate").toBool();
3609 				QString fileName = softwareNotesFolder + qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST) + "/" + qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME) + ".html";
3610 				qmc2SoftwareNotesEditor->setCurrentFileName(fileName);
3611 
3612 				qmc2SoftwareNotesEditor->enableFileNewFromTemplateAction(useSoftwareNotesTemplate);
3613 
3614 				qmc2SoftwareNotesEditor->templateMap.clear();
3615 #if QT_VERSION < 0x050000
3616 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_TITLE$"] = Qt::escape(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_TITLE));
3617 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_PUBLISHER$"] = Qt::escape(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_PUBLISHER));
3618 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_YEAR$"] = Qt::escape(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_YEAR));
3619 #else
3620 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_TITLE$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_TITLE).toHtmlEscaped();
3621 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_PUBLISHER$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_PUBLISHER).toHtmlEscaped();
3622 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_YEAR$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_YEAR).toHtmlEscaped();
3623 #endif
3624 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_NAME$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME);
3625 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_PARENT_ID$"] = softwareParent;
3626 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_LIST$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST);
3627 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SUPPORTED$"] = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_SUPPORTED);
3628 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SUPPORTED_UT$"] = MachineList::reverseTranslations.value(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_SUPPORTED));
3629 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_STATUS$"] = qmc2SoftwareList->softwareStatus(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST), qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME), true);
3630 				qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_STATUS_UT$"] = qmc2SoftwareList->softwareStatus(qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST), qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME), false);
3631 	      			qmc2SoftwareNotesEditor->templateMap["$GUI_LANGUAGE$"] = qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Language", "us").toString();
3632 	      			qmc2SoftwareNotesEditor->templateMap["$EMULATOR_VARIANT$"] = QMC2_EMU_NAME_VARIANT;
3633 	      			qmc2SoftwareNotesEditor->templateMap["$EMULATOR_TYPE$"] = QMC2_EMU_NAME;
3634 				if ( !qmc2SoftwareSnapshot ) {
3635 					qmc2SoftwareSnapshot = new SoftwareSnapshot(tabSnapshot);
3636 					QHBoxLayout *layout = new QHBoxLayout;
3637 					layout->addWidget(qmc2SoftwareSnapshot);
3638 					layout->setContentsMargins(0, 0, 0, 0);
3639 					tabSnapshot->setLayout(layout);
3640 				}
3641 				QDir dataDir(qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/DataDirectory").toString());
3642 				QString ghostPath(QDir::fromNativeSeparators(dataDir.absolutePath() + "/img/ghost.png"));
3643 #if defined(QMC2_OS_WIN)
3644 	      			qmc2SoftwareNotesEditor->templateMap["$GHOST_IMAGE$"] = "file:///" + ghostPath;
3645 				if ( qmc2SoftwareSnapshot->loadImage(listName, entryName) )
3646 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SNAPSHOT$"] = "file:///" + QDir::fromNativeSeparators(qmc2SoftwareSnapshot->absoluteImagePath());
3647 				else
3648 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SNAPSHOT$"] = "file:///" + ghostPath;
3649 #else
3650 	      			qmc2SoftwareNotesEditor->templateMap["$GHOST_IMAGE$"] = "file://" + ghostPath;
3651 				if ( qmc2SoftwareSnapshot->loadImage(listName, entryName) )
3652 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SNAPSHOT$"] = "file://" + QDir::fromNativeSeparators(qmc2SoftwareSnapshot->absoluteImagePath());
3653 				else
3654 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_SNAPSHOT$"] = "file://" + ghostPath;
3655 #endif
3656 				QString swInfo = qmc2MachineList->datInfoDb()->softwareInfo(listName, entryName);
3657 				if ( !swInfo.isEmpty() ) {
3658 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_INFO$"] = swInfo.replace(QRegExp(QString("((http|https|ftp)://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>"));
3659 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_INFO_STATUS$"] = "OK";
3660 				} else {
3661 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_INFO$"] = tr("No data available");
3662 					qmc2SoftwareNotesEditor->templateMap["$SOFTWARE_INFO_STATUS$"] = "NO_DATA";
3663 				}
3664 				qmc2SoftwareNotesEditor->setCurrentTemplateName(softwareNotesTemplate);
3665 				qmc2SoftwareNotesEditor->stopLoading = true;
3666 
3667 				if ( QFile::exists(fileName) )
3668 					QTimer::singleShot(25, qmc2SoftwareNotesEditor, SLOT(loadCurrent()));
3669 				else {
3670 					if ( useSoftwareNotesTemplate )
3671 						QTimer::singleShot(25, qmc2SoftwareNotesEditor, SLOT(loadCurrentTemplate()));
3672 					else
3673 						qmc2SoftwareNotesEditor->fileNew();
3674 				}
3675 				qmc2SoftwareNotesEditor->setCurrentFileName(fileName);
3676 				qmc2LastSoftwareNotesItem = qmc2SoftwareList->currentItem;
3677 			}
3678 			break;
3679 		case QMC2_SWINFO_INFO_PAGE:
3680 			if ( qmc2SoftwareList->currentItem != qmc2LastSoftwareInfoItem ) {
3681 				QString listName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST);
3682 				QString entryName = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME);
3683 				QString swInfo = qmc2MachineList->datInfoDb()->softwareInfo(listName, entryName);
3684 				if ( !swInfo.isEmpty() )
3685 					textBrowserSoftwareInfo->setHtml(swInfo.replace(QRegExp(QString("((http|https|ftp)://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>")));
3686 				else
3687 					textBrowserSoftwareInfo->setHtml("<p>" + tr("No data available") + "</p>");
3688 				qmc2LastSoftwareInfoItem = qmc2SoftwareList->currentItem;
3689 			}
3690 			break;
3691 		default:
3692 			break;
3693 	}
3694 }
3695 
scrollToCurrentItem()3696 void MainWindow::scrollToCurrentItem()
3697 {
3698 	QTreeWidgetItem *ci = 0;
3699 	if ( qmc2CurrentItem )
3700 		ci = qmc2CurrentItem;
3701 	else
3702 		ci = treeWidgetMachineList->currentItem();
3703 	if ( ci ) {
3704 		if ( ci->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
3705 			return;
3706 		QString machineName(ci->text(QMC2_MACHINELIST_COLUMN_NAME));
3707 		switch ( stackedWidgetView->currentIndex() ) {
3708 			case QMC2_VIEWHIERARCHY_INDEX:
3709 				ci = qmc2HierarchyItemHash.value(machineName);
3710 				if ( ci ) {
3711 					treeWidgetHierarchy->clearSelection();
3712 					treeWidgetHierarchy->setCurrentItem(ci);
3713 					treeWidgetHierarchy->scrollToItem(ci, qmc2CursorPositioningMode);
3714 				}
3715 				break;
3716 			case QMC2_VIEWCATEGORY_INDEX:
3717 				ci = qmc2CategoryItemHash.value(machineName);
3718 				if ( ci ) {
3719 					treeWidgetCategoryView->clearSelection();
3720 					treeWidgetCategoryView->setCurrentItem(ci);
3721 					treeWidgetCategoryView->scrollToItem(ci, qmc2CursorPositioningMode);
3722 				} else if ( qmc2CurrentItem ) {
3723 					// the category view hasn't been loaded (completely) yet, so select the item in the hierarchical view instead to avoid displaying the wrong machine detail temporarily
3724 					// (this will only happen when the selected machine is hidden in the main view and the category view is active inititally)
3725 					ci = qmc2HierarchyItemHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
3726 					if ( ci ) {
3727 						treeWidgetHierarchy->clearSelection();
3728 						treeWidgetHierarchy->setCurrentItem(ci);
3729 						treeWidgetHierarchy->scrollToItem(ci, qmc2CursorPositioningMode);
3730 						treeWidgetHierarchy->horizontalScrollBar()->setValue(0); // hidden views act strangley...
3731 					}
3732 				}
3733 				break;
3734 			case QMC2_VIEWVERSION_INDEX:
3735 				ci = qmc2VersionItemHash.value(machineName);
3736 				if ( ci ) {
3737 					treeWidgetVersionView->clearSelection();
3738 					treeWidgetVersionView->setCurrentItem(ci);
3739 					treeWidgetVersionView->scrollToItem(ci, qmc2CursorPositioningMode);
3740 				} else if ( qmc2CurrentItem ) {
3741 					// the version view hasn't been loaded (completely) yet, so select the item in the hierarchical view instead to avoid displaying the wrong machine detail temporarily
3742 					// (this will only happen when the selected machine is hidden in the main view and the version view is active inititally)
3743 					ci = qmc2HierarchyItemHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
3744 					if ( ci ) {
3745 						treeWidgetHierarchy->clearSelection();
3746 						treeWidgetHierarchy->setCurrentItem(ci);
3747 						treeWidgetHierarchy->scrollToItem(ci, qmc2CursorPositioningMode);
3748 						treeWidgetHierarchy->horizontalScrollBar()->setValue(0); // hidden views act strangley...
3749 					}
3750 				}
3751 				break;
3752 			case QMC2_VIEWCUSTOM_INDEX:
3753 				// handled by custom view
3754 				break;
3755 			case QMC2_VIEWMACHINELIST_INDEX:
3756 			default:
3757 				qmc2CheckItemVisibility = false;
3758 				treeWidgetMachineList->clearSelection();
3759 				treeWidgetMachineList->setCurrentItem(ci);
3760 				treeWidgetMachineList->scrollToItem(ci, qmc2CursorPositioningMode);
3761 				break;
3762 		}
3763 		if ( !qmc2ReloadActive && ci )
3764 			ci->setSelected(true);
3765 		QTimer::singleShot(0, this, SLOT(updateUserData()));
3766 	}
3767 }
3768 
checkCurrentSearchSelection()3769 void MainWindow::checkCurrentSearchSelection()
3770 {
3771 	listWidgetSearch->setCurrentIndex(QModelIndex());
3772 	listWidgetSearch->clearSelection();
3773 
3774 	if ( !qmc2CurrentItem )
3775 		return;
3776 
3777 	listWidgetSearch->blockSignals(true);
3778 	QList<QListWidgetItem *> searchMatches = listWidgetSearch->findItems(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE), Qt::MatchExactly);
3779 	if ( searchMatches.count() > 0 ) {
3780 		QListWidgetItem *matchedItem = searchMatches[0];
3781 		if ( matchedItem != 0 ) {
3782 			listWidgetSearch->setCurrentItem(matchedItem, QItemSelectionModel::ClearAndSelect);
3783 			listWidgetSearch->scrollToItem(matchedItem, qmc2CursorPositioningMode);
3784 			qApp->processEvents();
3785 		}
3786 	}
3787 	listWidgetSearch->blockSignals(false);
3788 }
3789 
checkCurrentFavoritesSelection()3790 void MainWindow::checkCurrentFavoritesSelection()
3791 {
3792 	listWidgetFavorites->setCurrentIndex(QModelIndex());
3793 	listWidgetFavorites->clearSelection();
3794 
3795 	if ( !qmc2CurrentItem )
3796 		return;
3797 
3798 	listWidgetFavorites->blockSignals(true);
3799 	QList<QListWidgetItem *> favoritesMatches = listWidgetFavorites->findItems(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE), Qt::MatchExactly);
3800 	if ( favoritesMatches.count() > 0 ) {
3801 		QListWidgetItem *matchedItem = favoritesMatches[0];
3802 		if ( matchedItem != 0 ) {
3803 			listWidgetFavorites->setCurrentItem(matchedItem, QItemSelectionModel::ClearAndSelect);
3804 			listWidgetFavorites->scrollToItem(matchedItem, qmc2CursorPositioningMode);
3805 			qApp->processEvents();
3806 		}
3807 	}
3808 	listWidgetFavorites->setFocus();
3809 	listWidgetFavorites->blockSignals(false);
3810 }
3811 
checkCurrentPlayedSelection()3812 void MainWindow::checkCurrentPlayedSelection()
3813 {
3814 	listWidgetPlayed->setCurrentIndex(QModelIndex());
3815 	listWidgetPlayed->clearSelection();
3816 
3817 	if ( !qmc2CurrentItem )
3818 		return;
3819 
3820 	listWidgetPlayed->blockSignals(true);
3821 	QList<QListWidgetItem *> playedMatches = listWidgetPlayed->findItems(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE), Qt::MatchExactly);
3822 	if ( playedMatches.count() > 0 ) {
3823 		QListWidgetItem *matchedItem = playedMatches[0];
3824 		if ( matchedItem != 0 ) {
3825 			listWidgetPlayed->setCurrentItem(matchedItem, QItemSelectionModel::ClearAndSelect);
3826 			listWidgetPlayed->scrollToItem(matchedItem, qmc2CursorPositioningMode);
3827 			qApp->processEvents();
3828 		}
3829 	}
3830 	listWidgetPlayed->setFocus();
3831 	listWidgetPlayed->blockSignals(false);
3832 }
3833 
softwareLoadInterrupted()3834 void MainWindow::softwareLoadInterrupted()
3835 {
3836 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
3837 	on_tabWidgetMachineDetail_currentChanged(componentInfo->appliedFeatureList().indexOf(QMC2_SOFTWARE_LIST_INDEX));
3838 }
3839 
detailTabBarUpdate(int currentIndex)3840 void MainWindow::detailTabBarUpdate(int currentIndex)
3841 {
3842 	// this is a workaround for a Qt bug that prevents the tab-header from scrolling correctly when the current index is "far to the right", seen on Windows
3843 	QTabBar *tabBar = tabWidgetMachineDetail->findChild<QTabBar *>();
3844 	if ( tabBar ) {
3845 		if ( tabBar->currentIndex() == currentIndex && tabBar->count() > 1 ) {
3846 			tabBar->blockSignals(true);
3847 			tabBar->setUpdatesEnabled(false);
3848 			tabBar->setCurrentIndex(currentIndex > 0 ? currentIndex - 1 : 1);
3849 			tabBar->setCurrentIndex(currentIndex);
3850 			tabBar->setUpdatesEnabled(true);
3851 			tabBar->blockSignals(false);
3852 		}
3853 	}
3854 }
3855 
showAttachedView(const QString & name)3856 void MainWindow::showAttachedView(const QString &name)
3857 {
3858 	stackedWidgetView->setCurrentIndex(QMC2_VIEWCUSTOM_INDEX);
3859 	if ( !attachedViewer() ) {
3860 		m_attachedViewer = new MachineListViewer(attachedViewsPage);
3861 		attachedViewer()->setVisible(!qmc2MachineList->initialLoad);
3862 		machineListViewers.append(attachedViewer());
3863 		connect(attachedViewer(), SIGNAL(selectionChanged(const QString &)), this, SLOT(machineListViewer_selectionChanged(const QString &)));
3864 		connect(attachedViewer(), SIGNAL(tagChanged(const QString &, bool)), this, SLOT(machineListViewer_tagChanged(const QString &, bool)));
3865 		connect(this, SIGNAL(selectionChanged(const QString &)), attachedViewer(), SLOT(mainSelectionChanged(const QString &)));
3866 		gridLayoutAttachedViewsPage->removeWidget(attachedViewsWidget);
3867 		delete attachedViewsWidget;
3868 		attachedViewer()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
3869 		gridLayoutAttachedViewsPage->addWidget(attachedViewer(), 0, 0);
3870 		attachedViewsWidget = (QWidget *)attachedViewer();
3871 		attachedViewer()->loadView(name);
3872 	} else {
3873 		attachedViewer()->setVisible(true);
3874 		if ( name != attachedViewer()->name() ) {
3875 			attachedViewer()->saveView();
3876 			attachedViewer()->loadView(name);
3877 		}
3878 	}
3879 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
3880 	int index = componentInfo->appliedFeatureList().indexOf(QMC2_MACHINELIST_INDEX);
3881 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
3882 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
3883 	if ( index > 0 && embedIndex >= 0 && embedIndex <= index )
3884 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
3885 			index--;
3886 #endif
3887 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
3888 	if ( index > 0 && foreignIndex >= 0 && foreignIndex <= index )
3889 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
3890 			index--;
3891 	tabWidgetMachineList->blockSignals(true);
3892 	tabWidgetMachineList->setCurrentIndex(index);
3893 	tabWidgetMachineList->blockSignals(false);
3894 	tabWidgetMachineList->setTabIcon(index, QIcon(QString::fromUtf8(":/data/img/filtered_view.png")));
3895 	menuView->setIcon(QIcon(QString::fromUtf8(":/data/img/filtered_view.png")));
3896 	comboBoxViewSelect->blockSignals(true);
3897 	comboBoxViewSelect->setCurrentIndex(MachineListViewer::viewSelectSeparatorIndex() + MachineListViewer::attachedViews().indexOf(name) + 1);
3898 	comboBoxViewSelect->blockSignals(false);
3899 	attachedViewer()->treeView->setFocus();
3900 }
3901 
attachedViewAction_triggered(bool)3902 void MainWindow::attachedViewAction_triggered(bool)
3903 {
3904 	QAction *a = (QAction *)sender();
3905 	if ( a ) {
3906 		comboBoxViewSelect->blockSignals(true);
3907 		comboBoxViewSelect->setCurrentIndex(MachineListViewer::viewSelectSeparatorIndex() + MachineListViewer::attachedViews().indexOf(a->text()) + 1);
3908 		comboBoxViewSelect->blockSignals(false);
3909 		showAttachedView(a->text());
3910 	}
3911 }
3912 
on_tabWidgetMachineDetail_currentChanged(int currentIndex)3913 void MainWindow::on_tabWidgetMachineDetail_currentChanged(int currentIndex)
3914 {
3915 	static bool initialCall = true;
3916 
3917 	// avoids crashes on critical sections
3918 	if ( qmc2CriticalSection ) {
3919 		retry_tabWidgetMachineDetail_currentIndex = currentIndex;
3920 		QTimer::singleShot(QMC2_CRITSECT_POLLING_TIME, this, SLOT(retry_tabWidgetMachineDetail_currentChanged()));
3921 		return;
3922 	}
3923 
3924 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
3925 
3926 	if ( qmc2CleaningUp || componentInfo->appliedFeatureList().isEmpty() || currentIndex == -1 )
3927 		return;
3928 
3929 	if ( !qmc2CurrentItem || qmc2EarlyReloadActive ) {
3930 		qmc2LastMachineInfoItem = qmc2LastEmuInfoItem = qmc2LastSoftwareInfoItem = qmc2LastConfigItem = qmc2LastDeviceConfigItem = qmc2LastSoftwareListItem = 0;
3931 		return;
3932 	}
3933 
3934 	// paranoia :)
3935 	QTreeWidgetItem *ci = treeWidgetMachineList->currentItem();
3936 	if ( !ci )
3937 		return;
3938 	if ( !ci->isSelected() )
3939 		return;
3940 	while ( ci->parent() )
3941 		ci = ci->parent();
3942 	qmc2CurrentItem = ci;
3943 	if ( qmc2CurrentItem->childCount() <= 0 )
3944 		return;
3945 
3946 	emit updateDetailTabBar(currentIndex);
3947 
3948 	// show / hide machine status indicator
3949 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicator").toBool() ) {
3950 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/MachineStatusIndicatorOnlyWhenRequired").toBool() ) {
3951 			if ( hSplitter->sizes().first() == 0 || tabWidgetMachineList->indexOf(tabMachineList) != tabWidgetMachineList->currentIndex() )
3952 				labelMachineStatus->setVisible(true);
3953 			else
3954 				labelMachineStatus->setVisible(false);
3955 		} else
3956 			labelMachineStatus->setVisible(true);
3957 	} else
3958 		labelMachineStatus->setVisible(false);
3959 
3960 	QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
3961 	if ( !m_ignoreSelectionChange )
3962 		emit selectionChanged(machineName);
3963 	else foreach (MachineListViewer *v, machineListViewers)
3964 		if ( v != m_lastMlvSender )
3965 			v->mainSelectionChanged(machineName);
3966 	m_ignoreSelectionChange = false;
3967 	m_lastMlvSender = 0;
3968 
3969 	// setup status indicator color
3970 	switch ( qmc2MachineList->romState(machineName) ) {
3971 		case 'C':
3972 			labelMachineStatus->setPalette(qmc2StatusColorGreen);
3973 			break;
3974 		case 'M':
3975 			labelMachineStatus->setPalette(qmc2StatusColorYellowGreen);
3976 			break;
3977 		case 'I':
3978 			labelMachineStatus->setPalette(qmc2StatusColorRed);
3979 			break;
3980 		case 'N':
3981 			labelMachineStatus->setPalette(qmc2StatusColorGrey);
3982 			break;
3983 		case 'U':
3984 		default:
3985 			labelMachineStatus->setPalette(qmc2StatusColorBlue);
3986 			break;
3987 	}
3988 
3989 	// 'special widgets': switch back to the default page if applicable
3990 	switch ( componentInfo->appliedFeatureList().at(tabWidgetMachineDetail->currentIndex()) )
3991 	{
3992 		case QMC2_SOFTWARE_LIST_INDEX:
3993 			if ( qmc2SoftwareList && qmc2CurrentItem == qmc2LastSoftwareListItem )
3994 				qmc2SoftwareList->on_toolButtonToggleSoftwareInfo_clicked(qmc2SoftwareList->toolButtonToggleSoftwareInfo->isChecked());
3995 			else
3996 				stackedWidgetSpecial_setCurrentIndex(QMC2_SPECIAL_DEFAULT_PAGE);
3997 			break;
3998 
3999 		default:
4000 			stackedWidgetSpecial_setCurrentIndex(QMC2_SPECIAL_DEFAULT_PAGE);
4001 			break;
4002 	}
4003 
4004 #if defined(QMC2_YOUTUBE_ENABLED)
4005 	// depending on the codec, an unused YT widget may still cause load on the system, so we destroy it when it's no longer required...
4006 	if ( componentInfo->appliedFeatureList().at(currentIndex) != QMC2_YOUTUBE_INDEX ) {
4007 		if ( qmc2YouTubeWidget && qmc2CurrentItem != qmc2LastYouTubeItem ) {
4008 			qmc2YouTubeWidget->saveSettings();
4009 			qmc2YouTubeWidget->forcedExit = true;
4010 			if ( qmc2YouTubeWidget->isPlaying() || qmc2YouTubeWidget->isPaused() )
4011 				qmc2YouTubeWidget->stop();
4012 			QLayout *vbl = tabYouTube->layout();
4013 			if ( vbl )
4014 				delete vbl;
4015 			qmc2YouTubeWidget->close();
4016 			qmc2YouTubeWidget->deleteLater();;
4017 			qmc2YouTubeWidget = 0;
4018 			qmc2LastYouTubeItem = 0;
4019 		}
4020 	}
4021 #endif
4022 
4023 	if ( !m_ignoreDetailTabChange && componentInfo->appliedFeatureList().at(currentIndex) != QMC2_SYSTEM_NOTES_INDEX ) {
4024 		if ( qmc2SystemNotesEditor ) {
4025 			qmc2SystemNotesEditor->hideTearOffMenus();
4026 			qmc2SystemNotesEditor->hide();
4027 		}
4028 	} else if ( qmc2SystemNotesEditor ) {
4029 		qmc2SystemNotesEditor->show();
4030 		qmc2SystemNotesEditor->raise();
4031 	}
4032 
4033 	qmc2UseDefaultEmulator = qmc2Config->value(QString(QMC2_EMULATOR_PREFIX + "Configuration/%1/SelectedEmulator").arg(machineName), tr("Default")).toString() == tr("Default");
4034 
4035 	int left, top, right, bottom;
4036 	switch ( componentInfo->appliedFeatureList().at(currentIndex) ) {
4037 #if defined(QMC2_YOUTUBE_ENABLED)
4038 		case QMC2_YOUTUBE_INDEX:
4039 			if ( !m_videoInfoMapLoaded )
4040 				loadYouTubeVideoInfoMap();
4041 			if ( qmc2CurrentItem != qmc2LastYouTubeItem ) {
4042 				tabYouTube->setUpdatesEnabled(false);
4043 				QString setID(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
4044 				QString setName(qmc2MachineListItemHash.value(setID)->text(QMC2_MACHINELIST_COLUMN_MACHINE));
4045 				if ( !qmc2YouTubeWidget ) {
4046 					gridLayout->getContentsMargins(&left, &top, &right, &bottom);
4047 					QVBoxLayout *layout = new QVBoxLayout;
4048 					layout->setContentsMargins(left, top, right, bottom);
4049 					qmc2YouTubeWidget = new YouTubeVideoPlayer(setID, setName, tabYouTube);
4050 					layout->addWidget(qmc2YouTubeWidget);
4051 					tabYouTube->setLayout(layout);
4052 					qmc2YouTubeWidget->show();
4053 				} else
4054 					qmc2YouTubeWidget->reload(setID, setName);
4055 				qmc2LastYouTubeItem = qmc2CurrentItem;
4056 				tabYouTube->setUpdatesEnabled(true);
4057 			}
4058 			break;
4059 #endif
4060 
4061 		case QMC2_SOFTWARE_LIST_INDEX:
4062 #if defined(QMC2_YOUTUBE_ENABLED)
4063 			if ( qmc2YouTubeWidget )
4064 				qmc2YouTubeWidget->clearMessage();
4065 #endif
4066 			if ( qmc2SoftwareList ) {
4067 				if ( qmc2SoftwareList->isInitialLoad ) {
4068 					QTimer::singleShot(0, this, SLOT(softwareLoadInterrupted()));
4069 					return;
4070 				}
4071 				if ( qmc2SoftwareList->isLoading || isCreatingSoftList ) {
4072 					qmc2SoftwareList->interruptLoad = true;
4073 					qmc2LastSoftwareListItem = 0;
4074 					QTimer::singleShot(0, this, SLOT(softwareLoadInterrupted()));
4075 					return;
4076 				}
4077 			}
4078 			if ( qmc2CurrentItem != qmc2LastSoftwareListItem && !isCreatingSoftList ) {
4079 				tabWidgetMachineDetail->setMovable(false);
4080 				QTreeWidgetItem *ci = qmc2CurrentItem;
4081 				isCreatingSoftList = true;
4082 				tabSoftwareList->setUpdatesEnabled(false);
4083 				if ( qmc2SoftwareList ) {
4084 					qmc2ShortcutHash["F10"].second = 0;
4085 					qmc2SoftwareList->save();
4086 					QLayout *vbl = tabSoftwareList->layout();
4087 					if ( vbl )
4088 						delete vbl;
4089 					delete qmc2SoftwareList;
4090 					qmc2SoftwareList = 0;
4091 				}
4092 				gridLayout->getContentsMargins(&left, &top, &right, &bottom);
4093 				QVBoxLayout *layout = new QVBoxLayout;
4094 				layout->setContentsMargins(left, top, right, bottom);
4095 				qmc2SoftwareList = new SoftwareList(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME), tabSoftwareList);
4096 				layout->addWidget(qmc2SoftwareList);
4097 				tabSoftwareList->setLayout(layout);
4098 				qmc2SoftwareList->show();
4099 				tabSoftwareList->setUpdatesEnabled(true);
4100 				isCreatingSoftList = false;
4101 				tabWidgetMachineDetail->setMovable(true);
4102 				qmc2SoftwareList->load();
4103 				qmc2LastSoftwareListItem = ci;
4104 			}
4105 			break;
4106 
4107 		case QMC2_DEVICE_INDEX:
4108 #if defined(QMC2_YOUTUBE_ENABLED)
4109 			if ( qmc2YouTubeWidget )
4110 				qmc2YouTubeWidget->clearMessage();
4111 #endif
4112 			if ( qmc2CurrentItem != qmc2LastDeviceConfigItem ) {
4113 				tabDevices->setUpdatesEnabled(false);
4114 				if ( qmc2DeviceConfigurator ) {
4115 					qmc2DeviceConfigurator->save();
4116 					qmc2DeviceConfigurator->saveSetup();
4117 				}
4118 				if ( !qmc2DeviceConfigurator ) {
4119 					// FIXME: remove this "fixme" warning when the device configurator works again
4120 					log(QMC2_LOG_FRONTEND, "FIXME: The new implementation of the device configurator doesn't work properly yet!");
4121 					gridLayout->getContentsMargins(&left, &top, &right, &bottom);
4122 					QVBoxLayout *layout = new QVBoxLayout;
4123 					layout->setContentsMargins(left, top, right, bottom);
4124 					qmc2DeviceConfigurator = new DeviceConfigurator(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME), tabDevices);
4125 					connect(&messDevCfgTimer, SIGNAL(timeout()), qmc2DeviceConfigurator, SLOT(load()));
4126 					layout->addWidget(qmc2DeviceConfigurator);
4127 					if ( !tabDevices->layout() )
4128 						tabDevices->setLayout(layout);
4129 					qmc2DeviceConfigurator->show();
4130 				} else
4131 					qmc2DeviceConfigurator->setCurrentMachine(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
4132 				qmc2LastDeviceConfigItem = qmc2CurrentItem;
4133 				messDevCfgTimer.start(QMC2_DEVCONFIG_LOAD_DELAY);
4134 				tabDevices->setUpdatesEnabled(true);
4135 			}
4136 			break;
4137 
4138 		case QMC2_PROJECTMESS_INDEX:
4139 #if defined(QMC2_YOUTUBE_ENABLED)
4140 			if ( qmc2YouTubeWidget )
4141 				qmc2YouTubeWidget->clearMessage();
4142 #endif
4143 			if ( qmc2CurrentItem != qmc2LastProjectMESSItem ) {
4144 				tabProjectMESS->setUpdatesEnabled(false);
4145 				if ( qmc2ProjectMESSLookup ) {
4146 					QLayout *vbl = tabProjectMESS->layout();
4147 					if ( vbl )
4148 						delete vbl;
4149 					qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "ProjectMESS/Zoom", qmc2ProjectMESSLookup->spinBoxZoom->value());
4150 					delete qmc2ProjectMESSLookup;
4151 					qmc2ProjectMESSLookup = 0;
4152 				}
4153 				gridLayout->getContentsMargins(&left, &top, &right, &bottom);
4154 				QVBoxLayout *layout = new QVBoxLayout;
4155 				layout->setContentsMargins(left, top, right, bottom);
4156 				qmc2ProjectMESSLookup = new MiniWebBrowser(tabProjectMESS);
4157 				qmc2ProjectMESSLookup->spinBoxZoom->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "ProjectMESS/Zoom", 100).toInt());
4158 				layout->addWidget(qmc2ProjectMESSLookup);
4159 				tabProjectMESS->setLayout(layout);
4160 				QString projectMessUrl;
4161 				QColor color = qmc2ProjectMESSLookup->webViewBrowser->palette().color(QPalette::WindowText);
4162 				QString machName = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME);
4163 				qmc2ProjectMESSLookup->webViewBrowser->setStatusTip(tr("ProjectMESS page for system '%1'").arg(machName));
4164 				if ( !qmc2ProjectMESSCache.contains(machName) ) {
4165 					projectMessUrl = QString(QMC2_PROJECTMESS_PATTERN_URL).arg(machName);
4166 					qmc2ProjectMESSLookup->webViewBrowser->setHtml(
4167 							QString("<html><head></head><body><center><p><font color=\"#%1%2%3\"<b>").arg(color.red()).arg(color.green()).arg(color.blue()) +
4168 							tr("Fetching ProjectMESS page for system '%1', please wait...").arg(machName) +
4169 							"</font></b></p><p>" + QString("(<a href=\"%1\">%1</a>)").arg(projectMessUrl) + "</p></center></body></html>",
4170 							QUrl(projectMessUrl));
4171 					qmc2ProjectMESSLookup->webViewBrowser->load(QUrl(projectMessUrl));
4172 				} else {
4173 					projectMessUrl = QString(QMC2_PROJECTMESS_PATTERN_URL).arg(machName);
4174 					qmc2ProjectMESSLookup->webViewBrowser->setHtml(QString(QMC2_UNCOMPRESS(*qmc2ProjectMESSCache[machName])), QUrl(projectMessUrl));
4175 					qmc2ProjectMESSLookup->webViewBrowser->load(QUrl(projectMessUrl));
4176 				}
4177 				qmc2LastProjectMESSItem = qmc2CurrentItem;
4178 				connect(qmc2ProjectMESSLookup->webViewBrowser, SIGNAL(loadFinished(bool)), this, SLOT(projectMessSystemLoadFinished(bool)));
4179 				connect(qmc2ProjectMESSLookup->webViewBrowser, SIGNAL(loadStarted()), this, SLOT(projectMessSystemLoadStarted()));
4180 				tabProjectMESS->setUpdatesEnabled(true);
4181 			}
4182 			break;
4183 
4184 		case QMC2_CONFIG_INDEX:
4185 #if defined(QMC2_YOUTUBE_ENABLED)
4186 			if ( qmc2YouTubeWidget )
4187 				qmc2YouTubeWidget->clearMessage();
4188 #endif
4189 			if ( qmc2CurrentItem != qmc2LastConfigItem ) {
4190 				QWidget *configWidget = componentInfo->widget(QMC2_CONFIG_INDEX);
4191 
4192 				configWidget->setUpdatesEnabled(false);
4193 
4194 				// save & cleanup existing game/machine specific emulator settings
4195 				QString selectedEmulator;
4196 				if ( qmc2EmulatorOptions ) {
4197 					qmc2EmulatorOptions->save();
4198 					selectedEmulator = comboBoxEmuSelector->currentText();
4199 					if ( selectedEmulator == tr("Default") || selectedEmulator.isEmpty() )
4200 						qmc2Config->remove(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator");
4201 					else
4202 						qmc2Config->setValue(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator", selectedEmulator);
4203 					QLayout *vbl = configWidget->layout();
4204 					if ( vbl )
4205 						delete vbl;
4206 					delete labelEmuSelector;
4207 					delete comboBoxEmuSelector;
4208 					comboBoxEmuSelector = 0;
4209 					delete qmc2EmulatorOptions;
4210 					delete pushButtonCurrentEmulatorOptionsExportToFile;
4211 					delete pushButtonCurrentEmulatorOptionsImportFromFile;
4212 					qmc2EmulatorOptions = 0;
4213 				}
4214 				gridLayout->getContentsMargins(&left, &top, &right, &bottom);
4215 				QVBoxLayout *layout = new QVBoxLayout;
4216 				layout->setContentsMargins(left, top, right, bottom);
4217 				configWidget->setLayout(layout);
4218 
4219 				// emulator selector (default, or one of the registered emulators)
4220 				labelEmuSelector = new QLabel(tr("Emulator for this machine") + ":", configWidget);
4221 				labelEmuSelector->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
4222 				comboBoxEmuSelector = new QComboBox(configWidget);
4223 				comboBoxEmuSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
4224 				qmc2Config->beginGroup(QMC2_EMULATOR_PREFIX + "RegisteredEmulators");
4225 				QStringList registeredEmulators(qmc2Config->childGroups());
4226 				qmc2Config->endGroup();
4227 				registeredEmulators.prepend(tr("Default"));
4228 				comboBoxEmuSelector->insertItems(0, registeredEmulators);
4229 				QHBoxLayout *emuSelectorLayout = new QHBoxLayout();
4230 				emuSelectorLayout->addWidget(labelEmuSelector);
4231 				emuSelectorLayout->addWidget(comboBoxEmuSelector);
4232 				layout->addLayout(emuSelectorLayout);
4233 				connect(comboBoxEmuSelector, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(emuSelector_currentIndexChanged(const QString &)));
4234 
4235 				// emulator options
4236 				qmc2EmulatorOptions = new EmulatorOptions(QMC2_EMULATOR_PREFIX + "Configuration/" + machineName, configWidget);
4237 				qmc2EmulatorOptions->load();
4238 
4239 				QString defaultChoice;
4240 				QStringList biosSets(getXmlChoices(machineName, "biosset", "name", &defaultChoice));
4241 				QStringList biosDescriptions(getXmlChoices(machineName, "biosset", "description"));
4242 				for (int i = 0; i < biosSets.count(); i++) {
4243 					biosDescriptions[i] = biosSets[i] + " - " + biosDescriptions[i];
4244 					if ( biosSets[i] == defaultChoice )
4245 						biosDescriptions[i] += " / " + tr("default");
4246 				}
4247 				qmc2EmulatorOptions->addChoices("bios", biosSets, biosDescriptions, defaultChoice);
4248 
4249 				QStringList ramSizes(getXmlChoices(machineName, "ramoption", QString(), &defaultChoice));
4250 				std::sort(ramSizes.begin(), ramSizes.end(), MainWindow::qStringListLessThan);
4251 				QStringList humanReadableRamSizes;
4252 				for (int i = 0; i < ramSizes.count(); i++) {
4253 					if ( ramSizes.at(i) == defaultChoice )
4254 						humanReadableRamSizes << ROMAlyzer::humanReadable(ramSizes.at(i).toULongLong(), 0) + " / " + tr("default");
4255 					else
4256 						humanReadableRamSizes << ROMAlyzer::humanReadable(ramSizes.at(i).toULongLong(), 0);
4257 				}
4258 				qmc2EmulatorOptions->addChoices("ramsize", ramSizes, humanReadableRamSizes, defaultChoice, false);
4259 
4260 				layout->addWidget(qmc2EmulatorOptions);
4261 
4262 				// import/export buttons
4263 				QHBoxLayout *buttonLayout = new QHBoxLayout();
4264 				pushButtonCurrentEmulatorOptionsExportToFile = new QPushButton(tr("Export to..."), this);
4265 				pushButtonCurrentEmulatorOptionsExportToFile->setToolTip(QObject::tr("Export machine-specific MAME configuration"));
4266 				pushButtonCurrentEmulatorOptionsExportToFile->setStatusTip(QObject::tr("Export machine-specific MAME configuration"));
4267 				pushButtonCurrentEmulatorOptionsImportFromFile = new QPushButton(QObject::tr("Import from..."), this);
4268 				pushButtonCurrentEmulatorOptionsImportFromFile->setToolTip(QObject::tr("Import machine-specific MAME configuration"));
4269 				pushButtonCurrentEmulatorOptionsImportFromFile->setStatusTip(QObject::tr("Import machine-specific MAME configuration"));
4270 				buttonLayout->addWidget(pushButtonCurrentEmulatorOptionsExportToFile);
4271 				buttonLayout->addWidget(pushButtonCurrentEmulatorOptionsImportFromFile);
4272 				layout->addLayout(buttonLayout);
4273 
4274 				// import/export menus
4275 				qmc2MainWindow->selectMenuCurrentEmulatorOptionsExportToFile = new QMenu(qmc2MainWindow->pushButtonCurrentEmulatorOptionsExportToFile);
4276 				connect(qmc2MainWindow->selectMenuCurrentEmulatorOptionsExportToFile->addAction(QIcon(QString::fromUtf8(":/data/img/work.png")), tr("<inipath>/%1.ini").arg(machineName)), SIGNAL(triggered()), qmc2MainWindow, SLOT(pushButtonCurrentEmulatorOptionsExportToFile_clicked()));
4277 				connect(qmc2MainWindow->selectMenuCurrentEmulatorOptionsExportToFile->addAction(QIcon(QString::fromUtf8(":/data/img/fileopen.png")), tr("Select file...")), SIGNAL(triggered()), qmc2MainWindow, SLOT(pushButtonCurrentEmulatorOptionsSelectExportFile_clicked()));
4278 				qmc2MainWindow->pushButtonCurrentEmulatorOptionsExportToFile->setMenu(qmc2MainWindow->selectMenuCurrentEmulatorOptionsExportToFile);
4279 				qmc2MainWindow->selectMenuCurrentEmulatorOptionsImportFromFile = new QMenu(qmc2MainWindow->pushButtonCurrentEmulatorOptionsImportFromFile);
4280 				connect(qmc2MainWindow->selectMenuCurrentEmulatorOptionsImportFromFile->addAction(QIcon(QString::fromUtf8(":/data/img/work.png")), tr("<inipath>/%1.ini").arg(machineName)), SIGNAL(triggered()), qmc2MainWindow, SLOT(pushButtonCurrentEmulatorOptionsImportFromFile_clicked()));
4281 				connect(qmc2MainWindow->selectMenuCurrentEmulatorOptionsImportFromFile->addAction(QIcon(QString::fromUtf8(":/data/img/fileopen.png")), tr("Select file...")), SIGNAL(triggered()), qmc2MainWindow, SLOT(pushButtonCurrentEmulatorOptionsSelectImportFile_clicked()));
4282 				qmc2MainWindow->pushButtonCurrentEmulatorOptionsImportFromFile->setMenu(qmc2MainWindow->selectMenuCurrentEmulatorOptionsImportFromFile);
4283 				qmc2LastConfigItem = qmc2CurrentItem;
4284 
4285 				// select the emulator to be used, if applicable
4286 				if ( registeredEmulators.count() > 1 ) {
4287 					if ( qmc2Config->contains(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator") ) {
4288 						selectedEmulator = qmc2Config->value(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator").toString();
4289 						if ( !selectedEmulator.isEmpty() && registeredEmulators.contains(selectedEmulator) ) {
4290 							int emuIndex = comboBoxEmuSelector->findText(selectedEmulator);
4291 							if ( emuIndex >= 0 )
4292 								comboBoxEmuSelector->setCurrentIndex(emuIndex);
4293 							else
4294 								comboBoxEmuSelector->setCurrentIndex(0);
4295 						}
4296 					}
4297 				}
4298 
4299 				// finally show the widgets...
4300 				labelEmuSelector->show();
4301 				comboBoxEmuSelector->show();
4302 				qmc2EmulatorOptions->show();
4303 				pushButtonCurrentEmulatorOptionsExportToFile->show();
4304 				pushButtonCurrentEmulatorOptionsImportFromFile->show();
4305 
4306 				configWidget->setUpdatesEnabled(true);
4307 				configWidget->update();
4308 
4309 				qmc2EmulatorOptions->horizontalScrollBar()->setSliderPosition(qmc2EmulatorOptions->horizontalScrollPosition);
4310 				qmc2EmulatorOptions->verticalScrollBar()->setSliderPosition(qmc2EmulatorOptions->verticalScrollPosition);
4311 			}
4312 			break;
4313 
4314 		case QMC2_MACHINEINFO_INDEX:
4315 #if defined(QMC2_YOUTUBE_ENABLED)
4316 			if ( qmc2YouTubeWidget )
4317 				qmc2YouTubeWidget->clearMessage();
4318 #endif
4319 			if ( qmc2CurrentItem != qmc2LastMachineInfoItem ) {
4320 				tabGameInfo->setUpdatesEnabled(false);
4321 				QString machineInfoKey(machineName);
4322 				if ( !qmc2MachineList->datInfoDb()->existsMachineInfo(machineInfoKey) ) {
4323 					machineInfoKey = qmc2ParentHash.value(machineName);
4324 					if ( !qmc2MachineList->datInfoDb()->existsMachineInfo(machineInfoKey) )
4325 						machineInfoKey.clear();
4326 				}
4327 				if ( !machineInfoKey.isEmpty() ) {
4328 					QString gameInfoText = qmc2MachineList->datInfoDb()->machineInfo(machineInfoKey);
4329 					if ( !gameInfoText.isEmpty() ) {
4330 						QString emulator = qmc2MachineList->datInfoDb()->machineInfoEmulator(machineInfoKey);
4331 						if ( emulator == "MESS" )
4332 							textBrowserMachineInfo->setHtml(messWikiToHtml(gameInfoText));
4333 						else
4334 							textBrowserMachineInfo->setHtml(gameInfoText.replace(QRegExp(QString("((http|https|ftp)://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>")));
4335 					} else
4336 						textBrowserMachineInfo->setHtml("<h2>" + qmc2MachineListItemHash.value(machineName)->text(QMC2_MACHINELIST_COLUMN_MACHINE) + "</h2>" + tr("<p>No data available</p>"));
4337 				} else
4338 					textBrowserMachineInfo->setHtml("<h2>" + qmc2MachineListItemHash.value(machineName)->text(QMC2_MACHINELIST_COLUMN_MACHINE) + "</h2>" + tr("<p>No data available</p>"));
4339 				qmc2LastMachineInfoItem = qmc2CurrentItem;
4340 				tabGameInfo->setUpdatesEnabled(true);
4341 			}
4342 			break;
4343 
4344 		case QMC2_EMUINFO_INDEX:
4345 #if defined(QMC2_YOUTUBE_ENABLED)
4346 			if ( qmc2YouTubeWidget )
4347 				qmc2YouTubeWidget->clearMessage();
4348 #endif
4349 			if ( qmc2CurrentItem != qmc2LastEmuInfoItem ) {
4350 				tabEmuInfo->setUpdatesEnabled(false);
4351 				QString emuInfoKey(machineName);
4352 				if ( !qmc2MachineList->datInfoDb()->existsEmuInfo(emuInfoKey) ) {
4353 					emuInfoKey = qmc2ParentHash.value(machineName);
4354 					if ( !qmc2MachineList->datInfoDb()->existsEmuInfo(emuInfoKey) )
4355 						emuInfoKey.clear();
4356 				}
4357 				if ( !emuInfoKey.isEmpty() ) {
4358 					QString emuInfoText = qmc2MachineList->datInfoDb()->emuInfo(emuInfoKey);
4359 					if ( !emuInfoText.isEmpty() )
4360 						textBrowserEmuInfo->setHtml(emuInfoText.replace(QRegExp(QString("(\\w+://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>")));
4361 					else
4362 						textBrowserEmuInfo->setHtml(tr("No data available"));
4363 				} else
4364 					textBrowserEmuInfo->setHtml(tr("No data available"));
4365 				qmc2LastEmuInfoItem = qmc2CurrentItem;
4366 				tabEmuInfo->setUpdatesEnabled(true);
4367 			}
4368 			break;
4369 
4370 		case QMC2_SYSTEM_NOTES_INDEX:
4371 #if defined(QMC2_YOUTUBE_ENABLED)
4372 			if ( qmc2YouTubeWidget )
4373 				qmc2YouTubeWidget->clearMessage();
4374 #endif
4375 			if ( qmc2CurrentItem != qmc2LastSystemNotesItem ) {
4376 				qmc2LastSystemNotesItem = qmc2CurrentItem;
4377 				if ( !qmc2SystemNotesEditor ) {
4378 					int tabIndex = tabWidgetMachineDetail->indexOf(componentInfo->widget(QMC2_SYSTEM_NOTES_INDEX));
4379 					tabWidgetMachineDetail->setUpdatesEnabled(false);
4380 					tabWidgetMachineDetail->removeTab(tabIndex);
4381 					qmc2SystemNotesEditor = new HtmlEditor("SystemNotes", true);
4382 					tabWidgetMachineDetail->insertTab(tabIndex, qmc2SystemNotesEditor, QIcon(QString::fromUtf8(":/data/img/notes.png")), tr("&Notes"));
4383 					tabWidgetMachineDetail->setCurrentIndex(tabIndex);
4384 					tabWidgetMachineDetail->setUpdatesEnabled(true);
4385 					qmc2SystemNotesEditor->move(0, 0);
4386 					qmc2SystemNotesEditor->resize(qmc2SystemNotesEditor->parentWidget()->size());
4387 					qmc2SystemNotesEditor->show();
4388 					qmc2SystemNotesEditor->raise();
4389 				} else {
4390 					qmc2SystemNotesEditor->save();
4391 					qmc2SystemNotesEditor->loadedContent.clear();
4392 					qmc2SystemNotesEditor->checkRevertStatus();
4393 				}
4394 
4395 				qmc2SystemNotesEditor->stopLoading = true;
4396 				bool useSystemNotesTemplate = qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/UseSystemNotesTemplate").toBool();
4397 				QString fileName(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/SystemNotesFolder").toString() + machineName + ".html");
4398 				qmc2SystemNotesEditor->setCurrentFileName(fileName);
4399 				QString parentSystem(qmc2ParentHash.value(machineName));
4400 
4401 				qmc2SystemNotesEditor->enableFileNewFromTemplateAction(useSystemNotesTemplate);
4402 
4403 				qmc2SystemNotesEditor->templateMap.clear();
4404 #if QT_VERSION < 0x050000
4405 				qmc2SystemNotesEditor->templateMap["$DESCRIPTION$"] = Qt::escape(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE));
4406 				qmc2SystemNotesEditor->templateMap["$MANUFACTURER$"] = Qt::escape(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MANU));
4407 				qmc2SystemNotesEditor->templateMap["$YEAR$"] = Qt::escape(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_YEAR));
4408 				qmc2SystemNotesEditor->templateMap["$CATEGORY$"] = Qt::escape(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_CATEGORY));
4409 #else
4410 				qmc2SystemNotesEditor->templateMap["$DESCRIPTION$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE).toHtmlEscaped();
4411 				qmc2SystemNotesEditor->templateMap["$MANUFACTURER$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MANU).toHtmlEscaped();
4412 				qmc2SystemNotesEditor->templateMap["$YEAR$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_YEAR).toHtmlEscaped();
4413 				qmc2SystemNotesEditor->templateMap["$CATEGORY$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_CATEGORY).toHtmlEscaped();
4414 #endif
4415 				qmc2SystemNotesEditor->templateMap["$ID$"] = machineName;
4416 				qmc2SystemNotesEditor->templateMap["$PARENT_ID$"] = parentSystem;
4417 #if QT_VERSION < 0x050000
4418 				qmc2SystemNotesEditor->templateMap["$VERSION$"] = Qt::escape(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_VERSION));
4419 #else
4420 				qmc2SystemNotesEditor->templateMap["$VERSION$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_VERSION).toHtmlEscaped();
4421 #endif
4422 				qmc2SystemNotesEditor->templateMap["$PLAYERS$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_PLAYERS);
4423 				qmc2SystemNotesEditor->templateMap["$ROM_TYPES$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_RTYPES);
4424 				qmc2SystemNotesEditor->templateMap["$DRIVER_STATUS$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_DRVSTAT);
4425 				qmc2SystemNotesEditor->templateMap["$DRIVER_STATUS_UT$"] = MachineList::reverseTranslations.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_DRVSTAT));
4426 				qmc2SystemNotesEditor->templateMap["$ROM_STATUS$"] = qmc2MachineList->romStatus(machineName, true);
4427 				qmc2SystemNotesEditor->templateMap["$ROM_STATUS_UT$"] = qmc2MachineList->romStatus(machineName, false);
4428 				qmc2SystemNotesEditor->templateMap["$IS_BIOS$"] = qmc2MachineList->isBios(machineName) ? "true" : "false";
4429 				qmc2SystemNotesEditor->templateMap["$IS_DEVICE$"] = qmc2MachineList->isDevice(machineName) ? "true" : "false";
4430 				qmc2SystemNotesEditor->templateMap["$GUI_LANGUAGE$"] = qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Language", "us").toString();
4431 				qmc2SystemNotesEditor->templateMap["$EMULATOR_VARIANT$"] = QMC2_EMU_NAME_VARIANT;
4432 				qmc2SystemNotesEditor->templateMap["$EMULATOR_TYPE$"] = QMC2_EMU_NAME;
4433 				qmc2SystemNotesEditor->templateMap["$SOURCE_FILE$"] = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_SRCFILE);
4434 				QDir dataDir(qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/DataDirectory").toString());
4435 				QString ghostPath(QDir::fromNativeSeparators(dataDir.absolutePath() + "/img/ghost.png"));
4436 #if defined(QMC2_OS_WIN)
4437 				qmc2SystemNotesEditor->templateMap["$GHOST_IMAGE$"] = "file:///" + ghostPath;
4438 #else
4439 				qmc2SystemNotesEditor->templateMap["$GHOST_IMAGE$"] = "file://" + ghostPath;
4440 #endif
4441 				QString videoThumbnailPath(QDir::fromNativeSeparators(dataDir.absolutePath() + "/img/video_thumbnail.png"));
4442 #if defined(QMC2_OS_WIN)
4443 				qmc2SystemNotesEditor->templateMap["$VIDEO_THUMBNAIL$"] = "file:///" + videoThumbnailPath;
4444 #else
4445 				qmc2SystemNotesEditor->templateMap["$VIDEO_THUMBNAIL$"] = "file://" + videoThumbnailPath;
4446 #endif
4447 				QString filePath;
4448 				if ( qmc2Preview ) {
4449 #if defined(QMC2_OS_WIN)
4450 					if ( qmc2Preview->loadImage(machineName, machineName, true, &filePath, false) )
4451 						qmc2SystemNotesEditor->templateMap["$PREVIEW_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4452 					else
4453 						qmc2SystemNotesEditor->templateMap["$PREVIEW_IMAGE$"] = "file:///" + ghostPath;
4454 #else
4455 					if ( qmc2Preview->loadImage(machineName, machineName, true, &filePath, false) )
4456 						qmc2SystemNotesEditor->templateMap["$PREVIEW_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4457 					else
4458 						qmc2SystemNotesEditor->templateMap["$PREVIEW_IMAGE$"] = "file://" + ghostPath;
4459 #endif
4460 				}
4461 				if ( qmc2Flyer ) {
4462 #if defined(QMC2_OS_WIN)
4463 					if ( qmc2Flyer->loadImage(machineName, machineName, true, &filePath, false) )
4464 						qmc2SystemNotesEditor->templateMap["$FLYER_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4465 					else
4466 						qmc2SystemNotesEditor->templateMap["$FLYER_IMAGE$"] = "file:///" + ghostPath;
4467 #else
4468 					if ( qmc2Flyer->loadImage(machineName, machineName, true, &filePath, false) )
4469 						qmc2SystemNotesEditor->templateMap["$FLYER_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4470 					else
4471 						qmc2SystemNotesEditor->templateMap["$FLYER_IMAGE$"] = "file://" + ghostPath;
4472 #endif
4473 				}
4474 				if ( qmc2Cabinet ) {
4475 #if defined(QMC2_OS_WIN)
4476 					if ( qmc2Cabinet->loadImage(machineName, machineName, true, &filePath, false) )
4477 						qmc2SystemNotesEditor->templateMap["$CABINET_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4478 					else
4479 						qmc2SystemNotesEditor->templateMap["$CABINET_IMAGE$"] = "file:///" + ghostPath;
4480 #else
4481 					if ( qmc2Cabinet->loadImage(machineName, machineName, true, &filePath, false) )
4482 						qmc2SystemNotesEditor->templateMap["$CABINET_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4483 					else
4484 						qmc2SystemNotesEditor->templateMap["$CABINET_IMAGE$"] = "file://" + ghostPath;
4485 #endif
4486 				}
4487 				if ( qmc2Controller ) {
4488 #if defined(QMC2_OS_WIN)
4489 					if ( qmc2Controller->loadImage(machineName, machineName, true, &filePath, false) )
4490 						qmc2SystemNotesEditor->templateMap["$CONTROLLER_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4491 					else
4492 						qmc2SystemNotesEditor->templateMap["$CONTROLLER_IMAGE$"] = "file:///" + ghostPath;
4493 #else
4494 					if ( qmc2Controller->loadImage(machineName, machineName, true, &filePath, false) )
4495 						qmc2SystemNotesEditor->templateMap["$CONTROLLER_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4496 					else
4497 						qmc2SystemNotesEditor->templateMap["$CONTROLLER_IMAGE$"] = "file://" + ghostPath;
4498 #endif
4499 				}
4500 				if ( qmc2Marquee ) {
4501 #if defined(QMC2_OS_WIN)
4502 					if ( qmc2Marquee->loadImage(machineName, machineName, true, &filePath, false) )
4503 						qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4504 					else
4505 						qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"] = "file:///" + ghostPath;
4506 					qmc2SystemNotesEditor->templateMap["$LOGO_IMAGE$"] = qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"];
4507 #else
4508 					if ( qmc2Marquee->loadImage(machineName, machineName, true, &filePath, false) )
4509 						qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4510 					else
4511 						qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"] = "file://" + ghostPath;
4512 					qmc2SystemNotesEditor->templateMap["$LOGO_IMAGE$"] = qmc2SystemNotesEditor->templateMap["$MARQUEE_IMAGE$"];
4513 #endif
4514 				}
4515 				if ( qmc2Title ) {
4516 #if defined(QMC2_OS_WIN)
4517 					if ( qmc2Title->loadImage(machineName, machineName, true, &filePath, false) )
4518 						qmc2SystemNotesEditor->templateMap["$TITLE_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4519 					else
4520 						qmc2SystemNotesEditor->templateMap["$TITLE_IMAGE$"] = "file:///" + ghostPath;
4521 #else
4522 					if ( qmc2Title->loadImage(machineName, machineName, true, &filePath, false) )
4523 						qmc2SystemNotesEditor->templateMap["$TITLE_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4524 					else
4525 						qmc2SystemNotesEditor->templateMap["$TITLE_IMAGE$"] = "file://" + ghostPath;
4526 #endif
4527 				}
4528 				if ( qmc2PCB ) {
4529 #if defined(QMC2_OS_WIN)
4530 					if ( qmc2PCB->loadImage(machineName, machineName, true, &filePath, false) )
4531 						qmc2SystemNotesEditor->templateMap["$PCB_IMAGE$"] = "file:///" + QDir::fromNativeSeparators(filePath);
4532 					else
4533 						qmc2SystemNotesEditor->templateMap["$PCB_IMAGE$"] = "file:///" + ghostPath;
4534 #else
4535 					if ( qmc2PCB->loadImage(machineName, machineName, true, &filePath, false) )
4536 						qmc2SystemNotesEditor->templateMap["$PCB_IMAGE$"] = "file://" + QDir::fromNativeSeparators(filePath);
4537 					else
4538 						qmc2SystemNotesEditor->templateMap["$PCB_IMAGE$"] = "file://" + ghostPath;
4539 #endif
4540 				}
4541 				QString emuInfoKey(machineName);
4542 				if ( !qmc2MachineList->datInfoDb()->existsEmuInfo(emuInfoKey) ) {
4543 					emuInfoKey = parentSystem;
4544 					if ( !qmc2MachineList->datInfoDb()->existsEmuInfo(emuInfoKey) )
4545 						emuInfoKey.clear();
4546 				}
4547 				if ( !emuInfoKey.isEmpty() ) {
4548 					QString emuInfoText = qmc2MachineList->datInfoDb()->emuInfo(emuInfoKey);
4549 					if ( !emuInfoText.isEmpty() ) {
4550 						qmc2SystemNotesEditor->templateMap["$EMU_INFO$"] = emuInfoText.replace(QRegExp(QString("(\\w+://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>"));
4551 						qmc2SystemNotesEditor->templateMap["$EMU_INFO_STATUS$"] = "OK";
4552 					} else {
4553 						qmc2SystemNotesEditor->templateMap["$EMU_INFO$"] = tr("No data available");
4554 						qmc2SystemNotesEditor->templateMap["$EMU_INFO_STATUS$"] = "NO_DATA";
4555 					}
4556 				} else {
4557 					qmc2SystemNotesEditor->templateMap["$EMU_INFO$"] = tr("No data available");
4558 					qmc2SystemNotesEditor->templateMap["$EMU_INFO_STATUS$"] = "NO_DATA";
4559 				}
4560 				QString videoSnapUrl;
4561 				foreach (QString videoSnapFolder, qmc2Config->value("MAME/FilesAndDirectories/VideoSnapFolder", QMC2_DEFAULT_DATA_PATH + "/vdo/").toString().split(";", QString::SkipEmptyParts)) {
4562 					foreach (QString formatExtension, videoSnapAllowedFormatExtensions) {
4563 						QFileInfo fi(QDir::cleanPath(videoSnapFolder + "/" + machineName + formatExtension));
4564 						if ( fi.exists() && fi.isReadable() ) {
4565 							videoSnapUrl = fi.absoluteFilePath();
4566 #if defined(QMC2_OS_WIN)
4567 							videoSnapUrl.prepend("file:///");
4568 #else
4569 							videoSnapUrl.prepend("file://");
4570 #endif
4571 							break;
4572 						}
4573 					}
4574 					if ( videoSnapUrl.isEmpty() ) { // parent fallback
4575 						if ( qmc2ParentImageFallback && qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/VideoFallback", 0).toInt() == 0 ) {
4576 							QString parentId = qmc2ParentHash.value(machineName);
4577 							if ( !parentId.isEmpty() ) {
4578 								foreach (QString formatExtension, videoSnapAllowedFormatExtensions) {
4579 									QFileInfo fi(QDir::cleanPath(videoSnapFolder + "/" + parentId + formatExtension));
4580 									if ( fi.exists() && fi.isReadable() ) {
4581 										videoSnapUrl = fi.absoluteFilePath();
4582 #if defined(QMC2_OS_WIN)
4583 										videoSnapUrl.prepend("file:///");
4584 #else
4585 										videoSnapUrl.prepend("file://");
4586 #endif
4587 										break;
4588 									}
4589 								}
4590 							}
4591 						}
4592 					}
4593 				}
4594 				qmc2SystemNotesEditor->templateMap["$VIDEO_SNAP_URL$"] = videoSnapUrl;
4595 				QString machineInfoKey(machineName);
4596 				if ( !qmc2MachineList->datInfoDb()->existsMachineInfo(machineInfoKey) ) {
4597 					machineInfoKey = parentSystem;
4598 					if ( !qmc2MachineList->datInfoDb()->existsMachineInfo(machineInfoKey) )
4599 						machineInfoKey.clear();
4600 				}
4601 				if ( !machineInfoKey.isEmpty() ) {
4602 					QString gameInfoText = qmc2MachineList->datInfoDb()->machineInfo(machineInfoKey);
4603 					if ( !gameInfoText.isEmpty() ) {
4604 						QString emulator = qmc2MachineList->datInfoDb()->machineInfoEmulator(machineInfoKey);
4605 						if ( emulator == "MESS" )
4606 							qmc2SystemNotesEditor->templateMap["$GAME_INFO$"] = messWikiToHtml(gameInfoText);
4607 						else
4608 							qmc2SystemNotesEditor->templateMap["$GAME_INFO$"] = gameInfoText.replace(QRegExp(QString("((http|https|ftp)://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>"));
4609 						qmc2SystemNotesEditor->templateMap["$GAME_INFO_STATUS$"] = "OK";
4610 					} else {
4611 						qmc2SystemNotesEditor->templateMap["$GAME_INFO$"] = tr("No data available");
4612 						qmc2SystemNotesEditor->templateMap["$GAME_INFO_STATUS$"] = "NO_DATA";
4613 					}
4614 				} else {
4615 					qmc2SystemNotesEditor->templateMap["$GAME_INFO$"] = tr("No data available");
4616 					qmc2SystemNotesEditor->templateMap["$GAME_INFO_STATUS$"] = "NO_DATA";
4617 				}
4618 				qmc2SystemNotesEditor->templateMap["$MACHINE_INFO$"] = qmc2SystemNotesEditor->templateMap["$GAME_INFO$"];
4619 				qmc2SystemNotesEditor->templateMap["$MACHINE_INFO_STATUS$"] = qmc2SystemNotesEditor->templateMap["$GAME_INFO_STATUS$"];
4620 				qmc2SystemNotesEditor->setCurrentTemplateName(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/SystemNotesTemplate").toString());
4621 				if ( QFile::exists(fileName) )
4622 					QTimer::singleShot(25, qmc2SystemNotesEditor, SLOT(loadCurrent()));
4623 				else {
4624 					if ( useSystemNotesTemplate )
4625 						QTimer::singleShot(25, qmc2SystemNotesEditor, SLOT(loadCurrentTemplate()));
4626 					else
4627 						qmc2SystemNotesEditor->fileNew();
4628 				}
4629 
4630 				qmc2SystemNotesEditor->setCurrentFileName(fileName);
4631 			}
4632 			break;
4633 
4634 		default:
4635 #if defined(QMC2_YOUTUBE_ENABLED)
4636 			if ( qmc2YouTubeWidget )
4637 				qmc2YouTubeWidget->clearMessage();
4638 #endif
4639 			// if local emulator options exits and they are no longer needed, close & destroy them...
4640 			if ( qmc2EmulatorOptions ) {
4641 				QWidget *configWidget = componentInfo->widget(QMC2_CONFIG_INDEX);
4642 				QString selectedEmulator = comboBoxEmuSelector->currentText();
4643 				if ( selectedEmulator == tr("Default") || selectedEmulator.isEmpty() )
4644 					qmc2Config->remove(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator");
4645 				else
4646 					qmc2Config->setValue(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator", selectedEmulator);
4647 				qmc2EmulatorOptions->save();
4648 				QLayout *vbl = configWidget->layout();
4649 				if ( vbl )
4650 					delete vbl;
4651 				delete labelEmuSelector;
4652 				delete comboBoxEmuSelector;
4653 				comboBoxEmuSelector = 0;
4654 				delete qmc2EmulatorOptions;
4655 				delete pushButtonCurrentEmulatorOptionsExportToFile;
4656 				delete pushButtonCurrentEmulatorOptionsImportFromFile;
4657 				qmc2EmulatorOptions = 0;
4658 			}
4659 			qmc2LastConfigItem = 0;
4660 			break;
4661 	}
4662 
4663 	if ( initialCall ) {
4664 		// this *forces* the tab-header to scroll, which it wouldn't do correctly otherwise when the current tab is far right (for whatever reason)
4665 		QTabBar *tabBar = tabWidgetMachineDetail->findChild<QTabBar *>();
4666 		if ( tabBar ) {
4667 			tabWidgetMachineDetail->setUpdatesEnabled(false);
4668 			tabBar->blockSignals(true);
4669 			tabBar->setCurrentIndex(0);
4670 			tabBar->setCurrentIndex(currentIndex);
4671 			tabBar->blockSignals(false);
4672 			tabWidgetMachineDetail->setUpdatesEnabled(true);
4673 		}
4674 	}
4675 	initialCall = false;
4676 }
4677 
qStringListLessThan(const QString & s1,const QString & s2)4678 bool MainWindow::qStringListLessThan(const QString &s1, const QString &s2)
4679 {
4680 	bool n1_ok, n2_ok;
4681        	quint64 n1 = s1.toULong(&n1_ok);
4682        	quint64 n2 = s2.toULong(&n2_ok);
4683 	if ( n1_ok && n2_ok )
4684 		return n1 < n2;
4685 	else
4686 		return s1.toLower() < s2.toLower();
4687 }
4688 
getXmlChoices(const QString & machineName,const QString & optionElement,const QString & optionAttribute,QString * defaultChoice)4689 QStringList &MainWindow::getXmlChoices(const QString &machineName, const QString &optionElement, const QString &optionAttribute, QString *defaultChoice)
4690 {
4691 	static QStringList xmlChoices;
4692 	xmlChoices.clear();
4693 	if ( machineName.isEmpty() )
4694 		return xmlChoices;
4695 	if ( defaultChoice )
4696 		defaultChoice->clear();
4697 	QStringList xmlLines(qmc2MachineList->xmlDb()->xml(machineName).split('\n', QString::SkipEmptyParts));
4698 	QString defaultYes("default=\"yes\"");
4699 	QString defaultOne("default=\"1\"");
4700 	int i = 0;
4701 	while ( i < xmlLines.count() ) {
4702 		QString xmlLine(xmlLines.at(i++).simplified());
4703 		int index = xmlLine.indexOf('<' + optionElement);
4704 		if ( index >= 0 ) {
4705 			if ( optionAttribute.isEmpty() ) {
4706 				index = xmlLine.indexOf('>', index);
4707 				if ( index >= 0 ) {
4708 					xmlLine.remove(0, index + 1);
4709 					bool isDefaultChoice = false;
4710 					if ( defaultChoice && (xmlLine.indexOf(defaultYes) >= 0 || xmlLine.indexOf(defaultOne) >= 0 || defaultChoice->isEmpty()) )
4711 						isDefaultChoice = true;
4712 					xmlLine.replace("</" + optionElement + '>', "");
4713 					QTextDocument doc;
4714 					doc.setHtml(xmlLine);
4715 					xmlLine = doc.toPlainText();
4716 					xmlChoices << xmlLine;
4717 					if ( isDefaultChoice )
4718 						*defaultChoice = xmlLine;
4719 				}
4720 			} else {
4721 				QString prefix(optionAttribute + "=\"");
4722 				index = xmlLine.indexOf(prefix);
4723 				if ( index >= 0 ) {
4724 					xmlLine.remove(0, index + prefix.length());
4725 					index = xmlLine.indexOf('\"');
4726 					if ( index >= 0 ) {
4727 						QTextDocument doc;
4728 						doc.setHtml(xmlLine.left(index));
4729 						QString choice = doc.toPlainText();
4730 						xmlChoices << choice;
4731 						if ( defaultChoice && (xmlLine.indexOf(defaultYes) >= 0 || xmlLine.indexOf(defaultOne) >= 0 || defaultChoice->isEmpty()) )
4732 							*defaultChoice = choice;
4733 					}
4734 				}
4735 			}
4736 		}
4737 	}
4738 	return xmlChoices;
4739 }
4740 
emuSelector_currentIndexChanged(const QString & text)4741 void MainWindow::emuSelector_currentIndexChanged(const QString &text)
4742 {
4743 	if ( !qmc2EmulatorOptions )
4744 		return;
4745 
4746 	if ( text == tr("Default") ) {
4747 		qmc2UseDefaultEmulator = true;
4748 		qmc2EmulatorOptions->setEnabled(true);
4749 		if ( qmc2SoftwareList )
4750 			qmc2SoftwareList->setEnabled(true);
4751 		if ( qmc2DeviceConfigurator )
4752 			qmc2DeviceConfigurator->setEnabled(true);
4753 		pushButtonCurrentEmulatorOptionsExportToFile->setEnabled(true);
4754 		pushButtonCurrentEmulatorOptionsImportFromFile->setEnabled(true);
4755 	} else {
4756 		qmc2UseDefaultEmulator = false;
4757 		qmc2EmulatorOptions->setEnabled(false);
4758 		if ( qmc2SoftwareList )
4759 			qmc2SoftwareList->setEnabled(false);
4760 		if ( qmc2DeviceConfigurator )
4761 			qmc2DeviceConfigurator->setEnabled(false);
4762 		pushButtonCurrentEmulatorOptionsExportToFile->setEnabled(false);
4763 		pushButtonCurrentEmulatorOptionsImportFromFile->setEnabled(false);
4764 	}
4765 
4766 	if ( qmc2UseDefaultEmulator )
4767 		qmc2Config->remove(QString(QMC2_EMULATOR_PREFIX + "Configuration/%1/SelectedEmulator").arg(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)));
4768 	else
4769 		qmc2Config->setValue(QString(QMC2_EMULATOR_PREFIX + "Configuration/%1/SelectedEmulator").arg(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)), text);
4770 }
4771 
on_treeWidgetMachineList_itemActivated(QTreeWidgetItem * item,int column)4772 void MainWindow::on_treeWidgetMachineList_itemActivated(QTreeWidgetItem *item, int column)
4773 {
4774 	if ( qmc2DemoModeDialog )
4775 		if ( qmc2DemoModeDialog->demoModeRunning )
4776 			return;
4777 
4778 	qmc2StartEmbedded = false;
4779 	if ( !qmc2IgnoreItemActivation ) {
4780 		switch ( qmc2DefaultLaunchMode ) {
4781 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
4782 			case QMC2_LAUNCH_MODE_EMBEDDED:
4783 				on_actionPlayEmbedded_triggered();
4784 				break;
4785 #endif
4786 			case QMC2_LAUNCH_MODE_INDEPENDENT:
4787 			default:
4788 				on_actionPlay_triggered();
4789 				break;
4790 		}
4791 	}
4792 	qmc2IgnoreItemActivation = false;
4793 }
4794 
on_treeWidgetHierarchy_itemActivated(QTreeWidgetItem * item,int column)4795 void MainWindow::on_treeWidgetHierarchy_itemActivated(QTreeWidgetItem *item, int column)
4796 {
4797 	if ( qmc2DemoModeDialog )
4798 		if ( qmc2DemoModeDialog->demoModeRunning )
4799 			return;
4800 
4801 	qmc2StartEmbedded = false;
4802 	if ( !qmc2IgnoreItemActivation ) {
4803 		switch ( qmc2DefaultLaunchMode ) {
4804 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
4805 			case QMC2_LAUNCH_MODE_EMBEDDED:
4806 				on_actionPlayEmbedded_triggered();
4807 				break;
4808 #endif
4809 			case QMC2_LAUNCH_MODE_INDEPENDENT:
4810 			default:
4811 				on_actionPlay_triggered();
4812 				break;
4813 		}
4814 	}
4815 	qmc2IgnoreItemActivation = false;
4816 }
4817 
on_treeWidgetForeignIDs_itemActivated(QTreeWidgetItem * item,int)4818 void MainWindow::on_treeWidgetForeignIDs_itemActivated(QTreeWidgetItem *item, int /*column*/)
4819 {
4820 	if ( qmc2DemoModeDialog )
4821 		if ( qmc2DemoModeDialog->demoModeRunning )
4822 			return;
4823 
4824 	qmc2StartEmbedded = false;
4825 	if ( !qmc2IgnoreItemActivation ) {
4826 		QStringList foreignInfo(item->whatsThis(0).split('\t'));
4827 		if ( foreignInfo.count() > 2 ) {
4828 			// 0:emuName -- 1:id -- 2:description
4829 			foreignEmuName = foreignInfo[0];
4830 			foreignID = foreignInfo[1];
4831 			foreignDescription = foreignInfo[2];
4832 			launchForeignID = true;
4833 			qmc2StartEmbedded = false;
4834 			switch ( qmc2DefaultLaunchMode ) {
4835 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
4836 				case QMC2_LAUNCH_MODE_EMBEDDED:
4837 					QTimer::singleShot(0, this, SLOT(on_actionPlayEmbedded_triggered()));
4838 					break;
4839 #endif
4840 				case QMC2_LAUNCH_MODE_INDEPENDENT:
4841 				default:
4842 					QTimer::singleShot(0, this, SLOT(on_actionPlay_triggered()));
4843 					break;
4844 			}
4845 		}
4846 	}
4847 	qmc2IgnoreItemActivation = false;
4848 }
4849 
on_treeWidgetMachineList_itemDoubleClicked(QTreeWidgetItem *,int)4850 void MainWindow::on_treeWidgetMachineList_itemDoubleClicked(QTreeWidgetItem * /*item*/, int /*column*/)
4851 {
4852 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/DoubleClickActivation").toBool() )
4853 		qmc2IgnoreItemActivation = true;
4854 }
4855 
on_treeWidgetHierarchy_itemDoubleClicked(QTreeWidgetItem *,int)4856 void MainWindow::on_treeWidgetHierarchy_itemDoubleClicked(QTreeWidgetItem * /*item*/, int /*column*/)
4857 {
4858 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/DoubleClickActivation").toBool() )
4859 		qmc2IgnoreItemActivation = true;
4860 }
4861 
on_treeWidgetForeignIDs_itemDoubleClicked(QTreeWidgetItem *,int)4862 void MainWindow::on_treeWidgetForeignIDs_itemDoubleClicked(QTreeWidgetItem * /*item*/, int /*column*/)
4863 {
4864 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/DoubleClickActivation").toBool() )
4865 		qmc2IgnoreItemActivation = true;
4866 }
4867 
on_treeWidgetForeignIDs_customContextMenuRequested(const QPoint & p)4868 void MainWindow::on_treeWidgetForeignIDs_customContextMenuRequested(const QPoint &p)
4869 {
4870 	QTreeWidgetItem *item = treeWidgetForeignIDs->itemAt(p);
4871 	if ( item ) {
4872 		treeWidgetForeignIDs->setItemSelected(item, true);
4873 		qmc2ForeignIDsMenu->move(adjustedWidgetPosition(treeWidgetForeignIDs->viewport()->mapToGlobal(p), qmc2ForeignIDsMenu));
4874 		qmc2ForeignIDsMenu->show();
4875 	}
4876 }
4877 
machineListViewer_selectionChanged(const QString & id)4878 void MainWindow::machineListViewer_selectionChanged(const QString &id)
4879 {
4880 	m_lastMlvSender = (MachineListViewer *)sender();
4881 	m_ignoreSelectionChange = true;
4882 	qmc2CurrentItem = qmc2MachineListItemHash.value(id);
4883 	treeWidgetMachineList->setCurrentItem(qmc2CurrentItem);
4884 	scrollToCurrentItem();
4885 }
4886 
machineListViewer_tagChanged(const QString & id,bool tagged)4887 void MainWindow::machineListViewer_tagChanged(const QString &id, bool tagged)
4888 {
4889 	QTreeWidgetItem *item;
4890 	item = qmc2MachineListItemHash.value(id);
4891 	Qt::CheckState cs = (tagged ? Qt::Checked : Qt::Unchecked);
4892 	if ( item )
4893 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
4894 	item = qmc2HierarchyItemHash.value(id);
4895 	if ( item )
4896 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
4897 	item = qmc2CategoryItemHash.value(id);
4898 	if ( item )
4899 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
4900 	item = qmc2VersionItemHash.value(id);
4901 	if ( item )
4902 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
4903 }
4904 
on_treeWidgetMachineList_itemExpanded(QTreeWidgetItem * item)4905 void MainWindow::on_treeWidgetMachineList_itemExpanded(QTreeWidgetItem *item)
4906 {
4907 	if ( !item )
4908 		return;
4909 
4910 	if ( qmc2ReloadActive ) {
4911 		treeWidgetMachineList->collapseItem(item);
4912 		log(QMC2_LOG_FRONTEND, tr("please wait for reload to finish and try again"));
4913 		return;
4914 	}
4915 
4916 	if ( qmc2SortingActive ) {
4917 		treeWidgetMachineList->collapseItem(item);
4918 		log(QMC2_LOG_FRONTEND, tr("please wait for sorting to finish and try again"));
4919 		return;
4920 	}
4921 
4922 	if ( item->child(0) ) {
4923 		treeWidgetMachineList->viewport()->update();
4924 		qApp->processEvents();
4925 		if ( item->child(0)->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData ) {
4926 			treeWidgetMachineList->viewport()->update();
4927 			qmc2MachineList->parseMachineDetail(item);
4928 			qmc2ExpandedMachineListItems << item;
4929 		}
4930 	}
4931 }
4932 
on_treeWidgetMachineList_currentItemChanged(QTreeWidgetItem * current,QTreeWidgetItem * previous)4933 void MainWindow::on_treeWidgetMachineList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
4934 {
4935 	// workaround for a Qt bug: when POS1/Home is pressed, QTreeWidget & QTreeView don't correctly select the first VISIBLE item,
4936 	// if the top item is HIDDEN
4937 	if ( current ) {
4938 		if ( qmc2CheckItemVisibility ) {
4939 			if ( current->isHidden() ) {
4940 				int i = treeWidgetMachineList->indexOfTopLevelItem(current);
4941 				if ( i >= 0 ) {
4942 					while ( current->isHidden() && i < treeWidgetMachineList->topLevelItemCount() ) {
4943 						current = treeWidgetMachineList->topLevelItem(++i);
4944 						if ( current == 0 )
4945 							break;
4946 					}
4947 					if ( current )
4948 						treeWidgetMachineList->setCurrentItem(current);
4949 				}
4950 			}
4951 		} else
4952 			qmc2CurrentItem = current;
4953 	}
4954 	qmc2CheckItemVisibility = true;
4955 	if ( qmc2UpdateDelay > 0 )
4956 		updateTimer.start(qmc2UpdateDelay);
4957 	else
4958 		treeWidgetMachineList_itemSelectionChanged_delayed();
4959 }
4960 
on_treeWidgetHierarchy_currentItemChanged(QTreeWidgetItem * current,QTreeWidgetItem * previous)4961 void MainWindow::on_treeWidgetHierarchy_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
4962 {
4963 	qmc2CheckItemVisibility = false;
4964 	if ( qmc2UpdateDelay > 0 )
4965 		updateTimer.start(qmc2UpdateDelay);
4966 	else
4967 		treeWidgetMachineList_itemSelectionChanged_delayed();
4968 }
4969 
on_treeWidgetMachineList_itemSelectionChanged()4970 void MainWindow::on_treeWidgetMachineList_itemSelectionChanged()
4971 {
4972 	if ( qmc2UpdateDelay > 0 )
4973 		updateTimer.start(qmc2UpdateDelay);
4974 	else
4975 		treeWidgetMachineList_itemSelectionChanged_delayed();
4976 }
4977 
treeWidgetMachineList_itemSelectionChanged_delayed()4978 void MainWindow::treeWidgetMachineList_itemSelectionChanged_delayed()
4979 {
4980 	updateTimer.stop();
4981 	QList<QTreeWidgetItem *> selected;
4982 	if ( qmc2HierarchySelectedItem != 0 )
4983 		selected.append(qmc2HierarchySelectedItem);
4984 	else
4985 		selected = treeWidgetMachineList->selectedItems();
4986 	if ( selected.isEmpty() )
4987 		if ( treeWidgetMachineList->currentItem() )
4988 			selected.append(treeWidgetMachineList->currentItem());
4989 	if ( !selected.isEmpty() ) {
4990 		QTreeWidgetItem *topLevelItem = selected.at(0);
4991 		while ( topLevelItem->parent() )
4992 			topLevelItem = topLevelItem->parent();
4993 		if ( topLevelItem ) {
4994 			qmc2CurrentItem = topLevelItem;
4995 			ImageWidget::updateArtwork();
4996 			on_tabWidgetMachineDetail_currentChanged(tabWidgetMachineDetail->currentIndex());
4997 		}
4998 	} else
4999 		qmc2CurrentItem = 0;
5000 	qmc2HierarchySelectedItem = 0;
5001 	QTimer::singleShot(0, this, SLOT(checkSystemManualAvailability()));
5002 }
5003 
on_treeWidgetHierarchy_itemSelectionChanged()5004 void MainWindow::on_treeWidgetHierarchy_itemSelectionChanged()
5005 {
5006 	qmc2HierarchySelectedItem = 0;
5007 	QList<QTreeWidgetItem *>selected = treeWidgetHierarchy->selectedItems();
5008 	if ( selected.count() > 0 ) {
5009 		if ( selected.at(0)->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
5010 			return;
5011 		qmc2HierarchySelectedItem = qmc2MachineListItemHash.value(selected.at(0)->text(QMC2_MACHINELIST_COLUMN_NAME));
5012 		qmc2CheckItemVisibility = false;
5013 		treeWidgetMachineList->setCurrentItem(qmc2HierarchySelectedItem);
5014 	}
5015 }
5016 
on_treeWidgetEmulators_customContextMenuRequested(const QPoint & p)5017 void MainWindow::on_treeWidgetEmulators_customContextMenuRequested(const QPoint &p)
5018 {
5019 	QTreeWidgetItem *item = treeWidgetEmulators->itemAt(p);
5020 	if ( item ) {
5021 		treeWidgetEmulators->setItemSelected(item, true);
5022 		qmc2EmulatorMenu->move(adjustedWidgetPosition(treeWidgetEmulators->viewport()->mapToGlobal(p), qmc2EmulatorMenu));
5023 		qmc2EmulatorMenu->show();
5024 	}
5025 }
5026 
5027 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
action_embedEmulator_triggered()5028 void MainWindow::action_embedEmulator_triggered()
5029 {
5030 	qmc2StartEmbedded = false;
5031 
5032 	QStringList mL;
5033 	QStringList idList;
5034 #if defined(QMC2_OS_UNIX)
5035 	QStringList statusList;
5036 #endif
5037 
5038 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
5039 
5040 	QList<QTreeWidgetItem *> sl = treeWidgetEmulators->selectedItems();
5041 	for (int i = 0; i < sl.count(); i++) {
5042 		QTreeWidgetItem *item = sl.at(i);
5043 		while ( item->parent() )
5044 			item = item->parent();
5045 		mL << item->text(QMC2_EMUCONTROL_COLUMN_MACHINE).split(':').at(0);
5046 		idList << item->text(QMC2_EMUCONTROL_COLUMN_NUMBER);
5047 #if defined(QMC2_OS_UNIX)
5048 		statusList << item->text(QMC2_EMUCONTROL_COLUMN_STATUS);
5049 #endif
5050 	}
5051 
5052 	if ( sl.count() == 0 )
5053 		if ( treeWidgetEmulators->currentItem() ) {
5054 			QTreeWidgetItem *item = treeWidgetEmulators->currentItem();
5055 			while ( item->parent() )
5056 				item = item->parent();
5057 			mL << item->text(QMC2_EMUCONTROL_COLUMN_MACHINE).split(':').at(0);
5058 			idList << item->text(QMC2_EMUCONTROL_COLUMN_NUMBER);
5059 #if defined(QMC2_OS_UNIX)
5060 			statusList << item->text(QMC2_EMUCONTROL_COLUMN_STATUS);
5061 #endif
5062 		}
5063 
5064 	bool success = true;
5065 	int i;
5066 	for (i = 0; i < mL.count(); i++) {
5067 		QString machineName(mL.at(i));
5068 		QString machineId(idList.at(i));
5069 #if defined(QMC2_OS_UNIX)
5070 		QString machineStatus(statusList.at(i));
5071 #endif
5072 
5073 		if ( machineName.isEmpty() || machineId.isEmpty() )
5074 			continue;
5075 
5076 		// check if the emulator window is already embedded
5077 		bool found = false;
5078 		int j;
5079 		for (j = 0; j < tabWidgetEmbeddedEmulators->count() && !found; j++)
5080 			found = tabWidgetEmbeddedEmulators->tabText(j).startsWith(QString("#%1 - ").arg(machineId));
5081 		if ( found ) {
5082 			log(QMC2_LOG_FRONTEND, tr("emulator #%1 is already embedded").arg(machineId));
5083 			tabWidgetMachineList->setCurrentIndex(tabWidgetMachineList->indexOf(widgetEmbeddedEmus));
5084 			tabWidgetEmbeddedEmulators->setCurrentIndex(j - 1);
5085 			continue;
5086 		}
5087 
5088 		QTreeWidgetItem *machineItem = qmc2MachineListItemHash.value(machineName);
5089 #if defined(QMC2_OS_UNIX)
5090 		QList<WId> winIdList;
5091 		int xwininfoRetries = 0;
5092 		while ( winIdList.isEmpty() && xwininfoRetries++ < QMC2_MAX_XWININFO_RETRIES ) {
5093 			WId windowId = x11FindWindowId(QRegExp::escape(QString("MAME: %1").arg(machineItem ? machineItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) : "")), QRegExp::escape(QString("QMC2-MAME-ID-%1").arg(machineId)));
5094 			if ( windowId )
5095 				winIdList << windowId;
5096 
5097 			if ( winIdList.isEmpty() && xwininfoRetries <= QMC2_MAX_XWININFO_RETRIES )
5098 				QTest::qWait(QMC2_XWININFO_DELAY);
5099 		}
5100 #elif defined(QMC2_OS_WIN)
5101 		QList<WId> winIdList;
5102 		int wininfoRetries = 0;
5103 		while ( winIdList.isEmpty() && wininfoRetries++ < QMC2_MAX_WININFO_RETRIES ) {
5104 			Q_PID gamePid = qmc2ProcessManager->getPid(machineId.toInt());
5105 			if ( gamePid ) {
5106 				HWND hwnd = winFindWindowHandleOfProcess(gamePid, "MAME:");
5107 				if ( hwnd )
5108 					winIdList << (WId)hwnd;
5109 			}
5110 			if ( winIdList.isEmpty() && wininfoRetries <= QMC2_MAX_WININFO_RETRIES )
5111 				QTest::qWait(QMC2_WININFO_DELAY);
5112 		}
5113 #endif
5114 
5115 #if defined(QMC2_OS_UNIX)
5116 		if ( winIdList.count() > 1 )
5117 			log(QMC2_LOG_FRONTEND, tr("WARNING: multiple windows for emulator #%1 found, choosing window ID %2 for embedding").arg(machineId).arg("0x" + QString::number(winIdList[0], 16)));
5118 #elif defined(QMC2_OS_WIN)
5119 		if ( winIdList.count() > 1 )
5120 			log(QMC2_LOG_FRONTEND, tr("WARNING: multiple windows for emulator #%1 found, choosing window ID %2 for embedding").arg(machineId).arg("0x" + QString::number((qulonglong)winIdList[0], 16)));
5121 #endif
5122 
5123 		if ( !winIdList.isEmpty() ) {
5124 			int embeddedEmusIndex = tabWidgetMachineList->indexOf(widgetEmbeddedEmus);
5125 			if ( tabWidgetMachineList->currentIndex() != embeddedEmusIndex )
5126 				qmc2LastListIndex = tabWidgetMachineList->currentIndex();
5127 			if ( embeddedEmusIndex < 0 ) {
5128 				int insertIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
5129 				int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
5130 				if ( foreignIndex >= 0 && foreignIndex <= insertIndex )
5131 					if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
5132 						insertIndex--;
5133 				tabWidgetMachineList->insertTab(insertIndex, widgetEmbeddedEmus, QIcon(QString::fromUtf8(":/data/img/embed.png")), tr("Embedded emulators"));
5134 			}
5135 			tabWidgetMachineList->setCurrentIndex(tabWidgetMachineList->indexOf(widgetEmbeddedEmus));
5136 #if defined(QMC2_OS_UNIX)
5137 			qApp->syncX();
5138 			log(QMC2_LOG_FRONTEND, tr("embedding emulator #%1, window ID = %2").arg(machineId).arg("0x" + QString::number(winIdList[0], 16)));
5139 			Embedder *embedder = new Embedder(machineName, machineId, winIdList[0], (machineStatus == tr("paused")), this, qmc2IconHash.value(machineName));
5140 #elif defined(QMC2_OS_WIN)
5141 			log(QMC2_LOG_FRONTEND, tr("embedding emulator #%1, window ID = %2").arg(machineId).arg("0x" + QString::number((qulonglong)winIdList[0], 16)));
5142 			Embedder *embedder = new Embedder(machineName, machineId, winIdList[0], false, this, qmc2IconHash.value(machineName));
5143 #endif
5144 			connect(embedder, SIGNAL(closing()), this, SLOT(closeEmbeddedEmuTab()));
5145 			if ( machineItem )
5146 				tabWidgetEmbeddedEmulators->addTab(embedder, QString("#%1 - %2").arg(machineId).arg(machineItem->text(QMC2_MACHINELIST_COLUMN_MACHINE)));
5147 			else
5148 				tabWidgetEmbeddedEmulators->addTab(embedder, QString("#%1").arg(machineId));
5149 			tabWidgetEmbeddedEmulators->setCurrentIndex(tabWidgetEmbeddedEmulators->count() - 1);
5150 
5151 			// serious hack to access the tab bar without sub-classing from QTabWidget ;)
5152 			QTabBar *tabBar = tabWidgetEmbeddedEmulators->findChild<QTabBar *>();
5153 			if ( tabBar ) {
5154 				// replace the default 'X' icon with something more suitable (the only way I found to accomplish this is by setting a style-sheet)
5155 				tabBar->setStyleSheet("QTabBar::close-button { image: url(:/data/img/release.png); subcontrol-position: right; } QTabBar::close-button:hover { image: url(:/data/img/release_alternate.png); }");
5156 
5157 				int index = tabWidgetEmbeddedEmulators->indexOf(embedder);
5158 				tabBar->tabButton(index, QTabBar::RightSide)->setToolTip(tr("Release emulator"));
5159 
5160 				QFont f;
5161 				f.fromString(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Font").toString());
5162 				QFontMetrics fm(f);
5163 				int baseSize = fm.height() + 2;
5164 				QSize optionsButtonSize(2 * baseSize, baseSize + 2);
5165 
5166 				QToolButton *optionsButton = new QToolButton(tabBar);
5167 				optionsButton->setFixedSize(optionsButtonSize);
5168 				optionsButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
5169 				optionsButton->setText(" ");
5170 				optionsButton->setIcon(QIcon(QString::fromUtf8(":/data/img/work.png")));
5171 				optionsButton->setToolTip(tr("Toggle embedder options (hold down for menu)"));
5172 				optionsButton->setStatusTip(tr("Toggle embedder options (hold down for menu)"));
5173 				optionsButton->setCheckable(true);
5174 				connect(optionsButton, SIGNAL(toggled(bool)), this, SLOT(embedderOptions_toggled(bool)));
5175 
5176 				QMenu *optionsMenu = new QMenu(optionsButton);
5177 				QString s;
5178 				QAction *action;
5179 				s = tr("To favorites");
5180 				action = optionsMenu->addAction(tr("To &favorites"));
5181 				action->setIcon(QIcon(QString::fromUtf8(":/data/img/favorites.png")));
5182 				action->setToolTip(s); action->setStatusTip(s);
5183 				connect(action, SIGNAL(triggered()), this, SLOT(embedderOptionsMenu_ToFavorites_activated()));
5184 				s = tr("Copy emulator command line to clipboard");
5185 				action = optionsMenu->addAction(tr("&Copy command"));
5186 				action->setToolTip(s); action->setStatusTip(s);
5187 				action->setIcon(QIcon(QString::fromUtf8(":/data/img/editcopy.png")));
5188 				connect(action, SIGNAL(triggered()), this, SLOT(embedderOptionsMenu_CopyCommand_activated()));
5189 				optionsMenu->addSeparator();
5190 				s = tr("Kill emulator");
5191 				action = optionsMenu->addAction(tr("&Kill emulator"));
5192 				action->setIcon(QIcon(QString::fromUtf8(":/data/img/kill.png")));
5193 				action->setToolTip(s); action->setStatusTip(s);
5194 				connect(action, SIGNAL(triggered()), this, SLOT(embedderOptionsMenu_KillEmulator_activated()));
5195 
5196 				optionsButton->setMenu(optionsMenu);
5197 
5198 				tabBar->setTabButton(index, QTabBar::LeftSide, optionsButton);
5199 
5200 				QTimer::singleShot(0, embedder, SLOT(embed()));
5201 			}
5202 		} else {
5203 			success = false;
5204 			log(QMC2_LOG_FRONTEND, tr("WARNING: no matching window for emulator #%1 found").arg(machineId));
5205 		}
5206 	}
5207 
5208 	sl = treeWidgetEmulators->selectedItems();
5209 	if ( !success && sl.count() > 0 ) {
5210 		switch ( QMessageBox::question(this, tr("Embedding failed"),
5211 					tr("Couldn't find the window ID of one or more\nemulator(s) within a reasonable timeframe.\n\nRetry embedding?"),
5212 					QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ) {
5213 			case QMessageBox::No:
5214 				break;
5215 
5216 			case QMessageBox::Yes:
5217 				sl = treeWidgetEmulators->selectedItems();
5218 				if ( sl.count() > 0 )
5219 					QTimer::singleShot(0, this, SLOT(action_embedEmulator_triggered()));
5220 				else
5221 					QMessageBox::information(this, tr("Information"), tr("Sorry, the emulator meanwhile died a sorrowful death :(."));
5222 				break;
5223 
5224 			default:
5225 				break;
5226 		}
5227 	}
5228 }
5229 
5230 #if defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000
action_embedderScanPauseKey_triggered()5231 void MainWindow::action_embedderScanPauseKey_triggered()
5232 {
5233 	qApp->removeEventFilter(qmc2MainEventFilter);
5234 
5235 	KeySequenceScanner keySeqScanner(this, true, true);
5236 	keySeqScanner.setWindowTitle(tr("Scanning pause key"));
5237 	keySeqScanner.labelStatus->setText(tr("Scanning pause key"));
5238 	if ( keySeqScanner.exec() == QDialog::Accepted )
5239   		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Embedder/PauseKey", keySeqScanner.keySequence);
5240 
5241 	qApp->installEventFilter(qmc2MainEventFilter);
5242 }
5243 #endif
5244 
embedderOptions_toggled(bool enabled)5245 void MainWindow::embedderOptions_toggled(bool enabled)
5246 {
5247 	// serious hack to access the tab bar ;)
5248 	QToolButton *optionsButton = (QToolButton *)sender();
5249 	QTabBar *tabBar = (QTabBar *)optionsButton->parent();
5250 	Embedder *embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(tabBar->tabAt(optionsButton->pos()));
5251 	if ( embedder )
5252 		embedder->toggleOptions();
5253 	if ( enabled )
5254 		tabWidgetEmbeddedEmulators->setCurrentIndex(tabWidgetEmbeddedEmulators->indexOf(embedder));
5255 }
5256 
on_tabWidgetEmbeddedEmulators_tabCloseRequested(int index)5257 void MainWindow::on_tabWidgetEmbeddedEmulators_tabCloseRequested(int index)
5258 {
5259 	tabWidgetMachineList->setUpdatesEnabled(false);
5260 	QWidget *widget = 0;
5261 	if ( index >= 0 ) {
5262 		widget = tabWidgetEmbeddedEmulators->widget(index);
5263 		if ( widget )
5264 			tabWidgetEmbeddedEmulators->removeTab(index);
5265 	}
5266 	if ( tabWidgetEmbeddedEmulators->count() < 1 ) {
5267 		tabWidgetMachineList->removeTab(tabWidgetMachineList->indexOf(tabEmbeddedEmus));
5268 		tabWidgetMachineList->setCurrentIndex(qmc2LastListIndex);
5269 		if ( toolButtonEmbedderMaximizeToggle->isChecked() )
5270 			hSplitter->setSizes(hSplitterSizes);
5271 		menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
5272 		statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
5273 		toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
5274 	}
5275 	if ( widget ) {
5276 		widget->close();
5277 		widget->deleteLater();
5278 	}
5279 	tabWidgetMachineList->setUpdatesEnabled(true);
5280 }
5281 
closeEmbeddedEmuTab()5282 void MainWindow::closeEmbeddedEmuTab()
5283 {
5284 	Embedder *embedder = (Embedder *)sender();
5285 	if ( !qmc2CleaningUp )
5286 		on_tabWidgetEmbeddedEmulators_tabCloseRequested(tabWidgetEmbeddedEmulators->indexOf(embedder));
5287 }
5288 
toolButtonEmbedderMaximizeToggle_toggled(bool on)5289 void MainWindow::toolButtonEmbedderMaximizeToggle_toggled(bool on)
5290 {
5291 	if ( on ) {
5292 		menuBar()->hide();
5293 		statusBar()->hide();
5294 		toolbar->hide();
5295 		qApp->processEvents();
5296 		hSplitterSizes = hSplitter->sizes();
5297 		QList<int> maximizedSizes;
5298 		if ( hSplitter->widget(0) == hSplitterWidget0 )
5299 			maximizedSizes << desktopGeometry.width() << 0;
5300 		else
5301 			maximizedSizes << 0 << desktopGeometry.width();
5302 		hSplitter->setSizes(maximizedSizes);
5303 		toolButtonEmbedderMaximizeToggle->setIcon(QIcon(QString::fromUtf8(":/data/img/minimize.png")));
5304 	} else {
5305 		hSplitter->setSizes(hSplitterSizes);
5306 		menuBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowMenuBar", true).toBool());
5307 		statusBar()->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Statusbar", true).toBool());
5308 		toolbar->setVisible(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Toolbar", true).toBool());
5309 		toolButtonEmbedderMaximizeToggle->setIcon(QIcon(QString::fromUtf8(":/data/img/maximize.png")));
5310 	}
5311 }
5312 
embedderOptionsMenu_KillEmulator_activated()5313 void MainWindow::embedderOptionsMenu_KillEmulator_activated()
5314 {
5315 	// serious hack to access the corresponding embedder ;)
5316 	QAction *action = (QAction *)sender();
5317 	QMenu *menu = (QMenu *)action->parent();
5318 	QToolButton *toolButton = (QToolButton *)menu->parent();
5319 	QTabBar *tabBar = (QTabBar *)toolButton->parent();
5320 	Embedder *embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(tabBar->tabAt(toolButton->pos()));
5321 	if ( embedder )
5322 		qmc2ProcessManager->kill(embedder->machineId.toInt());
5323 }
5324 
embedderOptionsMenu_ToFavorites_activated()5325 void MainWindow::embedderOptionsMenu_ToFavorites_activated()
5326 {
5327 	// serious hack to access the corresponding embedder ;)
5328 	QAction *action = (QAction *)sender();
5329 	QMenu *menu = (QMenu *)action->parent();
5330 	QToolButton *toolButton = (QToolButton *)menu->parent();
5331 	QTabBar *tabBar = (QTabBar *)toolButton->parent();
5332 	Embedder *embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(tabBar->tabAt(toolButton->pos()));
5333 	if ( embedder ) {
5334 		QString gameDescription = qmc2MachineListItemHash.value(embedder->machineName)->text(QMC2_MACHINELIST_COLUMN_MACHINE);
5335 		QList<QListWidgetItem *> matches = listWidgetFavorites->findItems(gameDescription, Qt::MatchExactly);
5336 		if ( matches.count() <= 0 ) {
5337 			QListWidgetItem *item = new QListWidgetItem(listWidgetFavorites);
5338 			item->setText(gameDescription);
5339 			listWidgetFavorites->sortItems();
5340 		}
5341 	}
5342 }
5343 
embedderOptionsMenu_CopyCommand_activated()5344 void MainWindow::embedderOptionsMenu_CopyCommand_activated()
5345 {
5346 	// serious hack to access the corresponding embedder ;)
5347 	QAction *action = (QAction *)sender();
5348 	QMenu *menu = (QMenu *)action->parent();
5349 	QToolButton *toolButton = (QToolButton *)menu->parent();
5350 	QTabBar *tabBar = (QTabBar *)toolButton->parent();
5351 	Embedder *embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(tabBar->tabAt(toolButton->pos()));
5352 	if ( embedder ) {
5353 		QList<QTreeWidgetItem *> il = treeWidgetEmulators->findItems(embedder->machineId, Qt::MatchExactly, QMC2_EMUCONTROL_COLUMN_ID);
5354 		if ( il.count() > 0 )
5355 			QApplication::clipboard()->setText(il[0]->text(QMC2_EMUCONTROL_COLUMN_COMMAND));
5356 	}
5357 }
5358 #endif
5359 
action_killEmulator_triggered()5360 void MainWindow::action_killEmulator_triggered()
5361 {
5362 	QList<QTreeWidgetItem *> sl = treeWidgetEmulators->selectedItems();
5363 	for (int i = 0; i < sl.count(); i++) {
5364 		QTreeWidgetItem *item = sl[i];
5365 		while ( item->parent() ) item = item->parent();
5366 		qmc2ProcessManager->kill(item->text(QMC2_EMUCONTROL_COLUMN_NUMBER).toInt());
5367 	}
5368 
5369 	if ( sl.count() == 0 )
5370 		if ( treeWidgetEmulators->currentItem() ) {
5371 			QTreeWidgetItem *item = treeWidgetEmulators->currentItem();
5372 			while ( item->parent() ) item = item->parent();
5373 			qmc2ProcessManager->kill(item->text(QMC2_EMUCONTROL_COLUMN_NUMBER).toInt());
5374 		}
5375 }
5376 
action_copyEmulatorCommand_triggered()5377 void MainWindow::action_copyEmulatorCommand_triggered()
5378 {
5379 	QString commandString;
5380 	QList<QTreeWidgetItem *> sl = treeWidgetEmulators->selectedItems();
5381 	QList<QTreeWidgetItem *> tl;
5382 
5383 	// find toplevel items...
5384 	for (int i = 0; i < sl.count(); i++) {
5385 		QTreeWidgetItem *item = sl[i];
5386 		while ( item->parent() )
5387 			item = item->parent();
5388 		if ( !tl.contains(item) )
5389 			tl.append(item);
5390 	}
5391 	// ... and copy their commands
5392 	for (int i = 0; i < tl.count(); i++) {
5393 		if ( i > 0 )
5394 			commandString += "\n";
5395 		commandString += tl[i]->text(QMC2_EMUCONTROL_COLUMN_COMMAND);
5396 	}
5397 
5398 	QApplication::clipboard()->setText(commandString);
5399 }
5400 
action_removeFromFavorites_triggered()5401 void MainWindow::action_removeFromFavorites_triggered()
5402 {
5403 	QListWidgetItem *i = listWidgetFavorites->currentItem();
5404 	if ( i ) {
5405 		QListWidgetItem *item = listWidgetFavorites->takeItem(listWidgetFavorites->row(i));
5406 		delete item;
5407 	}
5408 }
5409 
action_clearAllFavorites_triggered()5410 void MainWindow::action_clearAllFavorites_triggered()
5411 {
5412 	switch ( QMessageBox::question(this, tr("Confirm"),
5413 				tr("Are you sure you want to clear the favorites list?"),
5414 				QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
5415 		case QMessageBox::No:
5416 			return;
5417 			break;
5418 
5419 		case QMessageBox::Yes:
5420 			listWidgetFavorites->clear();
5421 			qmc2MachineList->saveFavorites();
5422 			break;
5423 
5424 		default:
5425 			break;
5426 	}
5427 }
5428 
action_saveFavorites_triggered()5429 void MainWindow::action_saveFavorites_triggered()
5430 {
5431 	qmc2MachineList->saveFavorites();
5432 }
5433 
action_removeFromPlayed_triggered()5434 void MainWindow::action_removeFromPlayed_triggered()
5435 {
5436 	QListWidgetItem *i = listWidgetPlayed->currentItem();
5437 	if ( i ) {
5438 		QListWidgetItem *item = listWidgetPlayed->takeItem(listWidgetPlayed->row(i));
5439 		delete item;
5440 	}
5441 }
5442 
action_clearAllPlayed_triggered()5443 void MainWindow::action_clearAllPlayed_triggered()
5444 {
5445 	switch ( QMessageBox::question(this, tr("Confirm"),
5446 				tr("Are you sure you want to clear the play history?"),
5447 				QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
5448 		case QMessageBox::No:
5449 			return;
5450 			break;
5451 
5452 		case QMessageBox::Yes:
5453 			listWidgetPlayed->clear();
5454 			qmc2MachineList->savePlayHistory();
5455 			break;
5456 
5457 		default:
5458 			break;
5459 	}
5460 }
5461 
action_savePlayed_triggered()5462 void MainWindow::action_savePlayed_triggered()
5463 {
5464 	qmc2MachineList->savePlayHistory();
5465 }
5466 
on_listWidgetSearch_customContextMenuRequested(const QPoint & p)5467 void MainWindow::on_listWidgetSearch_customContextMenuRequested(const QPoint &p)
5468 {
5469 	QListWidgetItem *item = listWidgetSearch->itemAt(p);
5470 	if ( item ) {
5471 		listWidgetSearch->setItemSelected(item, true);
5472 		qmc2SearchMenu->move(adjustedWidgetPosition(listWidgetSearch->viewport()->mapToGlobal(p), qmc2SearchMenu));
5473 		qmc2SearchMenu->show();
5474 	}
5475 }
5476 
on_listWidgetFavorites_customContextMenuRequested(const QPoint & p)5477 void MainWindow::on_listWidgetFavorites_customContextMenuRequested(const QPoint &p)
5478 {
5479 	QListWidgetItem *item = listWidgetFavorites->itemAt(p);
5480 	if ( item ) {
5481 		listWidgetFavorites->setItemSelected(item, true);
5482 		qmc2FavoritesMenu->move(adjustedWidgetPosition(listWidgetFavorites->viewport()->mapToGlobal(p), qmc2FavoritesMenu));
5483 		qmc2FavoritesMenu->show();
5484 	}
5485 }
5486 
on_listWidgetPlayed_customContextMenuRequested(const QPoint & p)5487 void MainWindow::on_listWidgetPlayed_customContextMenuRequested(const QPoint &p)
5488 {
5489 	QListWidgetItem *item = listWidgetPlayed->itemAt(p);
5490 	if ( item ) {
5491 		listWidgetPlayed->setItemSelected(item, true);
5492 		qmc2PlayedMenu->move(adjustedWidgetPosition(listWidgetPlayed->viewport()->mapToGlobal(p), qmc2PlayedMenu));
5493 		qmc2PlayedMenu->show();
5494 	}
5495 }
5496 
on_treeWidgetMachineList_customContextMenuRequested(const QPoint & p)5497 void MainWindow::on_treeWidgetMachineList_customContextMenuRequested(const QPoint &p)
5498 {
5499 	QTreeWidgetItem *item = treeWidgetMachineList->itemAt(p);
5500 	if ( !item )
5501 		return;
5502 	if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
5503 		return;
5504 	treeWidgetMachineList->setItemSelected(item, true);
5505 	qmc2MachineMenu->move(adjustedWidgetPosition(treeWidgetMachineList->viewport()->mapToGlobal(p), qmc2MachineMenu));
5506 	qmc2MachineMenu->show();
5507 }
5508 
on_treeWidgetHierarchy_customContextMenuRequested(const QPoint & p)5509 void MainWindow::on_treeWidgetHierarchy_customContextMenuRequested(const QPoint &p)
5510 {
5511 	QTreeWidgetItem *item = treeWidgetHierarchy->itemAt(p);
5512 	if ( !item )
5513 		return;
5514 	if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
5515 		return;
5516 	if ( item ) {
5517 		treeWidgetHierarchy->setItemSelected(item, true);
5518 		qmc2MachineMenu->move(adjustedWidgetPosition(treeWidgetHierarchy->viewport()->mapToGlobal(p), qmc2MachineMenu));
5519 		qmc2MachineMenu->show();
5520 	}
5521 }
5522 
on_stackedWidgetView_currentChanged(int index)5523 void MainWindow::on_stackedWidgetView_currentChanged(int index)
5524 {
5525 	if ( !qmc2EarlyStartup ) {
5526 		menuMachineListHeader->hide();
5527 		menuHierarchyHeader->hide();
5528 		menuCategoryHeader->hide();
5529 		menuVersionHeader->hide();
5530 	}
5531 
5532 	bool romFilterActive = qmc2Config->value(QMC2_FRONTEND_PREFIX + "RomStateFilter/Enabled", true).toBool();
5533 	switch ( index ) {
5534 		case QMC2_VIEWHIERARCHY_INDEX:
5535 		case QMC2_VIEWCATEGORY_INDEX:
5536 		case QMC2_VIEWVERSION_INDEX:
5537 			toolButtonSelectRomFilter->setVisible(false);
5538 			menuRomStatusFilter->setVisible(false);
5539 			actionTagVisible->setVisible(false);
5540 			actionUntagVisible->setVisible(false);
5541 			actionInvertVisibleTags->setVisible(false);
5542 			break;
5543 		case QMC2_VIEWCUSTOM_INDEX:
5544 			toolButtonSelectRomFilter->setVisible(false);
5545 			menuRomStatusFilter->setVisible(false);
5546 			actionTagVisible->setVisible(romFilterActive);
5547 			actionUntagVisible->setVisible(romFilterActive);
5548 			actionInvertVisibleTags->setVisible(romFilterActive);
5549 			break;
5550 		case QMC2_VIEWMACHINELIST_INDEX:
5551 		default:
5552 			toolButtonSelectRomFilter->setVisible(romFilterActive);
5553 			actionTagVisible->setVisible(romFilterActive);
5554 			actionUntagVisible->setVisible(romFilterActive);
5555 			actionInvertVisibleTags->setVisible(romFilterActive);
5556 			break;
5557 	}
5558 
5559 	if ( !qmc2CurrentItem )
5560 		return;
5561 
5562 	QTreeWidgetItem *ci = treeWidgetMachineList->currentItem();
5563 	if ( !ci )
5564 		return;
5565 
5566 	if ( qmc2CurrentItem != ci && qmc2ReloadActive )
5567 		qmc2CurrentItem = ci;
5568 
5569 	if ( qmc2CurrentItem->childCount() <= 0 )
5570 		return;
5571 
5572 	switch ( index ) {
5573 		case QMC2_VIEWHIERARCHY_INDEX:
5574 			if ( !qmc2ReloadActive ) {
5575 				QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
5576 				QTreeWidgetItem *hierarchyItem = qmc2HierarchyItemHash.value(machineName);
5577 				treeWidgetHierarchy->clearSelection();
5578 				if ( hierarchyItem ) {
5579 					treeWidgetHierarchy->setCurrentItem(hierarchyItem);
5580 					treeWidgetHierarchy->scrollToItem(hierarchyItem, qmc2CursorPositioningMode);
5581 					hierarchyItem->setSelected(true);
5582 				}
5583 				treeWidgetHierarchy_verticalScrollChanged();
5584 			}
5585 			break;
5586 		case QMC2_VIEWCATEGORY_INDEX:
5587 			if ( !qmc2ReloadActive ) {
5588 				QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
5589 				QTreeWidgetItem *categoryItem = qmc2CategoryItemHash.value(machineName);
5590 				treeWidgetCategoryView->clearSelection();
5591 				if ( categoryItem ) {
5592 					treeWidgetCategoryView->setCurrentItem(categoryItem);
5593 					treeWidgetCategoryView->scrollToItem(categoryItem, qmc2CursorPositioningMode);
5594 					categoryItem->setSelected(true);
5595 				}
5596 				treeWidgetCategoryView_verticalScrollChanged();
5597 			}
5598 			break;
5599 		case QMC2_VIEWVERSION_INDEX:
5600 			if ( !qmc2ReloadActive ) {
5601 				QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
5602 				QTreeWidgetItem *versionItem = qmc2VersionItemHash.value(machineName);
5603 				treeWidgetVersionView->clearSelection();
5604 				if ( versionItem ) {
5605 					treeWidgetVersionView->setCurrentItem(versionItem);
5606 					treeWidgetVersionView->scrollToItem(versionItem, qmc2CursorPositioningMode);
5607 					versionItem->setSelected(true);
5608 				}
5609 				treeWidgetVersionView_verticalScrollChanged();
5610 			}
5611 			break;
5612 		case QMC2_VIEWCUSTOM_INDEX:
5613 			// handled by custom view
5614 			break;
5615 		case QMC2_VIEWMACHINELIST_INDEX:
5616 		default:
5617 			scrollToCurrentItem();
5618 			treeWidgetMachineList_verticalScrollChanged();
5619 			break;
5620 	}
5621 }
5622 
pushButtonGlobalEmulatorOptionsSelectExportFile_clicked()5623 void MainWindow::pushButtonGlobalEmulatorOptionsSelectExportFile_clicked()
5624 {
5625 	QString fileName = qmc2Config->value("MAME/Configuration/Global/inipath", QDir::homePath()).toString().replace("~", QDir::homePath()) + "/mame.ini";
5626 	QString s = QFileDialog::getSaveFileName(qmc2Options, tr("Choose export file"), fileName, tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
5627 	if ( !s.isNull() )
5628 		pushButtonGlobalEmulatorOptionsExportToFile_clicked(s);
5629 }
5630 
pushButtonGlobalEmulatorOptionsExportToFile_clicked(QString useFileName)5631 void MainWindow::pushButtonGlobalEmulatorOptionsExportToFile_clicked(QString useFileName)
5632 {
5633 	qmc2GlobalEmulatorOptions->exportToIni(true, useFileName);
5634 }
5635 
pushButtonGlobalEmulatorOptionsSelectImportFile_clicked()5636 void MainWindow::pushButtonGlobalEmulatorOptionsSelectImportFile_clicked()
5637 {
5638 	QString fileName = qmc2Config->value("MAME/Configuration/Global/inipath", QDir::homePath()).toString().replace("~", QDir::homePath()) + "/mame.ini";
5639 	QString s = QFileDialog::getOpenFileName(qmc2Options, tr("Choose import file"), fileName, tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
5640 	if ( !s.isNull() )
5641 		pushButtonGlobalEmulatorOptionsImportFromFile_clicked(s);
5642 }
5643 
pushButtonGlobalEmulatorOptionsImportFromFile_clicked(QString useFileName)5644 void MainWindow::pushButtonGlobalEmulatorOptionsImportFromFile_clicked(QString useFileName)
5645 {
5646 	qmc2GlobalEmulatorOptions->importFromIni(true, useFileName);
5647 }
5648 
pushButtonCurrentEmulatorOptionsSelectExportFile_clicked()5649 void MainWindow::pushButtonCurrentEmulatorOptionsSelectExportFile_clicked()
5650 {
5651 	QStringList iniPaths(qmc2Config->value(QMC2_EMULATOR_PREFIX + "Configuration/Global/inipath", QDir::homePath()).toString().split(';', QString::SkipEmptyParts));
5652 	QString iniPath;
5653 	if ( iniPaths.count() > 0 )
5654 		iniPath = iniPaths[0].replace("~", QDir::homePath());
5655 	else {
5656 		iniPath = ".";
5657 		log(QMC2_LOG_FRONTEND, tr("WARNING: invalid inipath"));
5658 	}
5659 	QString s = QFileDialog::getSaveFileName(this, tr("Choose export file"), iniPath, tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
5660 	if ( !s.isNull() )
5661 		pushButtonCurrentEmulatorOptionsExportToFile_clicked(s);
5662 }
5663 
pushButtonCurrentEmulatorOptionsExportToFile_clicked(QString useFileName)5664 void MainWindow::pushButtonCurrentEmulatorOptionsExportToFile_clicked(QString useFileName)
5665 {
5666 	qmc2EmulatorOptions->exportToIni(false, useFileName);
5667 }
5668 
pushButtonCurrentEmulatorOptionsSelectImportFile_clicked()5669 void MainWindow::pushButtonCurrentEmulatorOptionsSelectImportFile_clicked()
5670 {
5671 	if ( !qmc2CurrentItem )
5672 		return;
5673 
5674 	QStringList iniPaths(qmc2Config->value(QMC2_EMULATOR_PREFIX + "Configuration/Global/inipath", QDir::homePath()).toString().split(';', QString::SkipEmptyParts));
5675 	QString iniPath;
5676 	if ( iniPaths.count() > 0 ) {
5677 		iniPath = iniPaths[0].replace("~", QDir::homePath());
5678 	} else {
5679 		iniPath = ".";
5680 		log(QMC2_LOG_FRONTEND, tr("WARNING: invalid inipath"));
5681 	}
5682 	iniPath += "/" + qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME) + ".ini";
5683 	QString s = QFileDialog::getOpenFileName(this, tr("Choose import file"), iniPath, tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
5684 	if ( !s.isNull() )
5685 		pushButtonCurrentEmulatorOptionsImportFromFile_clicked(s);
5686 }
5687 
pushButtonCurrentEmulatorOptionsImportFromFile_clicked(QString useFileName)5688 void MainWindow::pushButtonCurrentEmulatorOptionsImportFromFile_clicked(QString useFileName)
5689 {
5690 	qmc2EmulatorOptions->importFromIni(false, useFileName);
5691 }
5692 
5693 #if QMC2_JOYSTICK == 1
mapJoystickFunction(QString function)5694 void MainWindow::mapJoystickFunction(QString function)
5695 {
5696 	if ( qmc2CleaningUp )
5697 		return;
5698 
5699 	// don't map joystick functions while calibration or test are active
5700 	if ( qmc2Options->treeWidgetJoystickMappings->isHidden() )
5701 		return;
5702 
5703 	QString shortcut = qmc2CustomShortcutHash[qmc2JoystickFunctionHash[function]];
5704 
5705 #ifdef QMC2_DEBUG
5706 	log(QMC2_LOG_FRONTEND, QString("DEBUG: matched function = %1").arg(shortcut.isEmpty() ? "none" : shortcut));
5707 #endif
5708 
5709 	if ( shortcut.isEmpty() )
5710 		return;
5711 
5712 	QWidget *focusWidget = QApplication::focusWidget();
5713 
5714 	if ( focusWidget ) {
5715 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
5716 		// don't map joystick functions when they are really meant for an embedded emulator
5717 		if ( focusWidget->objectName() == "QMC2_EMBED_CONTAINER" )
5718 			return;
5719 #endif
5720 		QKeySequence keySeq(shortcut);
5721 		int key = 0;
5722 #if QT_VERSION < 0x050000
5723 		for (uint i = 0; i < keySeq.count(); i++)
5724 			key += keySeq[i];
5725 #else
5726 		for (int i = 0; i < keySeq.count(); i++)
5727 			key += keySeq[i];
5728 #endif
5729 		QKeyEvent *emulatedKeyEvent = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
5730 		qApp->postEvent(focusWidget, emulatedKeyEvent);
5731 	}
5732 }
5733 
joystickAxisValueChanged(int axis,int value)5734 void MainWindow::joystickAxisValueChanged(int axis, int value)
5735 {
5736 	if ( qmc2Config->value(QString(QMC2_FRONTEND_PREFIX + "Joystick/%1/Axis%2Enabled").arg(joyIndex).arg(axis), true).toBool() ) {
5737 		if ( value != 0 )
5738 			mapJoystickFunction(QString("A%1%2").arg(axis).arg(value < 0 ? "-" : "+"));
5739 	}
5740 }
5741 
joystickButtonValueChanged(int button,bool value)5742 void MainWindow::joystickButtonValueChanged(int button, bool value)
5743 {
5744 	if ( value )
5745 		mapJoystickFunction(QString("B%1").arg(button));
5746 }
5747 
joystickHatValueChanged(int hat,int value)5748 void MainWindow::joystickHatValueChanged(int hat, int value)
5749 {
5750 	if ( value != 0 )
5751 		mapJoystickFunction(QString("H%1:%2").arg(hat).arg(value));
5752 }
5753 
joystickTrackballValueChanged(int trackball,int deltaX,int deltaY)5754 void MainWindow::joystickTrackballValueChanged(int trackball, int deltaX, int deltaY)
5755 {
5756 	mapJoystickFunction(QString("T%1:X%2,Y%3").arg(trackball).arg(deltaX < 0 ? "-" : deltaX > 0 ? "+" : "=").arg(deltaY < 0 ? "-" : deltaY > 0 ? "+" : "="));
5757 }
5758 #endif
5759 
closeEvent(QCloseEvent * e)5760 void MainWindow::closeEvent(QCloseEvent *e)
5761 {
5762 	if ( qmc2CleaningUp ) {
5763 		e->ignore();
5764 		return;
5765 	}
5766 
5767 	if ( qmc2ReloadActive || qmc2VerifyActive || qmc2VerifyTaggedActive || qmc2FilterActive || qmc2ImageCheckActive || qmc2SampleCheckActive || (qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active()) || (qmc2SoftwareROMAlyzer && qmc2SoftwareROMAlyzer->active()) || qmc2LoadingMachineInfoDB || qmc2LoadingSoftwareInfoDB || qmc2LoadingEmuInfoDB ) {
5768 		qmc2LoadingInterrupted = true;
5769 		log(QMC2_LOG_FRONTEND, tr("stopping current processing upon user request"));
5770 		e->ignore();
5771 		return;
5772 	}
5773 
5774 	if ( qmc2SoftwareList && qmc2SoftwareList->isLoading ) {
5775 		qmc2SoftwareList->interruptLoad = true;
5776 		log(QMC2_LOG_FRONTEND, tr("stopping current processing upon user request"));
5777 		e->ignore();
5778 		return;
5779 	}
5780 
5781 	if ( !qmc2Options->applied ) {
5782 		switch ( QMessageBox::question(this, tr("Confirm"),
5783 					tr("Your configuration changes have not been applied yet.\nReally quit?"),
5784 					QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
5785 			case QMessageBox::No:
5786 				e->ignore();
5787 				return;
5788 				break;
5789 
5790 			default:
5791 				break;
5792 		}
5793 	}
5794 
5795 	bool doKillEmulators = qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/KillEmulatorsOnExit").toBool();
5796 	if ( qmc2ProcessManager->procMap.count() > 0 && !doKillEmulators ) {
5797 		switch ( QMessageBox::question(this, tr("Confirm"),
5798 					tr("There are one or more emulators still running.\nShould they be killed on exit?"),
5799 					QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel) ) {
5800 			case QMessageBox::Yes:
5801 				doKillEmulators = true;
5802 				break;
5803 
5804 			case QMessageBox::No:
5805 				doKillEmulators = false;
5806 				break;
5807 
5808 			case QMessageBox::Cancel:
5809 				e->ignore();
5810 				return;
5811 				break;
5812 
5813 			default:
5814 				break;
5815 		}
5816 	}
5817 
5818 	QList<int> indexList;
5819 	int runningDownloads = 0;
5820 	QTreeWidgetItemIterator it(treeWidgetDownloads);
5821 	while ( *it ) {
5822 		indexList << treeWidgetDownloads->indexOfTopLevelItem(*it);
5823 		if ( (*it)->whatsThis(0) == "downloading" || (*it)->whatsThis(0) == "initializing" )
5824 			runningDownloads++;
5825 		it++;
5826 	}
5827 	if ( runningDownloads > 0 ) {
5828 		switch ( QMessageBox::question(this, tr("Confirm"),
5829 					tr("There are one or more running downloads. Quit anyway?"),
5830 					QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
5831 			case QMessageBox::Yes:
5832 				break;
5833 
5834 			case QMessageBox::No:
5835 				e->ignore();
5836 				return;
5837 
5838 			default:
5839 				break;
5840 		}
5841 	}
5842 
5843 	log(QMC2_LOG_FRONTEND, tr("cleaning up"));
5844 	qmc2CleaningUp = true;
5845 
5846 	if ( runningDownloads > 0 )
5847 		log(QMC2_LOG_FRONTEND, tr("aborting running downloads"));
5848 	foreach (int i, indexList) {
5849 		DownloadItem *item = (DownloadItem *)treeWidgetDownloads->takeTopLevelItem(i);
5850 		if ( item ) {
5851 			if ( item->whatsThis(0) == "downloading" || item->whatsThis(0) == "initializing" )
5852 				item->itemDownloader->networkReply->abort();
5853 			delete item;
5854 		}
5855 	}
5856 
5857 	if ( attachedViewer() )
5858 		attachedViewer()->saveView();
5859 
5860 #if defined(QMC2_YOUTUBE_ENABLED)
5861 	if ( !qmc2YouTubeVideoInfoHash.isEmpty() && qmc2YouTubeVideoInfoHashChanged ) {
5862 		log(QMC2_LOG_FRONTEND, tr("saving YouTube video info cache"));
5863 		QDir youTubeCacheDir(qmc2Config->value(QMC2_FRONTEND_PREFIX + "YouTubeWidget/CacheDirectory").toString());
5864 		if ( youTubeCacheDir.exists() ) {
5865 #if defined(QMC2_SDLMAME)
5866 			QFile f(youTubeCacheDir.canonicalPath() + "/qmc2-sdlmame.yti");
5867 #elif defined(QMC2_MAME)
5868 			QFile f(youTubeCacheDir.canonicalPath() + "/qmc2-mame.yti");
5869 #else
5870 			QFile f(youTubeCacheDir.canonicalPath() + "/qmc2.yti");
5871 #endif
5872 			if ( f.open(QIODevice::WriteOnly | QIODevice::Text) ) {
5873 				QTextStream ts(&f);
5874 				ts << "# THIS FILE IS AUTO-GENERATED - PLEASE DO NOT EDIT!\n";
5875 				QHashIterator<QString, YouTubeVideoInfo> it(qmc2YouTubeVideoInfoHash);
5876 				while ( it.hasNext() ) {
5877 					it.next();
5878 					ts << it.key() << "\t" << it.value().author << "\t" << it.value().title << "\n";
5879 				}
5880 				f.close();
5881 				log(QMC2_LOG_FRONTEND, tr("done (saving YouTube video info cache)"));
5882 			} else
5883 				log(QMC2_LOG_FRONTEND, tr("failed (saving YouTube video info cache)"));
5884 		} else
5885 			log(QMC2_LOG_FRONTEND, tr("failed (saving YouTube video info cache)"));
5886 	}
5887 #endif
5888 
5889 #if QMC2_USE_PHONON_API
5890 	log(QMC2_LOG_FRONTEND, tr("disconnecting audio source from audio sink"));
5891 	phononAudioPath.disconnect();
5892 	if ( qmc2AudioEffectDialog ) {
5893 		log(QMC2_LOG_FRONTEND, tr("destroying audio effects dialog"));
5894 		qmc2AudioEffectDialog->close();
5895 		delete qmc2AudioEffectDialog;
5896 	}
5897 	if ( phononAudioOutput )
5898 		delete phononAudioOutput;
5899 	if ( phononAudioPlayer )
5900 		delete phononAudioPlayer;
5901 #endif
5902 #if QMC2_MULTIMEDIA_ENABLED
5903 	if ( mediaPlayer ) {
5904 		log(QMC2_LOG_FRONTEND, tr("destroying media player"));
5905 		mediaPlayer->disconnect();
5906 		delete mediaPlayer;
5907 	}
5908 #endif
5909 
5910 #if defined(QMC2_YOUTUBE_ENABLED)
5911 	if ( qmc2YouTubeWidget ) {
5912 		log(QMC2_LOG_FRONTEND, tr("destroying YouTube video widget"));
5913 		qmc2YouTubeWidget->saveSettings();
5914 		qmc2YouTubeWidget->forcedExit = true;
5915 		if ( qmc2YouTubeWidget->isPlaying() || qmc2YouTubeWidget->isPaused() )
5916 			qmc2YouTubeWidget->stop();
5917 		qmc2YouTubeWidget->close();
5918 		qmc2YouTubeWidget->deleteLater();
5919 		qmc2YouTubeWidget = 0;
5920 	}
5921 #endif
5922 
5923 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/RanksLocked", RankItemWidget::ranksLocked);
5924 
5925 	if ( !qmc2TemplateCheck ) {
5926 		if ( listWidgetFavorites->count() > 0 )
5927 			qmc2MachineList->saveFavorites();
5928 
5929 		if ( listWidgetPlayed->count() > 0 )
5930 			qmc2MachineList->savePlayHistory();
5931 
5932 		QStringList searchStrings;
5933 		for (int index = 0; index < comboBoxSearch->count(); index++)
5934 			searchStrings << comboBoxSearch->itemText(index);
5935 		if ( searchStrings.isEmpty() )
5936 			qmc2Config->remove(QMC2_FRONTEND_PREFIX + "MachineSearchHistory");
5937 		else
5938 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "MachineSearchHistory", searchStrings);
5939 
5940 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "GUI/MachineListView", comboBoxViewSelect->currentIndex());
5941 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/SaveMachineSelection").toBool() ) {
5942 			if ( qmc2CurrentItem ) {
5943 				log(QMC2_LOG_FRONTEND, tr("saving machine selection"));
5944 				qmc2Config->setValue(QMC2_EMULATOR_PREFIX + "SelectedMachine", qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
5945 			} else
5946 				qmc2Config->remove(QMC2_EMULATOR_PREFIX + "SelectedMachine");
5947 		}
5948 
5949 		QTreeWidgetItem *foreignItem = treeWidgetForeignIDs->currentItem();
5950 		if ( foreignItem && foreignItem->isSelected() ) {
5951 			QTreeWidgetItem *parentItem = foreignItem;
5952 			if ( foreignItem->parent() )
5953 				parentItem = foreignItem->parent();
5954 			QStringList foreignIdState;
5955 			if ( parentItem == foreignItem )
5956 				foreignIdState << QString::number(treeWidgetForeignIDs->indexOfTopLevelItem(parentItem));
5957 			else
5958 				foreignIdState << QString::number(treeWidgetForeignIDs->indexOfTopLevelItem(parentItem)) << QString::number(parentItem->indexOfChild(foreignItem));
5959 			qmc2Config->setValue(QMC2_EMULATOR_PREFIX + "SelectedForeignID", foreignIdState);
5960 		} else
5961 			qmc2Config->remove(QMC2_EMULATOR_PREFIX + "SelectedForeignID");
5962 
5963 		log(QMC2_LOG_FRONTEND, tr("saving main widget layout"));
5964 		if ( windowState() & Qt::WindowFullScreen ) {
5965 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Fullscreen", true);
5966 		} else {
5967 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Fullscreen", false);
5968 			if ( isMaximized() ) {
5969 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Maximized", true);
5970 			} else {
5971 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Maximized", false);
5972 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Geometry", saveGeometry());
5973 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Position", pos());
5974 				qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/Size", size());
5975 			}
5976 		}
5977 
5978 		ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
5979 
5980 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
5981 		int currentIndex = tabWidgetMachineList->currentIndex();
5982 		int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
5983 		if ( embedIndex >= 0 && embedIndex <= currentIndex )
5984 			if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
5985 				currentIndex++;
5986 		int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
5987 		if ( foreignIndex >= 0 && foreignIndex <= currentIndex )
5988 			if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
5989 				currentIndex++;
5990 		if ( toolButtonEmbedderMaximizeToggle->isChecked() && componentInfo->appliedFeatureList().at(currentIndex) == QMC2_EMBED_INDEX )
5991 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/hSplitter", QSize(hSplitterSizes[0], hSplitterSizes[1]));
5992 		else
5993 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/hSplitter", QSize(hSplitter->sizes().at(0), hSplitter->sizes().at(1)));
5994 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Embedder/Maximize", toolButtonEmbedderMaximizeToggle->isChecked());
5995 #if defined(QMC2_OS_UNIX)
5996 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/Embedder/AutoPause", toolButtonEmbedderAutoPause->isChecked());
5997 #endif
5998 #else
5999 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/hSplitter", QSize(hSplitter->sizes().at(0), hSplitter->sizes().at(1)));
6000 #endif
6001 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/vSplitter", QSize(vSplitterSizes.at(0), vSplitterSizes.at(1)));
6002 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/vSplitterSoftwareDetail", QSize(vSplitterSizesSoftwareDetail.at(0), vSplitterSizesSoftwareDetail.at(1)));
6003 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6004 		if ( componentInfo->appliedFeatureList().at(currentIndex) == QMC2_EMBED_INDEX )
6005 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListTab", qmc2LastListIndex);
6006 		else
6007 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListTab", tabWidgetMachineList->currentIndex());
6008 #else
6009 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListTab", tabWidgetMachineList->currentIndex());
6010 #endif
6011 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineDetailTab", tabWidgetMachineDetail->currentIndex());
6012 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/LogsAndEmulatorsTab", tabWidgetLogsAndEmulators->currentIndex());
6013 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailTab", tabWidgetSoftwareDetail->currentIndex());
6014 		// save toolbar state
6015 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ToolbarState", saveState());
6016 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListHeaderState", treeWidgetMachineList->header()->saveState());
6017 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/HierarchyHeaderState", treeWidgetHierarchy->header()->saveState());
6018 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/CategoryViewHeaderState", treeWidgetCategoryView->header()->saveState());
6019 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/VersionViewHeaderState", treeWidgetVersionView->header()->saveState());
6020 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/EmulatorControlHeaderState", treeWidgetEmulators->header()->saveState());
6021 
6022 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailDocked", floatToggleButtonSoftwareDetail->isChecked());
6023 		if ( !floatToggleButtonSoftwareDetail->isChecked() )
6024 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry", tabWidgetSoftwareDetail->saveGeometry());
6025 
6026 #if QMC2_USE_PHONON_API || QMC2_MULTIMEDIA_ENABLED
6027 		QStringList psl;
6028 		for (int i = 0; i < listWidgetAudioPlaylist->count(); i++)
6029 			psl << listWidgetAudioPlaylist->item(i)->text();
6030 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayList", psl);
6031 		if ( listWidgetAudioPlaylist->currentItem() )
6032 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/LastTrack", listWidgetAudioPlaylist->currentItem()->text());
6033 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayOnStart", checkBoxAudioPlayOnStart->isChecked());
6034 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/Shuffle", checkBoxAudioShuffle->isChecked());
6035 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/Pause", checkBoxAudioPause->isChecked());
6036 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/Fade", checkBoxAudioFade->isChecked());
6037 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "AudioPlayer/Volume", dialAudioVolume->value());
6038 #endif
6039 	}
6040 
6041 	// download manager widget
6042 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Downloads/RemoveFinished", checkBoxRemoveFinishedDownloads->isChecked());
6043 
6044 	// search box options
6045 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/NegateSearch", actionNegateSearch->isChecked());
6046 
6047 	if ( qmc2SystemNotesEditor ) {
6048 		qmc2SystemNotesEditor->stopLoading = true;
6049 		qmc2SystemNotesEditor->save();
6050 		qmc2SystemNotesEditor->close();
6051 		delete qmc2SystemNotesEditor;
6052 		qmc2SystemNotesEditor = 0;
6053 	}
6054 
6055 	if ( qmc2SoftwareList ) {
6056 		if ( qmc2SoftwareNotesEditor ) {
6057 			qmc2SoftwareNotesEditor->save();
6058 			qmc2SoftwareNotesEditor->close();
6059 			delete qmc2SoftwareNotesEditor;
6060 		}
6061 		if ( qmc2SoftwareList->fullyLoaded ) {
6062 			log(QMC2_LOG_FRONTEND, tr("saving current machine's favorite software"));
6063 			qmc2SoftwareList->save();
6064 		}
6065 		delete qmc2SoftwareList;
6066 	}
6067 	if ( qmc2DeviceConfigurator ) {
6068 		log(QMC2_LOG_FRONTEND, tr("saving current machine's device configurations"));
6069 		qmc2DeviceConfigurator->save();
6070 		qmc2DeviceConfigurator->saveSetup();
6071 		delete qmc2DeviceConfigurator;
6072 	}
6073 
6074 	if ( swlDb ) {
6075 		QString connectionName = swlDb->connectionName();
6076 		delete swlDb;
6077 		QSqlDatabase::removeDatabase(connectionName);
6078 	}
6079 
6080 	log(QMC2_LOG_FRONTEND, tr("destroying emulator configuration instances"));
6081 	if ( qmc2EmulatorOptions ) {
6082 		QString selectedEmulator = comboBoxEmuSelector->currentText();
6083 		if ( selectedEmulator == tr("Default") || selectedEmulator.isEmpty() )
6084 			qmc2Config->remove(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator");
6085 		else
6086 			qmc2Config->setValue(qmc2EmulatorOptions->settingsGroup + "/SelectedEmulator", selectedEmulator);
6087 		qmc2EmulatorOptions->save();
6088 		delete qmc2EmulatorOptions;
6089 	}
6090 	qmc2GlobalEmulatorOptions->saveHeaderState();
6091 	qmc2GlobalEmulatorOptions->setParent(0);
6092 	log(QMC2_LOG_FRONTEND, tr("destroying machine list"));
6093 	delete qmc2MachineList;
6094 
6095 	log(QMC2_LOG_FRONTEND, tr("destroying image widgets"));
6096 	if ( qmc2Preview )
6097 		delete qmc2Preview;
6098 	if ( qmc2Flyer )
6099 		delete qmc2Flyer;
6100 	if ( qmc2Cabinet )
6101 		delete qmc2Cabinet;
6102 	if ( qmc2Controller )
6103 		delete qmc2Controller;
6104 	if ( qmc2Marquee )
6105 		delete qmc2Marquee;
6106 	if ( qmc2Title )
6107 		delete qmc2Title;
6108 	if ( qmc2PCB )
6109 		delete qmc2PCB;
6110 	if ( qmc2SoftwareSnapshot )
6111 		delete qmc2SoftwareSnapshot;
6112 	if ( qmc2SoftwareSnap )
6113 		delete qmc2SoftwareSnap;
6114 
6115 	log(QMC2_LOG_FRONTEND, tr("destroying open dialogs"));
6116 	if ( qmc2About )
6117 		delete qmc2About;
6118 	if ( qmc2DocBrowser ) {
6119 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/DocBrowser/Zoom", qmc2DocBrowser->browser->spinBoxZoom->value());
6120 		delete qmc2DocBrowser;
6121 	}
6122 	if ( qmc2ProjectMESSLookup )
6123 		delete qmc2ProjectMESSLookup;
6124 	if ( qmc2ImageChecker ) {
6125 		qmc2ImageChecker->close();
6126 		delete qmc2ImageChecker;
6127 	}
6128 	if ( qmc2SampleChecker ) {
6129 		qmc2SampleChecker->close();
6130 		delete qmc2SampleChecker;
6131 	}
6132 	if ( qmc2SystemROMAlyzer ) {
6133 		qmc2SystemROMAlyzer->saveState();
6134 		delete qmc2SystemROMAlyzer;
6135 	}
6136 	if ( qmc2SoftwareROMAlyzer ) {
6137 		qmc2SoftwareROMAlyzer->saveState();
6138 		delete qmc2SoftwareROMAlyzer;
6139 	}
6140 	if ( qmc2ROMStatusExporter ) {
6141 		qmc2ROMStatusExporter->close();
6142 		delete qmc2ROMStatusExporter;
6143 	}
6144 	if ( qmc2ComponentSetup ) {
6145 		qmc2ComponentSetup->close();
6146 		delete qmc2ComponentSetup;
6147 	}
6148 	if ( qmc2ToolBarCustomizer ) {
6149 		qmc2ToolBarCustomizer->close();
6150 		delete qmc2ToolBarCustomizer;
6151 	}
6152 	if ( qmc2DemoModeDialog ) {
6153 		qmc2DemoModeDialog->close();
6154 		delete qmc2DemoModeDialog;
6155 	}
6156 
6157 	log(QMC2_LOG_FRONTEND, tr("destroying process manager"));
6158 	if ( qmc2ProcessManager->procMap.count() > 0 ) {
6159 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6160 		for (int j = 0; j < tabWidgetEmbeddedEmulators->count(); j++) {
6161 			Embedder *embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(j);
6162 			if ( embedder )
6163 				embedder->release();
6164 		}
6165 #endif
6166 		if ( doKillEmulators ) {
6167 			log(QMC2_LOG_FRONTEND, tr("killing %n running emulator(s) on exit", "", qmc2ProcessManager->procMap.count()));
6168 			delete qmc2ProcessManager;
6169 		} else
6170 			log(QMC2_LOG_FRONTEND, tr("keeping %n running emulator(s) alive", "", qmc2ProcessManager->procMap.count()));
6171 	} else
6172 		delete qmc2ProcessManager;
6173 
6174 	if ( qmc2NetworkAccessManager ) {
6175 		log(QMC2_LOG_FRONTEND, tr("destroying network access manager"));
6176 		delete qmc2NetworkAccessManager;
6177 	}
6178 
6179 	log(QMC2_LOG_FRONTEND, tr("so long and thanks for all the fish"));
6180 
6181 	qmc2Config->setValue(QString(QMC2_FRONTEND_PREFIX + "InstanceRunning"), false);
6182 
6183 #if QT_VERSION < 0x050000
6184 	qInstallMsgHandler(0);
6185 #else
6186 	qInstallMessageHandler(0);
6187 #endif
6188 	delete qmc2MainEventFilter;
6189 	delete m_searchBoxKeyEventFilter;
6190 
6191 	// remove possible left-overs
6192 	QApplication::closeAllWindows();
6193 
6194 	delete qmc2Options;
6195 	e->accept();
6196 
6197 	// reconfigure restart requested?
6198 	if ( qmc2ReconfigureRestartRequested ) {
6199 		QStringList args(qApp->arguments());
6200 		args << "-r";
6201 		QProcess::startDetached(args.at(0), args);
6202 	}
6203 }
6204 
showEvent(QShowEvent * e)6205 void MainWindow::showEvent(QShowEvent *e)
6206 {
6207 	if ( !qmc2AutoMinimizedWidgets.isEmpty() ) {
6208 		QMapIterator<QWidget *, Qt::WindowStates> it(qmc2AutoMinimizedWidgets);
6209 		while ( it.hasNext() ) {
6210 			it.next();
6211 			it.key()->setWindowState(it.value());
6212 		}
6213 		qmc2AutoMinimizedWidgets.clear();
6214 	}
6215 }
6216 
resizeEvent(QResizeEvent * e)6217 void MainWindow::resizeEvent(QResizeEvent *e)
6218 {
6219 	static bool mainWindowResizeEventActive = false;
6220 
6221 	if ( mainWindowResizeEventActive )
6222 		return;
6223 	else
6224 		mainWindowResizeEventActive = true;
6225 
6226 	bool refreshViews = true;
6227 
6228 	if ( e ) {
6229 		refreshViews = (e->oldSize().height() != e->size().height());
6230 		QMainWindow::resizeEvent(e);
6231 	}
6232 
6233 	if ( refreshViews ) {
6234 		if ( tabWidgetMachineList->indexOf(tabMachineList) == tabWidgetMachineList->currentIndex() ) {
6235 			switch ( stackedWidgetView->currentIndex() ) {
6236 				case QMC2_VIEWHIERARCHY_INDEX:
6237 					QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetHierarchy_verticalScrollChanged()));
6238 					break;
6239 				case QMC2_VIEWCATEGORY_INDEX:
6240 					QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetCategoryView_verticalScrollChanged()));
6241 					break;
6242 				case QMC2_VIEWVERSION_INDEX:
6243 					QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetVersionView_verticalScrollChanged()));
6244 					break;
6245 				case QMC2_VIEWCUSTOM_INDEX:
6246 					// handled by custom view
6247 					break;
6248 				case QMC2_VIEWMACHINELIST_INDEX:
6249 				default:
6250 					QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetMachineList_verticalScrollChanged()));
6251 					break;
6252 			}
6253 		}
6254 	}
6255 
6256 	mainWindowResizeEventActive = false;
6257 }
6258 
init()6259 void MainWindow::init()
6260 {
6261 	if ( qmc2TemplateCheck )
6262 		return;
6263 
6264 #if QT_VERSION < 0x050000
6265 #if !(QMC2_USE_PHONON_API)
6266 	tabWidgetLogsAndEmulators->removeTab(tabWidgetLogsAndEmulators->indexOf(tabAudioPlayer));
6267 	menuTools->removeAction(menuAudioPlayer->menuAction());
6268 #else
6269 	audioState = Phonon::StoppedState;
6270 	phononAudioPlayer = new Phonon::MediaObject(this);
6271 	phononAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
6272 	phononAudioPath = Phonon::createPath(phononAudioPlayer, phononAudioOutput);
6273 	listWidgetAudioPlaylist->setTextElideMode(Qt::ElideMiddle);
6274 	listWidgetAudioPlaylist->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
6275 	QStringList psl(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayList").toStringList());
6276 	listWidgetAudioPlaylist->addItems(psl);
6277 	int row = psl.indexOf(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/LastTrack", QString()).toString());
6278 	if ( row >= 0 ) {
6279 		listWidgetAudioPlaylist->setCurrentRow(row);
6280 		listWidgetAudioPlaylist->scrollToItem(listWidgetAudioPlaylist->item(row), qmc2CursorPositioningMode);
6281 		qmc2AudioLastIndividualTrack = psl.at(row);
6282 	}
6283 	checkBoxAudioPlayOnStart->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayOnStart", false).toBool());
6284 	checkBoxAudioShuffle->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Shuffle", false).toBool());
6285 	checkBoxAudioPause->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Pause", true).toBool());
6286 	checkBoxAudioFade->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Fade", true).toBool());
6287 	dialAudioVolume->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Volume", 50).toInt());
6288 	phononAudioOutput->setVolume((qreal)dialAudioVolume->value()/100.0);
6289 	toolButtonAudioPreviousTrack->setDefaultAction(actionAudioPreviousTrack);
6290 	toolButtonAudioNextTrack->setDefaultAction(actionAudioNextTrack);
6291 	toolButtonAudioStopTrack->setDefaultAction(actionAudioStopTrack);
6292 	toolButtonAudioPauseTrack->setDefaultAction(actionAudioPauseTrack);
6293 	toolButtonAudioPlayTrack->setDefaultAction(actionAudioPlayTrack);
6294 	phononAudioPlayer->setTickInterval(1000);
6295 	connect(phononAudioPlayer, SIGNAL(tick(qint64)), this, SLOT(audioTick(qint64)));
6296 	connect(phononAudioPlayer, SIGNAL(totalTimeChanged(qint64)), this, SLOT(audioTotalTimeChanged(qint64)));
6297 	connect(phononAudioPlayer, SIGNAL(finished()), this, SLOT(audioFinished()));
6298 	connect(phononAudioPlayer, SIGNAL(metaDataChanged()), this, SLOT(audioMetaDataChanged()));
6299 	connect(phononAudioPlayer, SIGNAL(bufferStatus(int)), this, SLOT(audioBufferStatus(int)));
6300 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
6301 	if ( checkBoxAudioPlayOnStart->isChecked() ) {
6302 		audioState = Phonon::PlayingState;
6303 		QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
6304 	} else
6305 		QTimer::singleShot(0, this, SLOT(on_actionAudioStopTrack_triggered()));
6306 #endif
6307 #else
6308 #if !(QMC2_MULTIMEDIA_ENABLED)
6309 	tabWidgetLogsAndEmulators->removeTab(tabWidgetLogsAndEmulators->indexOf(tabAudioPlayer));
6310 	menuTools->removeAction(menuAudioPlayer->menuAction());
6311 #else
6312 	audioState = QMediaPlayer::StoppedState;
6313 	mediaPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
6314 	listWidgetAudioPlaylist->setTextElideMode(Qt::ElideMiddle);
6315 	listWidgetAudioPlaylist->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
6316 	QStringList psl(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayList").toStringList());
6317 	listWidgetAudioPlaylist->addItems(psl);
6318 	int row = psl.indexOf(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/LastTrack", QString()).toString());
6319 	if ( row >= 0 ) {
6320 		listWidgetAudioPlaylist->setCurrentRow(row);
6321 		listWidgetAudioPlaylist->scrollToItem(listWidgetAudioPlaylist->item(row), qmc2CursorPositioningMode);
6322 		qmc2AudioLastIndividualTrack = psl.at(row);
6323 	}
6324 	checkBoxAudioPlayOnStart->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/PlayOnStart", false).toBool());
6325 	checkBoxAudioShuffle->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Shuffle", false).toBool());
6326 	checkBoxAudioPause->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Pause", true).toBool());
6327 	checkBoxAudioFade->setChecked(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Fade", true).toBool());
6328 	dialAudioVolume->setValue(qmc2Config->value(QMC2_FRONTEND_PREFIX + "AudioPlayer/Volume", 50).toInt());
6329 	mediaPlayer->setVolume(dialAudioVolume->value());
6330 	toolButtonAudioPreviousTrack->setDefaultAction(actionAudioPreviousTrack);
6331 	toolButtonAudioNextTrack->setDefaultAction(actionAudioNextTrack);
6332 	toolButtonAudioStopTrack->setDefaultAction(actionAudioStopTrack);
6333 	toolButtonAudioPauseTrack->setDefaultAction(actionAudioPauseTrack);
6334 	toolButtonAudioPlayTrack->setDefaultAction(actionAudioPlayTrack);
6335 	mediaPlayer->setNotifyInterval(1000);
6336 	connect(mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(audioTick(qint64)));
6337 	connect(mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(audioTotalTimeChanged(qint64)));
6338 	connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(audioStateChanged(QMediaPlayer::MediaStatus)));
6339 	connect(mediaPlayer, SIGNAL(metaDataChanged()), this, SLOT(audioMetaDataChanged()));
6340 	connect(mediaPlayer, SIGNAL(bufferStatusChanged(int)), this, SLOT(audioBufferStatus(int)));
6341 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
6342 	if ( checkBoxAudioPlayOnStart->isChecked() ) {
6343 		audioState = QMediaPlayer::PlayingState;
6344 		QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
6345 	} else
6346 		QTimer::singleShot(0, this, SLOT(on_actionAudioStopTrack_triggered()));
6347 #endif
6348 #endif
6349 
6350 	// signal setup requests for style, style-sheet and palette
6351 	signalStyleSetupRequested(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Style", "Default").toString());
6352 	signalStyleSheetSetupRequested(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/StyleSheet", QString()).toString());
6353 	signalPaletteSetupRequested(qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/Style", "Default").toString());
6354 
6355 	// recreate all components
6356 	foreach (QString component, qmc2ComponentSetup->components())
6357 		qmc2ComponentSetup->saveComponent(component);
6358 
6359 	if ( qmc2SplashScreen ) {
6360 		qmc2SplashScreen->showMessage(tr("Welcome to QMC2 v%1!").arg(XSTR(QMC2_VERSION)), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
6361 		QTimer::singleShot(QMC2_SPLASH_DURATION, qmc2SplashScreen, SLOT(hide()));
6362 	}
6363 
6364 	// tool-bar customization
6365 	qmc2ToolBarCustomizer = new ToolBarCustomizer(qmc2Options);
6366 
6367 #if defined(QMC2_OS_MAC)
6368 	qmc2Options->setParent(this, Qt::Dialog);
6369 #endif
6370 
6371 #if QMC2_USE_PHONON_API
6372 	QTimer::singleShot(0, this, SLOT(on_toolButtonAudioSetupEffects_clicked()));
6373 #endif
6374 
6375 	qmc2GhostImagePixmap.load(":/data/img/ghost.png");
6376 	qmc2GhostImagePixmap.isGhost = true;
6377 
6378 	qmc2LastListIndex = qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListTab", 0).toInt();
6379 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6380 	if ( qmc2LastListIndex == QMC2_EMBED_INDEX )
6381 		qmc2LastListIndex = 0;
6382 #endif
6383 	tabWidgetMachineList->blockSignals(true);
6384 	tabWidgetMachineList->setCurrentIndex(qmc2LastListIndex);
6385 	tabWidgetMachineList->blockSignals(false);
6386 	on_tabWidgetMachineList_currentChanged(qmc2LastListIndex);
6387 	floatToggleButtonSoftwareDetail_toggled(floatToggleButtonSoftwareDetail->isChecked());
6388 	ImageWidget::reloadArtworkFormats();
6389 	qmc2EarlyStartup = false;
6390 
6391 	// hide machine list / show loading animation initially
6392 	treeWidgetMachineList->setVisible(false);
6393 	((AspectRatioLabel *)labelLoadingMachineList)->setLabelText(tr("Loading, please wait..."));
6394 	labelLoadingMachineList->setVisible(true);
6395 
6396 	treeWidgetHierarchy->setVisible(false);
6397 	((AspectRatioLabel *)labelLoadingHierarchy)->setLabelText(tr("Loading, please wait..."));
6398 	labelLoadingHierarchy->setVisible(true);
6399 
6400 	treeWidgetCategoryView->setVisible(false);
6401 	((AspectRatioLabel *)labelCreatingCategoryView)->setLabelText(tr("Loading, please wait..."));
6402 	labelCreatingCategoryView->setVisible(true);
6403 
6404 	treeWidgetVersionView->setVisible(false);
6405 	((AspectRatioLabel *)labelCreatingVersionView)->setLabelText(tr("Loading, please wait..."));
6406 	labelCreatingVersionView->setVisible(true);
6407 
6408 	attachedViewsWidget->setVisible(false);
6409 	((AspectRatioLabel *)labelLoadingAttachedViews)->setLabelText(tr("Loading, please wait..."));
6410 	labelLoadingAttachedViews->setVisible(true);
6411 
6412 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowLoadingAnimation", true).toBool() )
6413 		loadAnimMovie->start();
6414 
6415 	// restore machine search history
6416 	QStringList machineSearchHistory(qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineSearchHistory", QStringList()).toStringList());
6417 	machineSearchHistory.removeDuplicates();
6418 	while ( machineSearchHistory.count() > QMC2_MACHINE_SEARCH_HISTORY_LENGTH )
6419 		machineSearchHistory.removeLast();
6420 	comboBoxToolbarSearch->blockSignals(true);
6421 	comboBoxToolbarSearch->addItems(machineSearchHistory);
6422 	comboBoxToolbarSearch->lineEdit()->setText(QString());
6423 	comboBoxToolbarSearch->blockSignals(false);
6424 	comboBoxSearch->blockSignals(true);
6425 	comboBoxSearch->addItems(machineSearchHistory);
6426 	comboBoxSearch->lineEdit()->setText(QString());
6427 	comboBoxSearch->blockSignals(false);
6428 
6429 	// disable the system manual actions initially
6430 	checkSystemManualAvailability();
6431 
6432 	// process the queued events
6433 	setUpdatesEnabled(true);
6434 	setVisible(true);
6435 	qApp->processEvents();
6436 
6437 	// make sure the logs are scrolled to their maxima
6438 	logScrollToEnd(QMC2_LOG_FRONTEND);
6439 	logScrollToEnd(QMC2_LOG_EMULATOR);
6440 
6441 	// trigger initial load
6442 	QTimer::singleShot(0, this, SLOT(updateTabWidgets()));
6443 	QTimer::singleShot(0, this, SLOT(on_actionReload_triggered()));
6444 
6445 	activityCheckTimer.start(QMC2_ACTIVITY_CHECK_INTERVAL);
6446 }
6447 
setupStyle(QString styleName)6448 void MainWindow::setupStyle(QString styleName)
6449 {
6450 	if ( qmc2Options->currentStyleName() == styleName )
6451 		return;
6452 	QStyle *newStyle = 0;
6453 	if ( styleName != "Default" ) {
6454 		if ( QStyleFactory::keys().contains(styleName) )
6455 			newStyle = QStyleFactory::create(styleName);
6456 		else {
6457 			newStyle = QStyleFactory::create(defaultStyle);
6458 			styleName = "Default";
6459 		}
6460 	} else {
6461 		newStyle = QStyleFactory::create(defaultStyle);
6462 		styleName = "Default";
6463 	}
6464 	if ( newStyle ) {
6465 		log(QMC2_LOG_FRONTEND, tr("setting GUI style to '%1'").arg(styleName));
6466 		if ( !qmc2StandardPalettes.contains(styleName) )
6467 			qmc2StandardPalettes[styleName] = newStyle->standardPalette();
6468 		if ( !proxyStyle ) {
6469 			proxyStyle = new ProxyStyle;
6470 			proxyStyle->setBaseStyle(newStyle);
6471 			qApp->setStyle(proxyStyle);
6472 		} else {
6473 			QStyle *oldBaseStyle = proxyStyle->baseStyle();
6474 			proxyStyle->setBaseStyle(newStyle);
6475 			delete oldBaseStyle;
6476 		}
6477 		qmc2Options->setCurrentStyleName(styleName);
6478 	} else
6479 		log(QMC2_LOG_FRONTEND, tr("WARNING: GUI style '%1' not found").arg(styleName));
6480 }
6481 
setupStyleSheet(QString styleSheetName)6482 void MainWindow::setupStyleSheet(QString styleSheetName)
6483 {
6484 	static QString oldStyleSheetName;
6485 	if ( !styleSheetName.isEmpty() ) {
6486 		QFile f(styleSheetName);
6487 		if ( f.open(QIODevice::ReadOnly) ) {
6488 			if ( styleSheetName != oldStyleSheetName )
6489 				log(QMC2_LOG_FRONTEND, tr("loading style sheet '%1'").arg(styleSheetName));
6490 			if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/SetWorkDirFromExec", false).toBool() )
6491 				QDir::setCurrent(QFileInfo(f).absolutePath());
6492 			qApp->setStyleSheet(f.readAll());
6493 			f.close();
6494 		} else
6495 			log(QMC2_LOG_FRONTEND, tr("WARNING: can't open style sheet '%1'").arg(styleSheetName));
6496 	} else {
6497 		if ( !qApp->styleSheet().isEmpty() )
6498 			log(QMC2_LOG_FRONTEND, tr("removing current style sheet"));
6499 		qApp->setStyleSheet(QString());
6500 	}
6501 	oldStyleSheetName = styleSheetName;
6502 }
6503 
setupPalette(QString styleName)6504 void MainWindow::setupPalette(QString styleName)
6505 {
6506 	static QPalette oldPalette;
6507 	qmc2Options->loadCustomPalette(styleName);
6508 	QPalette newPalette;
6509 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/StandardColorPalette", true).toBool() ) {
6510 		newPalette = qmc2StandardPalettes[styleName];
6511 		if ( oldPalette != newPalette )
6512 			log(QMC2_LOG_FRONTEND, tr("using default color palette for GUI style '%1'").arg(styleName));
6513 	} else {
6514 		newPalette = qmc2CustomPalette;
6515 		if ( oldPalette != newPalette )
6516 			log(QMC2_LOG_FRONTEND, tr("using custom color palette"));
6517 	}
6518 	qApp->setPalette(newPalette);
6519 	// work around for an annoying Qt bug
6520 	menuBar()->setPalette(newPalette);
6521 	toolbar->setPalette(newPalette);
6522 	oldPalette = newPalette;
6523 }
6524 
viewFullDetail()6525 void MainWindow::viewFullDetail()
6526 {
6527 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
6528 	int index = componentInfo->appliedFeatureList().indexOf(QMC2_MACHINELIST_INDEX);
6529 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6530 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
6531 	if ( index > 0 && embedIndex >= 0 && embedIndex <= index )
6532 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
6533 			index--;
6534 #endif
6535 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
6536 	if ( index > 0 && foreignIndex >= 0 && foreignIndex <= index )
6537 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
6538 			index--;
6539 	stackedWidgetView->setCurrentIndex(QMC2_VIEWMACHINELIST_INDEX);
6540 	comboBoxViewSelect->blockSignals(true);
6541 	comboBoxViewSelect->setCurrentIndex(QMC2_VIEWMACHINELIST_INDEX);
6542 	comboBoxViewSelect->blockSignals(false);
6543 	tabWidgetMachineList->setCurrentIndex(index);
6544 	tabWidgetMachineList->setTabIcon(index, QIcon(QString::fromUtf8(":/data/img/flat.png")));
6545 	menuView->setIcon(QIcon(QString::fromUtf8(":/data/img/flat.png")));
6546 	treeWidgetMachineList->setFocus();
6547 	stackedWidgetView->update();
6548 	qApp->processEvents();
6549 }
6550 
viewParentClones()6551 void MainWindow::viewParentClones()
6552 {
6553 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
6554 	int index = componentInfo->appliedFeatureList().indexOf(QMC2_MACHINELIST_INDEX);
6555 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6556 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
6557 	if ( index > 0 && embedIndex >= 0 && embedIndex <= index )
6558 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
6559 			index--;
6560 #endif
6561 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
6562 	if ( index > 0 && foreignIndex >= 0 && foreignIndex <= index )
6563 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
6564 			index--;
6565 	stackedWidgetView->setCurrentIndex(QMC2_VIEWHIERARCHY_INDEX);
6566 	comboBoxViewSelect->blockSignals(true);
6567 	comboBoxViewSelect->setCurrentIndex(QMC2_VIEWHIERARCHY_INDEX);
6568 	comboBoxViewSelect->blockSignals(false);
6569 	tabWidgetMachineList->setCurrentIndex(index);
6570 	tabWidgetMachineList->setTabIcon(index, QIcon(QString::fromUtf8(":/data/img/clone.png")));
6571 	menuView->setIcon(QIcon(QString::fromUtf8(":/data/img/clone.png")));
6572 	treeWidgetHierarchy->setFocus();
6573 	stackedWidgetView->update();
6574 	qApp->processEvents();
6575 }
6576 
viewByCategory()6577 void MainWindow::viewByCategory()
6578 {
6579 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
6580 	int index = componentInfo->appliedFeatureList().indexOf(QMC2_MACHINELIST_INDEX);
6581 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6582 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
6583 	if ( index > 0 && embedIndex >= 0 && embedIndex <= index )
6584 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
6585 			index--;
6586 #endif
6587 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
6588 	if ( index > 0 && foreignIndex >= 0 && foreignIndex <= index )
6589 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
6590 			index--;
6591 	stackedWidgetView->setCurrentIndex(QMC2_VIEWCATEGORY_INDEX);
6592 	comboBoxViewSelect->blockSignals(true);
6593 	comboBoxViewSelect->setCurrentIndex(QMC2_VIEWCATEGORY_INDEX);
6594 	comboBoxViewSelect->blockSignals(false);
6595 	tabWidgetMachineList->setCurrentIndex(index);
6596 	tabWidgetMachineList->setTabIcon(index, QIcon(QString::fromUtf8(":/data/img/category.png")));
6597 	menuView->setIcon(QIcon(QString::fromUtf8(":/data/img/category.png")));
6598 	QTreeWidgetItem *item = treeWidgetCategoryView->topLevelItem(0);
6599 	if ( item ) {
6600 		if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData ) {
6601 			treeWidgetCategoryView->setVisible(false);
6602 			((AspectRatioLabel *)labelCreatingCategoryView)->setLabelText(tr("Loading, please wait..."));
6603 			labelCreatingCategoryView->setVisible(true);
6604 			QTimer::singleShot(0, qmc2MachineList, SLOT(createCategoryView()));
6605 		} else
6606 			QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetCategoryView_verticalScrollChanged()));
6607 	} else {
6608 		treeWidgetCategoryView->setVisible(false);
6609 		((AspectRatioLabel *)labelCreatingCategoryView)->setLabelText(tr("Loading, please wait..."));
6610 		labelCreatingCategoryView->setVisible(true);
6611 		QTimer::singleShot(0, qmc2MachineList, SLOT(createCategoryView()));
6612 	}
6613 	treeWidgetCategoryView->setFocus();
6614 	stackedWidgetView->update();
6615 	qApp->processEvents();
6616 }
6617 
viewByVersion()6618 void MainWindow::viewByVersion()
6619 {
6620 	ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component1");
6621 	int index = componentInfo->appliedFeatureList().indexOf(QMC2_MACHINELIST_INDEX);
6622 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
6623 	int embedIndex = componentInfo->appliedFeatureList().indexOf(QMC2_EMBED_INDEX);
6624 	if ( index > 0 && embedIndex >= 0 && embedIndex <= index )
6625 		if ( tabWidgetMachineList->indexOf(tabEmbeddedEmus) < 0 )
6626 			index--;
6627 #endif
6628 	int foreignIndex = componentInfo->appliedFeatureList().indexOf(QMC2_FOREIGN_INDEX);
6629 	if ( index > 0 && foreignIndex >= 0 && foreignIndex <= index )
6630 		if ( tabWidgetMachineList->indexOf(tabForeignEmulators) < 0 )
6631 			index--;
6632 	stackedWidgetView->setCurrentIndex(QMC2_VIEWVERSION_INDEX);
6633 	comboBoxViewSelect->blockSignals(true);
6634 	comboBoxViewSelect->setCurrentIndex(QMC2_VIEWVERSION_INDEX);
6635 	comboBoxViewSelect->blockSignals(false);
6636 	tabWidgetMachineList->setCurrentIndex(index);
6637 	tabWidgetMachineList->setTabIcon(index, QIcon(QString::fromUtf8(":/data/img/version.png")));
6638 	menuView->setIcon(QIcon(QString::fromUtf8(":/data/img/version.png")));
6639 	QTreeWidgetItem *item = treeWidgetVersionView->topLevelItem(0);
6640 	if ( item ) {
6641 		if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData ) {
6642 			treeWidgetVersionView->setVisible(false);
6643 			((AspectRatioLabel *)labelCreatingVersionView)->setLabelText(tr("Loading, please wait..."));
6644 			labelCreatingVersionView->setVisible(true);
6645 			QTimer::singleShot(0, qmc2MachineList, SLOT(createVersionView()));
6646 		} else
6647 			QTimer::singleShot(QMC2_RANK_UPDATE_DELAY, this, SLOT(treeWidgetVersionView_verticalScrollChanged()));
6648 	} else {
6649 		treeWidgetVersionView->setVisible(false);
6650 		((AspectRatioLabel *)labelCreatingVersionView)->setLabelText(tr("Loading, please wait..."));
6651 		labelCreatingVersionView->setVisible(true);
6652 		QTimer::singleShot(0, qmc2MachineList, SLOT(createVersionView()));
6653 	}
6654 	treeWidgetVersionView->setFocus();
6655 	stackedWidgetView->update();
6656 	qApp->processEvents();
6657 }
6658 
actionCustomView_triggered()6659 void MainWindow::actionCustomView_triggered()
6660 {
6661 	if ( MachineListViewer::attachedViews().isEmpty() )
6662 		return;
6663 	if ( attachedViewer() )
6664 		showAttachedView(attachedViewer()->name());
6665 	else
6666 		showAttachedView(MachineListViewer::attachedViews().first());
6667 }
6668 
eventFilter(QObject * object,QEvent * event)6669 bool MainEventFilter::eventFilter(QObject *object, QEvent *event)
6670 {
6671 	switch ( event->type() ) {
6672 		case QEvent::KeyPress:
6673 		case QEvent::KeyRelease: {
6674 			QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
6675 			if ( keyEvent->text() == QString("QMC2_EMULATED_KEY") ) {
6676 				QString emulatedSequence = QKeySequence(keyEvent->key() | keyEvent->modifiers()).toString();
6677 #ifdef QMC2_DEBUG
6678 				qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: emulated key event, key-sequence = '%1'").arg(emulatedSequence));
6679 #endif
6680 				QPair<QString, QAction *> actionPair = qmc2ShortcutHash[emulatedSequence];
6681 				if ( actionPair.second ) {
6682 					if ( event->type() == QEvent::KeyPress && actionPair.second->isEnabled() )
6683 						actionPair.second->trigger();
6684 					return true;
6685 				} else
6686 					return false;
6687 			}
6688 			int myKeySeq = 0;
6689 			if ( keyEvent->modifiers() & Qt::ShiftModifier )
6690 				myKeySeq += Qt::SHIFT;
6691 			if ( keyEvent->modifiers() & Qt::ControlModifier )
6692 				myKeySeq += Qt::CTRL;
6693 			if ( keyEvent->modifiers() & Qt::AltModifier )
6694 				myKeySeq += Qt::ALT;
6695 			if ( keyEvent->modifiers() & Qt::MetaModifier )
6696 				myKeySeq += Qt::META;
6697 			myKeySeq += keyEvent->key();
6698 			QString pressedKeySeq = QKeySequence(myKeySeq).toString();
6699 #ifdef QMC2_DEBUG
6700 			qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: current key-sequence = '%1'").arg(pressedKeySeq));
6701 #endif
6702 			QString matchedKeySeq = qmc2CustomShortcutHash.key(pressedKeySeq);
6703 			if ( !matchedKeySeq.isEmpty() ) {
6704 				if ( !qmc2MainWindow->menuBar()->isVisible() ) {
6705 					QPair<QString, QAction *> actionPair = qmc2ShortcutHash[qmc2CustomShortcutHash.key(pressedKeySeq)];
6706 					if ( actionPair.second )
6707 					{
6708 #ifdef QMC2_DEBUG
6709 						qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: '%1' pressed, emulating key event (due to no menu bar)").arg(pressedKeySeq));
6710 #endif
6711 						if ( actionPair.second->isEnabled() )
6712 							actionPair.second->trigger();
6713 						return true;
6714 					}
6715 				}
6716 				if ( matchedKeySeq != pressedKeySeq ) {
6717 #ifdef QMC2_DEBUG
6718 					qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: emulating key event for '%1'").arg(matchedKeySeq));
6719 #endif
6720 					// emulate a key event for the mapped key
6721 					int key = 0;
6722 					if ( qmc2QtKeyHash.contains(matchedKeySeq) )
6723 						key = qmc2QtKeyHash[matchedKeySeq][0] | qmc2QtKeyHash[matchedKeySeq][1] | qmc2QtKeyHash[matchedKeySeq][2] | qmc2QtKeyHash[matchedKeySeq][3];
6724 					else {
6725 						QKeySequence emulatedKeySequence(matchedKeySeq);
6726 						key = emulatedKeySequence[0] | emulatedKeySequence[1] | emulatedKeySequence[2] | emulatedKeySequence[3];
6727 					}
6728 
6729 					Qt::KeyboardModifiers mods = Qt::NoModifier;
6730 					if ( key & Qt::ShiftModifier ) {
6731 						key -= Qt::ShiftModifier;
6732 						mods |= Qt::ShiftModifier;
6733 					}
6734 					if ( key & Qt::ControlModifier ) {
6735 						key -= Qt::ControlModifier;
6736 						mods |= Qt::ControlModifier;
6737 					}
6738 					if ( key & Qt::AltModifier ) {
6739 						key -= Qt::AltModifier;
6740 						mods |= Qt::AltModifier;
6741 					}
6742 					if ( key & Qt::MetaModifier ) {
6743 						key -= Qt::MetaModifier;
6744 						mods |= Qt::MetaModifier;
6745 					}
6746 					QKeyEvent *emulatedKeyEvent = new QKeyEvent(event->type(), key, mods, QString("QMC2_EMULATED_KEY"));
6747 					qApp->postEvent(object, emulatedKeyEvent);
6748 					return true;
6749 				} else {
6750 #ifdef QMC2_DEBUG
6751 					qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: '%1' pressed, default key event processing").arg(pressedKeySeq));
6752 #endif
6753 					// default key event processing
6754 					return false;
6755 				}
6756 			}
6757 			QHash<QString, QString>::const_iterator it = qmc2CustomShortcutHash.find(pressedKeySeq);
6758 			if ( it != qmc2CustomShortcutHash.end() ) {
6759 				if ( !it.value().isEmpty() ) {
6760 #ifdef QMC2_DEBUG
6761 					qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: '%1' pressed, key event suppressed").arg(pressedKeySeq));
6762 #endif
6763 					return true;
6764 				} else {
6765 #ifdef QMC2_DEBUG
6766 					qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: '%1' pressed, default key event processing").arg(pressedKeySeq));
6767 #endif
6768 					return false;
6769 				}
6770 			}
6771 #ifdef QMC2_DEBUG
6772 			qmc2MainWindow->log(QMC2_LOG_FRONTEND, QString("DEBUG: '%1' pressed, default key event processing").arg(pressedKeySeq));
6773 #endif
6774 			return false;
6775 		}
6776 		default:
6777 			// default event processing
6778 			return QObject::eventFilter(object, event);
6779 	}
6780 }
6781 
eventFilter(QObject * obj,QEvent * event)6782 bool SearchBoxKeyEventFilter::eventFilter(QObject *obj, QEvent *event)
6783 {
6784 	if ( event->type() == QEvent::KeyPress ) {
6785 		QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
6786 		switch ( keyEvent->key() ) {
6787 			case Qt::Key_Up:
6788 			case Qt::Key_Down:
6789 				return true;
6790 				break;
6791 			default:
6792 				break;
6793 		}
6794 	}
6795 	return QObject::eventFilter(obj, event);
6796 }
6797 
6798 #if defined(QMC2_YOUTUBE_ENABLED)
loadYouTubeVideoInfoMap()6799 void MainWindow::loadYouTubeVideoInfoMap()
6800 {
6801 	if ( m_videoInfoMapLoaded )
6802 		return;
6803 	log(QMC2_LOG_FRONTEND, tr("loading YouTube video info cache"));
6804 	QDir youTubeCacheDir(qmc2Config->value(QMC2_FRONTEND_PREFIX + "YouTubeWidget/CacheDirectory").toString());
6805 	if ( youTubeCacheDir.exists() ) {
6806 #if defined(QMC2_SDLMAME)
6807 		QFile f(youTubeCacheDir.canonicalPath() + "/qmc2-sdlmame.yti");
6808 #elif defined(QMC2_MAME)
6809 		QFile f(youTubeCacheDir.canonicalPath() + "/qmc2-mame.yti");
6810 #else
6811 		QFile f(youTubeCacheDir.canonicalPath() + "/qmc2.yti");
6812 #endif
6813 		if ( f.open(QIODevice::ReadOnly | QIODevice::Text) ) {
6814 			QString oldFormat = progressBarMachineList->format();
6815 			int oldMinimum = progressBarMachineList->minimum();
6816 			int oldMaximum = progressBarMachineList->maximum();
6817 			int oldValue = progressBarMachineList->value();
6818 			if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
6819 				progressBarMachineList->setFormat(tr("YouTube index - %p%"));
6820 			else
6821 				progressBarMachineList->setFormat("%p%");
6822 			QFileInfo fi(f.fileName());
6823 			progressBarMachineList->setRange(0, fi.size());
6824 			progressBarMachineList->setValue(0);
6825 			qmc2YouTubeVideoInfoHash.clear();
6826 			QTextStream ts(&f);
6827 			quint64 viCounter = 0;
6828 			quint64 curLen = 0;
6829 			while ( !ts.atEnd() ) {
6830 				QString line = ts.readLine();
6831 #if defined(QMC2_OS_WIN)
6832 				curLen += line.length() + 2; // + 0x0d 0x0a
6833 #else
6834 				curLen += line.length() + 1; // + 0x0a
6835 #endif
6836 				if ( viCounter++ % QMC2_YOUTUBE_VIDEO_INFO_RSP == 0 )
6837 					progressBarMachineList->setValue(curLen);
6838 				if ( !line.startsWith('#') ) {
6839 					QStringList tokens(line.split('\t'));
6840 					if ( tokens.count() > 2 )
6841 						qmc2YouTubeVideoInfoHash.insert(tokens.at(0), YouTubeVideoInfo(tokens.at(2), tokens.at(1)));
6842 				}
6843 			}
6844 			progressBarMachineList->reset();
6845 			progressBarMachineList->setFormat(oldFormat);
6846 			progressBarMachineList->setRange(oldMinimum, oldMaximum);
6847 			progressBarMachineList->setValue(oldValue);
6848 		}
6849 	}
6850 	log(QMC2_LOG_FRONTEND, tr("done (loading YouTube video info cache)"));
6851 	log(QMC2_LOG_FRONTEND, tr("%n video info record(s) loaded", "", qmc2YouTubeVideoInfoHash.count()));
6852 	qmc2YouTubeVideoInfoHashChanged = false;
6853 	m_videoInfoMapLoaded = true;
6854 }
6855 #endif
6856 
loadMachineInfoDB()6857 void MainWindow::loadMachineInfoDB()
6858 {
6859 	QStringList pathList;
6860 	QStringList emulatorList;
6861 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMameHistoryDat").toBool() ) {
6862 		pathList << qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/MameHistoryDat").toString();
6863 		emulatorList << "MAME";
6864 	}
6865 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMessSysinfoDat").toBool() ) {
6866 		pathList << qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/MessSysinfoDat").toString();
6867 		if ( !pathList.last().toLower().endsWith("sysinfo.dat") )
6868 			emulatorList << "MAME";
6869 		else
6870 			emulatorList << "MESS";
6871 	}
6872 
6873 	if ( qmc2MachineList->datInfoDb()->machineInfoImportRequired(pathList) ) {
6874 		qmc2LoadingMachineInfoDB = true;
6875 		qmc2Options->toolButtonImportGameInfo->setEnabled(false);
6876 		qmc2Options->toolButtonImportMachineInfo->setEnabled(false);
6877 		qmc2MachineList->datInfoDb()->importMachineInfo(pathList, emulatorList);
6878 		qmc2Options->toolButtonImportGameInfo->setEnabled(true);
6879 		qmc2Options->toolButtonImportMachineInfo->setEnabled(true);
6880 		qmc2LoadingMachineInfoDB = false;
6881 	}
6882 }
6883 
loadEmuInfoDB()6884 void MainWindow::loadEmuInfoDB()
6885 {
6886 	QStringList pathList;
6887 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMameInfoDat").toBool() )
6888 		pathList << qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/MameInfoDat").toString();
6889 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/ProcessMessInfoDat").toBool() )
6890 		pathList << qmc2Config->value(QMC2_FRONTEND_PREFIX + "FilesAndDirectories/MessInfoDat").toString();
6891 
6892 	if ( qmc2MachineList->datInfoDb()->emuInfoImportRequired(pathList) ) {
6893 		qmc2LoadingEmuInfoDB = true;
6894 		qmc2Options->toolButtonImportMameInfo->setEnabled(false);
6895 		qmc2Options->toolButtonImportMessInfo->setEnabled(false);
6896 		qmc2MachineList->datInfoDb()->importEmuInfo(pathList);
6897 		qmc2Options->toolButtonImportMameInfo->setEnabled(true);
6898 		qmc2Options->toolButtonImportMessInfo->setEnabled(true);
6899 		qmc2LoadingEmuInfoDB = false;
6900 	}
6901 }
6902 
loadSoftwareInfoDB()6903 void MainWindow::loadSoftwareInfoDB()
6904 {
6905 	QStringList pathList(QStringList() << qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/SoftwareInfoDB").toString());
6906 	if ( qmc2MachineList->datInfoDb()->softwareInfoImportRequired(pathList) ) {
6907 		qmc2LoadingSoftwareInfoDB = true;
6908 		qmc2Options->toolButtonImportSoftwareInfo->setEnabled(false);
6909 		qmc2MachineList->datInfoDb()->importSoftwareInfo(pathList);
6910 		qmc2Options->toolButtonImportSoftwareInfo->setEnabled(true);
6911 		qmc2LoadingSoftwareInfoDB = false;
6912 	}
6913 }
6914 
6915 #if QMC2_USE_PHONON_API || QMC2_MULTIMEDIA_ENABLED
on_actionAudioPreviousTrack_triggered(bool)6916 void MainWindow::on_actionAudioPreviousTrack_triggered(bool /*checked*/)
6917 {
6918 	toolButtonAudioPreviousTrack->setDown(true);
6919 	QTimer::singleShot(QMC2_BUTTON_ANIMATION_TIMEOUT, this, SLOT(toolButtonAudioPreviousTrack_resetButton()));
6920 	audioFastForwarding = audioFastBackwarding = false;
6921 	audioSkippingTracks = true;
6922 
6923 	if ( listWidgetAudioPlaylist->count() > 0 ) {
6924 		QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
6925 		QListWidgetItem *ci = 0;
6926 		if ( sl.count() > 0 )
6927 			ci = sl[0];
6928 		if ( !ci )
6929 			ci = listWidgetAudioPlaylist->currentItem();
6930 		int row;
6931 		if ( ci )
6932 			row = listWidgetAudioPlaylist->currentRow() - 1;
6933 		else
6934 			row = listWidgetAudioPlaylist->count() - 1;
6935 		if ( row < 0 )
6936 			row = listWidgetAudioPlaylist->count() - 1;
6937 		listWidgetAudioPlaylist->clearSelection();
6938 		listWidgetAudioPlaylist->setCurrentRow(row);
6939 		ci = listWidgetAudioPlaylist->currentItem();
6940 		switch ( audioState ) {
6941 #if QMC2_MULTIMEDIA_ENABLED
6942 			case QMediaPlayer::PlayingState:
6943 #else
6944 			case Phonon::PlayingState:
6945 #endif
6946 				QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
6947 				break;
6948 
6949 			default:
6950 				QTimer::singleShot(0, this, SLOT(on_actionAudioStopTrack_triggered()));
6951 				break;
6952 		}
6953 	}
6954 }
6955 
toolButtonAudioPreviousTrack_resetButton()6956 void MainWindow::toolButtonAudioPreviousTrack_resetButton()
6957 {
6958 	toolButtonAudioPreviousTrack->setDown(false);
6959 }
6960 
on_actionAudioNextTrack_triggered(bool)6961 void MainWindow::on_actionAudioNextTrack_triggered(bool /*checked*/)
6962 {
6963 	toolButtonAudioNextTrack->setDown(true);
6964 	QTimer::singleShot(QMC2_BUTTON_ANIMATION_TIMEOUT, this, SLOT(toolButtonAudioNextTrack_resetButton()));
6965 	audioFastForwarding = audioFastBackwarding = false;
6966 	audioSkippingTracks = true;
6967 
6968 	if ( listWidgetAudioPlaylist->count() > 0 ) {
6969 		QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
6970 		QListWidgetItem *ci = 0;
6971 		if ( sl.count() > 0 )
6972 			ci = sl[0];
6973 		if ( !ci )
6974 			ci = listWidgetAudioPlaylist->currentItem();
6975 		int row;
6976 		if ( ci )
6977 			row = listWidgetAudioPlaylist->currentRow() + 1;
6978 		else
6979 			row = 0;
6980 		if ( row > listWidgetAudioPlaylist->count() - 1 )
6981 			row = 0;
6982 		listWidgetAudioPlaylist->clearSelection();
6983 		listWidgetAudioPlaylist->setCurrentRow(row);
6984 		ci = listWidgetAudioPlaylist->currentItem();
6985 		switch ( audioState ) {
6986 #if QMC2_MULTIMEDIA_ENABLED
6987 			case QMediaPlayer::PlayingState:
6988 #else
6989 			case Phonon::PlayingState:
6990 #endif
6991 				QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
6992 				break;
6993 
6994 			default:
6995 				QTimer::singleShot(0, this, SLOT(on_actionAudioStopTrack_triggered()));
6996 				break;
6997 		}
6998 	}
6999 }
7000 
toolButtonAudioNextTrack_resetButton()7001 void MainWindow::toolButtonAudioNextTrack_resetButton()
7002 {
7003 	toolButtonAudioNextTrack->setDown(false);
7004 }
7005 
on_actionAudioFastBackward_triggered(bool checked)7006 void MainWindow::on_actionAudioFastBackward_triggered(bool checked)
7007 {
7008 	toolButtonAudioFastBackward->setDown(true);
7009 	QTimer::singleShot(QMC2_BUTTON_ANIMATION_TIMEOUT, this, SLOT(toolButtonAudioFastBackward_resetButton()));
7010 
7011 	on_toolButtonAudioFastBackward_clicked(checked);
7012 }
7013 
on_toolButtonAudioFastBackward_clicked(bool)7014 void MainWindow::on_toolButtonAudioFastBackward_clicked(bool /*checked*/)
7015 {
7016 #if QMC2_MULTIMEDIA_ENABLED
7017 	qint64 newTime = mediaPlayer->position();
7018 #else
7019 	qint64 newTime = phononAudioPlayer->currentTime();
7020 #endif
7021 	if ( newTime > 0 ) {
7022 		newTime -= QMC2_AUDIOPLAYER_SEEK_OFFSET;
7023 		audioFastBackwarding = true;
7024 #if QMC2_MULTIMEDIA_ENABLED
7025 		mediaPlayer->setPosition(newTime);
7026 #else
7027 		phononAudioPlayer->seek(newTime);
7028 #endif
7029 		audioTick(newTime);
7030 	}
7031 }
7032 
toolButtonAudioFastBackward_resetButton()7033 void MainWindow::toolButtonAudioFastBackward_resetButton()
7034 {
7035 	toolButtonAudioFastBackward->setDown(false);
7036 	audioFastForwarding = false;
7037 }
7038 
on_actionAudioFastForward_triggered(bool checked)7039 void MainWindow::on_actionAudioFastForward_triggered(bool checked)
7040 {
7041 	toolButtonAudioFastForward->setDown(true);
7042 	QTimer::singleShot(QMC2_BUTTON_ANIMATION_TIMEOUT, this, SLOT(toolButtonAudioFastForward_resetButton()));
7043 
7044 	on_toolButtonAudioFastForward_clicked(checked);
7045 }
7046 
on_toolButtonAudioFastForward_clicked(bool)7047 void MainWindow::on_toolButtonAudioFastForward_clicked(bool /*checked*/)
7048 {
7049 #if QMC2_MULTIMEDIA_ENABLED
7050 	qint64 newTime = mediaPlayer->position();
7051 #else
7052 	qint64 newTime = phononAudioPlayer->currentTime();
7053 #endif
7054 	if ( newTime > 0 ) {
7055 		newTime += QMC2_AUDIOPLAYER_SEEK_OFFSET;
7056 		audioFastForwarding = true;
7057 #if QMC2_MULTIMEDIA_ENABLED
7058 		mediaPlayer->setPosition(newTime);
7059 #else
7060 		phononAudioPlayer->seek(newTime);
7061 #endif
7062 		audioTick(newTime);
7063 	}
7064 }
7065 
toolButtonAudioFastForward_resetButton()7066 void MainWindow::toolButtonAudioFastForward_resetButton()
7067 {
7068 	toolButtonAudioFastForward->setDown(false);
7069 	audioFastForwarding = false;
7070 }
7071 
on_actionAudioStopTrack_triggered(bool)7072 void MainWindow::on_actionAudioStopTrack_triggered(bool /*checked*/)
7073 {
7074 	actionAudioStopTrack->setChecked(true);
7075 	actionAudioPauseTrack->setChecked(false);
7076 	actionAudioPlayTrack->setChecked(false);
7077 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
7078 #if QMC2_MULTIMEDIA_ENABLED
7079 	mediaPlayer->stop();
7080 	audioState = QMediaPlayer::StoppedState;
7081 #else
7082 	phononAudioPlayer->stop();
7083 	audioState = Phonon::StoppedState;
7084 #endif
7085 	progressBarAudioProgress->setFormat(QString());
7086 	progressBarAudioProgress->setRange(0, 100);
7087 	progressBarAudioProgress->setValue(0);
7088 	progressBarAudioProgress->reset();
7089 }
7090 
on_actionAudioPauseTrack_triggered(bool)7091 void MainWindow::on_actionAudioPauseTrack_triggered(bool /*checked*/)
7092 {
7093 	actionAudioPauseTrack->setChecked(true);
7094 	actionAudioStopTrack->setChecked(false);
7095 	actionAudioPlayTrack->setChecked(false);
7096 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
7097 #if QMC2_MULTIMEDIA_ENABLED
7098 	if ( checkBoxAudioFade->isChecked() && audioState == QMediaPlayer::PlayingState )
7099 		audioFade(QMC2_AUDIOPLAYER_FADER_PAUSE);
7100 	else
7101 		mediaPlayer->pause();
7102 	audioState = QMediaPlayer::PausedState;
7103 #else
7104 	if ( checkBoxAudioFade->isChecked() && audioState == Phonon::PlayingState )
7105 		audioFade(QMC2_AUDIOPLAYER_FADER_PAUSE);
7106 	else
7107 		phononAudioPlayer->pause();
7108 	audioState = Phonon::PausedState;
7109 #endif
7110 }
7111 
on_actionAudioPlayTrack_triggered(bool)7112 void MainWindow::on_actionAudioPlayTrack_triggered(bool /*checked*/)
7113 {
7114 #if QMC2_MULTIMEDIA_ENABLED
7115 	// if this is a URL media source, force a reconnect to the stream...
7116 	if ( mediaPlayer->currentMedia().canonicalUrl().scheme() != "file" )
7117 		mediaPlayer->setMedia(mediaPlayer->currentMedia().canonicalUrl());
7118 
7119 	static QString audioPlayerCurrentTrack;
7120 	audioFastForwarding = audioFastBackwarding = false;
7121 	if ( audioState == QMediaPlayer::PausedState ) {
7122 		if ( qmc2ProcessManager->sentPlaySignal && qmc2ProcessManager->procMap.count() > 0 ) {
7123 			qmc2ProcessManager->musicWasPlaying = true;
7124 		} else if ( checkBoxAudioFade->isChecked() ) {
7125 			audioFade(QMC2_AUDIOPLAYER_FADER_PLAY);
7126 		} else {
7127 			mediaPlayer->play();
7128 			actionAudioPlayTrack->setChecked(true);
7129 			actionAudioStopTrack->setChecked(false);
7130 			actionAudioPauseTrack->setChecked(false);
7131 		}
7132 		qmc2ProcessManager->sentPlaySignal = false;
7133 		audioState = QMediaPlayer::PlayingState;
7134 	} else if ( listWidgetAudioPlaylist->count() > 0 ) {
7135 		QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
7136 		QListWidgetItem *ci = 0;
7137 		if ( sl.count() > 0 )
7138 			ci = sl[0];
7139 		if ( !ci ) {
7140 			if ( !qmc2AudioLastIndividualTrack.isEmpty() ) {
7141 				audioScrollToCurrentItem();
7142 				ci = listWidgetAudioPlaylist->currentItem();
7143 			}
7144 			if ( !ci ) {
7145 				listWidgetAudioPlaylist->setCurrentRow(0);
7146 				ci = listWidgetAudioPlaylist->currentItem();
7147 			}
7148 		}
7149 		if ( ci->text() != audioPlayerCurrentTrack ) {
7150 			progressBarAudioProgress->reset();
7151 			audioPlayerCurrentTrack = ci->text();
7152 			listWidgetAudioPlaylist->scrollToItem(ci, qmc2CursorPositioningMode);
7153 			if ( QFileInfo(audioPlayerCurrentTrack).exists() )
7154 				mediaPlayer->setMedia(QUrl::fromLocalFile(audioPlayerCurrentTrack));
7155 			else
7156 				mediaPlayer->setMedia(QUrl::fromUserInput(audioPlayerCurrentTrack));
7157 		}
7158 		mediaPlayer->play();
7159 		actionAudioPlayTrack->setChecked(true);
7160 		actionAudioStopTrack->setChecked(false);
7161 		actionAudioPauseTrack->setChecked(false);
7162 		audioState = QMediaPlayer::PlayingState;
7163 	} else
7164 		on_actionAudioStopTrack_triggered(true);
7165 #else
7166 	// if this is a URL media source, force a reconnect to the stream...
7167 	if ( phononAudioPlayer->currentSource().type() == Phonon::MediaSource::Url )
7168 		phononAudioPlayer->setCurrentSource(phononAudioPlayer->currentSource().url());
7169 
7170 	static QString audioPlayerCurrentTrack;
7171 	audioFastForwarding = audioFastBackwarding = false;
7172 	if ( audioState == Phonon::PausedState ) {
7173 		if ( qmc2ProcessManager->sentPlaySignal && qmc2ProcessManager->procMap.count() > 0 ) {
7174 			qmc2ProcessManager->musicWasPlaying = true;
7175 		} else if ( checkBoxAudioFade->isChecked() ) {
7176 			audioFade(QMC2_AUDIOPLAYER_FADER_PLAY);
7177 		} else {
7178 			phononAudioPlayer->play();
7179 			actionAudioPlayTrack->setChecked(true);
7180 			actionAudioStopTrack->setChecked(false);
7181 			actionAudioPauseTrack->setChecked(false);
7182 		}
7183 		qmc2ProcessManager->sentPlaySignal = false;
7184 		audioState = Phonon::PlayingState;
7185 	} else if ( listWidgetAudioPlaylist->count() > 0 ) {
7186 		QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
7187 		QListWidgetItem *ci = 0;
7188 		if ( sl.count() > 0 )
7189 			ci = sl[0];
7190 		if ( !ci ) {
7191 			if ( !qmc2AudioLastIndividualTrack.isEmpty() ) {
7192 				audioScrollToCurrentItem();
7193 				ci = listWidgetAudioPlaylist->currentItem();
7194 			}
7195 			if ( !ci ) {
7196 				listWidgetAudioPlaylist->setCurrentRow(0);
7197 				ci = listWidgetAudioPlaylist->currentItem();
7198 			}
7199 		}
7200 		if ( ci->text() != audioPlayerCurrentTrack ) {
7201 			progressBarAudioProgress->reset();
7202 			audioPlayerCurrentTrack = ci->text();
7203 			listWidgetAudioPlaylist->scrollToItem(ci, qmc2CursorPositioningMode);
7204 			phononAudioPlayer->setCurrentSource(Phonon::MediaSource(audioPlayerCurrentTrack));
7205 		}
7206 		phononAudioPlayer->play();
7207 		actionAudioPlayTrack->setChecked(true);
7208 		actionAudioStopTrack->setChecked(false);
7209 		actionAudioPauseTrack->setChecked(false);
7210 		audioState = Phonon::PlayingState;
7211 	} else
7212 		on_actionAudioStopTrack_triggered(true);
7213 #endif
7214 }
7215 
on_toolButtonAudioAddTracks_clicked()7216 void MainWindow::on_toolButtonAudioAddTracks_clicked()
7217 {
7218 	QStringList sl(QFileDialog::getOpenFileNames(this, tr("Select one or more audio files"), QString(), tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog));
7219 	if ( sl.count() > 0 )
7220 		listWidgetAudioPlaylist->addItems(sl);
7221 }
7222 
on_toolButtonAudioAddURL_clicked()7223 void MainWindow::on_toolButtonAudioAddURL_clicked()
7224 {
7225 	bool ok;
7226 	QString streamUrl = QInputDialog::getText(this, tr("Add URL"), tr("Enter valid MP3 stream URL:"), QLineEdit::Normal, "", &ok);
7227 	if ( ok && !streamUrl.isEmpty() )
7228 		listWidgetAudioPlaylist->addItem(streamUrl);
7229 }
7230 
on_toolButtonAudioSetupEffects_clicked()7231 void MainWindow::on_toolButtonAudioSetupEffects_clicked()
7232 {
7233 #if !QMC2_MULTIMEDIA_ENABLED
7234 	static bool audioSetupEffectsFirstCall = true;
7235 
7236 	if ( !qmc2AudioEffectDialog )
7237 		qmc2AudioEffectDialog = new AudioEffectDialog(this);
7238 
7239 	if ( !audioSetupEffectsFirstCall ) {
7240 		qmc2AudioEffectDialog->show();
7241 		qmc2AudioEffectDialog->raise();
7242 	}
7243 
7244 	audioSetupEffectsFirstCall = false;
7245 #endif
7246 }
7247 
on_toolButtonAudioRemoveTracks_clicked()7248 void MainWindow::on_toolButtonAudioRemoveTracks_clicked()
7249 {
7250 	QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
7251 	foreach (QListWidgetItem *item, sl) {
7252 		item = listWidgetAudioPlaylist->takeItem(listWidgetAudioPlaylist->row(item));
7253 		delete item;
7254 	}
7255 }
7256 
on_listWidgetAudioPlaylist_itemSelectionChanged()7257 void MainWindow::on_listWidgetAudioPlaylist_itemSelectionChanged()
7258 {
7259 	QList<QListWidgetItem *> sl = listWidgetAudioPlaylist->selectedItems();
7260 	if ( sl.count() > 0 )
7261 		toolButtonAudioRemoveTracks->setEnabled(true);
7262 	else
7263 		toolButtonAudioRemoveTracks->setEnabled(false);
7264 
7265 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
7266 
7267 	if ( sl.count() == 1 && !audioSkippingTracks && !qmc2EarlyStartup ) {
7268 		QListWidgetItem *ci = listWidgetAudioPlaylist->currentItem();
7269 		switch ( audioState ) {
7270 #if QMC2_MULTIMEDIA_ENABLED
7271 			case QMediaPlayer::PlayingState:
7272 #else
7273 			case Phonon::PlayingState:
7274 #endif
7275 				if ( qmc2AudioLastIndividualTrack != sl[0]->text() && ci == sl[0] )
7276 					QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
7277 				break;
7278 
7279 			default:
7280 				QTimer::singleShot(0, this, SLOT(on_actionAudioStopTrack_triggered()));
7281 				break;
7282 		}
7283 		if ( ci ) {
7284 			if ( ci->text() == sl[0]->text() )
7285 				qmc2AudioLastIndividualTrack = sl[0]->text();
7286 		}
7287 	} else if ( sl.count() <= 0 )
7288 		QTimer::singleShot(0, this, SLOT(audioScrollToCurrentItem()));
7289 }
7290 
audioScrollToCurrentItem()7291 void MainWindow::audioScrollToCurrentItem()
7292 {
7293 	if ( !qmc2AudioLastIndividualTrack.isEmpty() ) {
7294 		QList<QListWidgetItem *> itemList = listWidgetAudioPlaylist->findItems(qmc2AudioLastIndividualTrack, Qt::MatchExactly);
7295 		if ( itemList.count() > 0 ) {
7296 			QListWidgetItem *item = itemList[0];
7297 			listWidgetAudioPlaylist->scrollToItem(item, QAbstractItemView::PositionAtCenter);
7298 			listWidgetAudioPlaylist->setCurrentItem(item, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent);
7299 		}
7300 	}
7301 }
7302 
on_actionAudioRaiseVolume_triggered(bool)7303 void MainWindow::on_actionAudioRaiseVolume_triggered(bool /*checked*/)
7304 {
7305 	dialAudioVolume->setValue(dialAudioVolume->value() + dialAudioVolume->pageStep());
7306 }
7307 
on_actionAudioLowerVolume_triggered(bool)7308 void MainWindow::on_actionAudioLowerVolume_triggered(bool /*checked*/)
7309 {
7310 	dialAudioVolume->setValue(dialAudioVolume->value() - dialAudioVolume->pageStep());
7311 }
7312 
on_dialAudioVolume_valueChanged(int value)7313 void MainWindow::on_dialAudioVolume_valueChanged(int value)
7314 {
7315 #if QMC2_MULTIMEDIA_ENABLED
7316 	mediaPlayer->setVolume(value);
7317 #else
7318 	phononAudioOutput->setVolume((qreal)value/100.0);
7319 #endif
7320 }
7321 
audioFinished()7322 void MainWindow::audioFinished()
7323 {
7324 	static QStringList shuffleSelectionList;
7325 
7326 	if ( audioFastBackwarding )
7327 		QTimer::singleShot(0, this, SLOT(on_actionAudioPreviousTrack_triggered()));
7328 	else if ( audioFastForwarding )
7329 		QTimer::singleShot(0, this, SLOT(on_actionAudioNextTrack_triggered()));
7330 	else if ( checkBoxAudioShuffle->isChecked() ) {
7331 		if ( shuffleSelectionList.count() >= listWidgetAudioPlaylist->count() )
7332 			shuffleSelectionList.clear();
7333 		int newTrackIndex = qrand() % listWidgetAudioPlaylist->count();
7334 		while ( shuffleSelectionList.contains(listWidgetAudioPlaylist->item(newTrackIndex)->text()) ) {
7335 			qApp->processEvents();
7336 			newTrackIndex = qrand() % listWidgetAudioPlaylist->count();
7337 		}
7338 		shuffleSelectionList << listWidgetAudioPlaylist->item(newTrackIndex)->text();
7339 		listWidgetAudioPlaylist->setCurrentRow(newTrackIndex);
7340 		QTimer::singleShot(0, this, SLOT(on_actionAudioPlayTrack_triggered()));
7341 	} else
7342 		QTimer::singleShot(0, this, SLOT(on_actionAudioNextTrack_triggered()));
7343 }
7344 
7345 #if QMC2_MULTIMEDIA_ENABLED
audioStateChanged(QMediaPlayer::MediaStatus mediaStatus)7346 void MainWindow::audioStateChanged(QMediaPlayer::MediaStatus mediaStatus)
7347 {
7348 	if ( mediaStatus == QMediaPlayer::EndOfMedia )
7349 		audioFinished();
7350 }
7351 #endif
7352 
audioTick(qint64 newTime)7353 void MainWindow::audioTick(qint64 newTime)
7354 {
7355 #if QMC2_MULTIMEDIA_ENABLED
7356 	if ( audioState != QMediaPlayer::StoppedState ) {
7357 		progressBarAudioProgress->setFormat(tr("%vs (%ms total)"));
7358 		progressBarAudioProgress->setValue(newTime/1000);
7359 	}
7360 #else
7361 	if ( audioState != Phonon::StoppedState ) {
7362 		progressBarAudioProgress->setFormat(tr("%vs (%ms total)"));
7363 		progressBarAudioProgress->setValue(newTime/1000);
7364 	}
7365 #endif
7366 }
7367 
audioTotalTimeChanged(qint64 newTotalTime)7368 void MainWindow::audioTotalTimeChanged(qint64 newTotalTime)
7369 {
7370 	if ( newTotalTime > 0 ) {
7371 		progressBarAudioProgress->setFormat(tr("%vs (%ms total)"));
7372 		progressBarAudioProgress->setRange(0, newTotalTime/1000);
7373 #if QMC2_MULTIMEDIA_ENABLED
7374 		progressBarAudioProgress->setValue(mediaPlayer->position()/1000);
7375 #else
7376 		progressBarAudioProgress->setValue(phononAudioPlayer->currentTime()/1000);
7377 #endif
7378 	} else {
7379 		progressBarAudioProgress->setRange(0, 100);
7380 		progressBarAudioProgress->setValue(0);
7381 		progressBarAudioProgress->reset();
7382 	}
7383 }
7384 
audioFade(int faderFunction)7385 void MainWindow::audioFade(int faderFunction)
7386 {
7387 	int currentVolume = dialAudioVolume->value();
7388 	int updateCounter;
7389 	double vol;
7390 	double volStep = (double)currentVolume / (double)QMC2_AUDIOPLAYER_FADER_TIMEOUT;
7391 	audioFastForwarding = audioFastBackwarding = audioSkippingTracks = false;
7392 	switch ( faderFunction ) {
7393 		case QMC2_AUDIOPLAYER_FADER_PAUSE:
7394 			actionAudioPauseTrack->setChecked(true);
7395 			actionAudioStopTrack->setChecked(false);
7396 			actionAudioPlayTrack->setChecked(false);
7397 			actionAudioPauseTrack->setEnabled(false);
7398 			toolButtonAudioPauseTrack->setEnabled(false);
7399 			actionAudioPlayTrack->setEnabled(false);
7400 			toolButtonAudioPlayTrack->setEnabled(false);
7401 			actionAudioStopTrack->setEnabled(false);
7402 			toolButtonAudioStopTrack->setEnabled(false);
7403 			updateCounter = 0;
7404 			for (vol = currentVolume; vol > 0.0; vol -= volStep) {
7405 				updateCounter++;
7406 				dialAudioVolume->setValue((int)vol);
7407 				if ( updateCounter % 10 == 0 )
7408 					qApp->processEvents();
7409 				QTest::qSleep(1);
7410 			}
7411 #if QMC2_MULTIMEDIA_ENABLED
7412 			mediaPlayer->pause();
7413 			audioState = QMediaPlayer::PausedState;
7414 #else
7415 			phononAudioPlayer->pause();
7416 			audioState = Phonon::PausedState;
7417 #endif
7418 			qApp->processEvents();
7419 			actionAudioPauseTrack->setEnabled(true);
7420 			toolButtonAudioPauseTrack->setEnabled(true);
7421 			actionAudioPlayTrack->setEnabled(true);
7422 			toolButtonAudioPlayTrack->setEnabled(true);
7423 			actionAudioStopTrack->setEnabled(true);
7424 			toolButtonAudioStopTrack->setEnabled(true);
7425 			break;
7426 
7427 		case QMC2_AUDIOPLAYER_FADER_PLAY:
7428 			dialAudioVolume->setValue(0);
7429 			actionAudioPauseTrack->setChecked(false);
7430 			actionAudioStopTrack->setChecked(false);
7431 			actionAudioPlayTrack->setChecked(true);
7432 			actionAudioPauseTrack->setEnabled(false);
7433 			toolButtonAudioPauseTrack->setEnabled(false);
7434 			actionAudioPlayTrack->setEnabled(false);
7435 			toolButtonAudioPlayTrack->setEnabled(false);
7436 			actionAudioStopTrack->setEnabled(false);
7437 			toolButtonAudioStopTrack->setEnabled(false);
7438 			qApp->processEvents();
7439 #if QMC2_MULTIMEDIA_ENABLED
7440 			mediaPlayer->play();
7441 			audioState = QMediaPlayer::PlayingState;
7442 #else
7443 			phononAudioPlayer->play();
7444 			audioState = Phonon::PlayingState;
7445 #endif
7446 			updateCounter = 0;
7447 			for (vol = 0; vol <= currentVolume; vol += volStep) {
7448 				updateCounter++;
7449 				dialAudioVolume->setValue((int)vol);
7450 				if ( updateCounter % 10 == 0 )
7451 					qApp->processEvents();
7452 				QTest::qSleep(1);
7453 			}
7454 			qApp->processEvents();
7455 			actionAudioPauseTrack->setEnabled(true);
7456 			toolButtonAudioPauseTrack->setEnabled(true);
7457 			actionAudioPlayTrack->setEnabled(true);
7458 			toolButtonAudioPlayTrack->setEnabled(true);
7459 			actionAudioStopTrack->setEnabled(true);
7460 			toolButtonAudioStopTrack->setEnabled(true);
7461 			break;
7462 	}
7463 	dialAudioVolume->setValue(currentVolume);
7464 }
7465 
audioMetaDataChanged()7466 void MainWindow::audioMetaDataChanged()
7467 {
7468 	static QString lastTrackInfo;
7469 #if QMC2_MULTIMEDIA_ENABLED
7470 	QString titleMetaData(mediaPlayer->metaData(QMediaMetaData::Title).toString());
7471 	QString artistMetaData(mediaPlayer->metaData(QMediaMetaData::ContributingArtist).toStringList().join(" / "));
7472 	QString albumMetaData(mediaPlayer->metaData(QMediaMetaData::AlbumTitle).toString());
7473 	QString genreMetaData(mediaPlayer->metaData(QMediaMetaData::Genre).toString());
7474 #else
7475 	QString titleMetaData(phononAudioPlayer->metaData(Phonon::TitleMetaData).join(", "));
7476 	QString artistMetaData(phononAudioPlayer->metaData(Phonon::ArtistMetaData).join(", "));
7477 	QString albumMetaData(phononAudioPlayer->metaData(Phonon::AlbumMetaData).join(", "));
7478 	QString genreMetaData(phononAudioPlayer->metaData(Phonon::GenreMetaData).join(", "));
7479 #endif
7480 
7481 	if ( titleMetaData.isEmpty() && artistMetaData.isEmpty() && albumMetaData.isEmpty() && genreMetaData.isEmpty() )
7482 		return;
7483 	QString trackInfo = tr("audio player: track info: title = '%1', artist = '%2', album = '%3', genre = '%4'").arg(titleMetaData).arg(artistMetaData).arg(albumMetaData).arg(genreMetaData);
7484 	if ( trackInfo != lastTrackInfo ) {
7485 		log(QMC2_LOG_FRONTEND, trackInfo);
7486 		lastTrackInfo = trackInfo;
7487 	}
7488 }
7489 
audioBufferStatus(int percentFilled)7490 void MainWindow::audioBufferStatus(int percentFilled)
7491 {
7492 	progressBarAudioProgress->setRange(0, 100);
7493 	progressBarAudioProgress->setFormat(tr("Buffering %p%"));
7494 	progressBarAudioProgress->setValue(percentFilled);
7495 	if ( percentFilled >= 100 ) {
7496 #if QMC2_MULTIMEDIA_ENABLED
7497 		if ( audioState == QMediaPlayer::StoppedState )
7498 			progressBarAudioProgress->setRange(0, 100);
7499 		else
7500 			progressBarAudioProgress->setRange(0, 0);
7501 #else
7502 		if ( audioState == Phonon::StoppedState )
7503 			progressBarAudioProgress->setRange(0, 100);
7504 		else
7505 			progressBarAudioProgress->setRange(0, 0);
7506 #endif
7507 		progressBarAudioProgress->reset();
7508 	}
7509 }
7510 #else
on_actionAudioPreviousTrack_triggered(bool)7511 void MainWindow::on_actionAudioPreviousTrack_triggered(bool) {}
toolButtonAudioPreviousTrack_resetButton()7512 void MainWindow::toolButtonAudioPreviousTrack_resetButton() {}
on_actionAudioNextTrack_triggered(bool)7513 void MainWindow::on_actionAudioNextTrack_triggered(bool) {}
toolButtonAudioNextTrack_resetButton()7514 void MainWindow::toolButtonAudioNextTrack_resetButton() {}
on_actionAudioFastBackward_triggered(bool)7515 void MainWindow::on_actionAudioFastBackward_triggered(bool) {}
on_toolButtonAudioFastBackward_clicked(bool)7516 void MainWindow::on_toolButtonAudioFastBackward_clicked(bool) {}
toolButtonAudioFastBackward_resetButton()7517 void MainWindow::toolButtonAudioFastBackward_resetButton() {}
on_actionAudioFastForward_triggered(bool)7518 void MainWindow::on_actionAudioFastForward_triggered(bool) {}
on_toolButtonAudioFastForward_clicked(bool)7519 void MainWindow::on_toolButtonAudioFastForward_clicked(bool) {}
toolButtonAudioFastForward_resetButton()7520 void MainWindow::toolButtonAudioFastForward_resetButton() {}
on_actionAudioStopTrack_triggered(bool)7521 void MainWindow::on_actionAudioStopTrack_triggered(bool) {}
on_actionAudioPauseTrack_triggered(bool)7522 void MainWindow::on_actionAudioPauseTrack_triggered(bool) {}
on_actionAudioPlayTrack_triggered(bool)7523 void MainWindow::on_actionAudioPlayTrack_triggered(bool) {}
on_toolButtonAudioAddTracks_clicked()7524 void MainWindow::on_toolButtonAudioAddTracks_clicked() {}
on_toolButtonAudioAddURL_clicked()7525 void MainWindow::on_toolButtonAudioAddURL_clicked() {}
on_toolButtonAudioRemoveTracks_clicked()7526 void MainWindow::on_toolButtonAudioRemoveTracks_clicked() {}
on_toolButtonAudioSetupEffects_clicked()7527 void MainWindow::on_toolButtonAudioSetupEffects_clicked() {}
on_listWidgetAudioPlaylist_itemSelectionChanged()7528 void MainWindow::on_listWidgetAudioPlaylist_itemSelectionChanged() {}
on_dialAudioVolume_valueChanged(int)7529 void MainWindow::on_dialAudioVolume_valueChanged(int) {}
on_actionAudioRaiseVolume_triggered(bool)7530 void MainWindow::on_actionAudioRaiseVolume_triggered(bool) {}
on_actionAudioLowerVolume_triggered(bool)7531 void MainWindow::on_actionAudioLowerVolume_triggered(bool) {}
audioFinished()7532 void MainWindow::audioFinished() {}
audioTick(qint64)7533 void MainWindow::audioTick(qint64) {}
audioTotalTimeChanged(qint64)7534 void MainWindow::audioTotalTimeChanged(qint64) {}
audioFade(int)7535 void MainWindow::audioFade(int) {}
audioMetaDataChanged()7536 void MainWindow::audioMetaDataChanged() {}
audioBufferStatus(int)7537 void MainWindow::audioBufferStatus(int) {}
audioScrollToCurrentItem()7538 void MainWindow::audioScrollToCurrentItem() {}
7539 #if QMC2_MULTIMEDIA_ENABLED
audioStateChanged(QMediaPlayer::MediaStatus)7540 void MainWindow::audioStateChanged(QMediaPlayer::MediaStatus) {}
7541 #endif
7542 #endif
7543 
on_checkBoxRemoveFinishedDownloads_stateChanged(int)7544 void MainWindow::on_checkBoxRemoveFinishedDownloads_stateChanged(int /*state*/)
7545 {
7546 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Downloads/RemoveFinished", checkBoxRemoveFinishedDownloads->isChecked());
7547 }
7548 
processOutputNotifier(int emuId,const QString & name,const QString & value)7549 void MainWindow::processOutputNotifier(int emuId, const QString &name, const QString &value)
7550 {
7551 	if ( qmc2CleaningUp )
7552 		return;
7553 
7554 	QList<QTreeWidgetItem *> il = treeWidgetEmulators->findItems(QString::number(emuId), Qt::MatchExactly, QMC2_EMUCONTROL_COLUMN_ID);
7555 	if ( il.count() > 0 ) {
7556 		if ( name == "pause" ) {
7557 #if defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000
7558 			Embedder *embedder = 0;
7559 			int embedderIndex = -1;
7560 			for (int j = 0; j < tabWidgetEmbeddedEmulators->count() && embedder == 0; j++) {
7561 				if ( tabWidgetEmbeddedEmulators->tabText(j).startsWith(QString("#%1 - ").arg(emuId)) ) {
7562 					embedder = (Embedder *)tabWidgetEmbeddedEmulators->widget(j);
7563 					embedderIndex = j;
7564 				}
7565 			}
7566 			if ( value == "0" ) {
7567 				il.first()->setText(QMC2_EMUCONTROL_COLUMN_STATUS, tr("running"));
7568 				if ( embedder ) {
7569 					embedder->isPaused = false;
7570 					tabWidgetEmbeddedEmulators->setTabIcon(embedderIndex, embedder->iconRunning);
7571 				}
7572 			} else {
7573 				il.first()->setText(QMC2_EMUCONTROL_COLUMN_STATUS, tr("paused"));
7574 				if ( embedder ) {
7575 					embedder->isPaused = true;
7576 					tabWidgetEmbeddedEmulators->setTabIcon(embedderIndex, embedder->iconPaused);
7577 				}
7578 			}
7579 #else
7580 			if ( value == "0" )
7581 				il.first()->setText(QMC2_EMUCONTROL_COLUMN_STATUS, tr("running"));
7582 			else
7583 				il.first()->setText(QMC2_EMUCONTROL_COLUMN_STATUS, tr("paused"));
7584 #endif
7585 		} else if ( name == "led0" ) {
7586 			if ( value == "0" )
7587 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED0, QIcon(QString::fromUtf8(":/data/img/led_off.png")));
7588 			else
7589 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED0, QIcon(QString::fromUtf8(":/data/img/led_on.png")));
7590 		} else if ( name == "led1" ) {
7591 			if ( value == "0" )
7592 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED1, QIcon(QString::fromUtf8(":/data/img/led_off.png")));
7593 			else
7594 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED1, QIcon(QString::fromUtf8(":/data/img/led_on.png")));
7595 		} else if ( name == "led2" ) {
7596 			if ( value == "0" )
7597 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED2, QIcon(QString::fromUtf8(":/data/img/led_off.png")));
7598 			else
7599 				il.first()->setIcon(QMC2_EMUCONTROL_COLUMN_LED2, QIcon(QString::fromUtf8(":/data/img/led_on.png")));
7600 		} else {
7601 			// add or refresh dynamic output notifiers
7602 			QTreeWidgetItem *itemFound = 0;
7603 			for (int i = 0; i < il.first()->childCount() && itemFound == 0; i++) {
7604 				QTreeWidgetItem *item = il.first()->child(i);
7605 				if ( item->text(QMC2_EMUCONTROL_COLUMN_MACHINE) == name )
7606 					itemFound = item;
7607 			}
7608 			if ( itemFound != 0 )
7609 				itemFound->setText(QMC2_EMUCONTROL_COLUMN_STATUS, value);
7610 			else {
7611 				itemFound = new QTreeWidgetItem(il[0]);
7612 				itemFound->setText(QMC2_EMUCONTROL_COLUMN_MACHINE, name);
7613 				itemFound->setText(QMC2_EMUCONTROL_COLUMN_STATUS, value);
7614 				if ( il.first()->childCount() == 1 ) {
7615 					// this is a workaround for a minor Qt bug: the root decoration
7616 					// isn't updated correctly on the first child item insertion
7617 					treeWidgetEmulators->setRootIsDecorated(false);
7618 					treeWidgetEmulators->setRootIsDecorated(true);
7619 				}
7620 			}
7621 		}
7622 		treeWidgetEmulators->update();
7623 	}
7624 }
7625 
treeWidgetMachineList_headerSectionClicked(int logicalIndex)7626 void MainWindow::treeWidgetMachineList_headerSectionClicked(int logicalIndex)
7627 {
7628 	qmc2MainWindow->treeWidgetMachineList->header()->setSortIndicatorShown(false);
7629 	qmc2MainWindow->treeWidgetHierarchy->header()->setSortIndicatorShown(false);
7630 	qmc2MainWindow->treeWidgetCategoryView->header()->setSortIndicatorShown(false);
7631 	qmc2MainWindow->treeWidgetVersionView->header()->setSortIndicatorShown(false);
7632 
7633 	switch ( logicalIndex ) {
7634 		case QMC2_MACHINELIST_COLUMN_MACHINE:
7635 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_DESCRIPTION )
7636 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7637 			else
7638 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_DESCRIPTION);
7639 			break;
7640 
7641 		case QMC2_MACHINELIST_COLUMN_TAG:
7642 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_TAG )
7643 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7644 			else
7645 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_TAG);
7646 			break;
7647 
7648 		case QMC2_MACHINELIST_COLUMN_YEAR:
7649 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_YEAR )
7650 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7651 			else
7652 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_YEAR);
7653 			break;
7654 
7655 		case QMC2_MACHINELIST_COLUMN_MANU:
7656 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_MANUFACTURER )
7657 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7658 			else
7659 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_MANUFACTURER);
7660 			break;
7661 
7662 		case QMC2_MACHINELIST_COLUMN_NAME:
7663 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_MACHINENAME )
7664 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7665 			else
7666 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_MACHINENAME);
7667 			break;
7668 
7669 		case QMC2_MACHINELIST_COLUMN_RTYPES:
7670 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_ROMTYPES )
7671 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7672 			else
7673 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_ROMTYPES);
7674 			break;
7675 
7676 		case QMC2_MACHINELIST_COLUMN_PLAYERS:
7677 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_PLAYERS )
7678 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7679 			else
7680 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_PLAYERS);
7681 			break;
7682 
7683 		case QMC2_MACHINELIST_COLUMN_DRVSTAT:
7684 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_DRVSTAT )
7685 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7686 			else
7687 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_DRVSTAT);
7688 			break;
7689 
7690 		case QMC2_MACHINELIST_COLUMN_SRCFILE:
7691 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_SRCFILE )
7692 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7693 			else
7694 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_SRCFILE);
7695 			break;
7696 
7697 		case QMC2_MACHINELIST_COLUMN_RANK:
7698 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_RANK )
7699 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7700 			else
7701 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_RANK);
7702 			break;
7703 
7704 		case QMC2_MACHINELIST_COLUMN_CATEGORY:
7705 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_CATEGORY )
7706 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7707 			else
7708 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_CATEGORY);
7709 			break;
7710 
7711 		case QMC2_MACHINELIST_COLUMN_VERSION:
7712 			if ( qmc2Options->comboBoxSortCriteria->currentIndex() == QMC2_SORTCRITERIA_VERSION )
7713 				qmc2Options->comboBoxSortOrder->setCurrentIndex(qmc2Options->comboBoxSortOrder->currentIndex() == 0 ? 1 : 0);
7714 			else
7715 				qmc2Options->comboBoxSortCriteria->setCurrentIndex(QMC2_SORTCRITERIA_VERSION);
7716 			break;
7717 
7718 		default:
7719 			break;
7720 	}
7721 
7722 	QTimer::singleShot(0, qmc2Options, SLOT(on_pushButtonApply_clicked()));
7723 }
7724 
menuTabWidgetMachineList_North_activated()7725 void MainWindow::menuTabWidgetMachineList_North_activated()
7726 {
7727 	tabWidgetMachineList->setTabPosition(QTabWidget::North);
7728 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineList/TabPosition", QTabWidget::North);
7729 }
7730 
menuTabWidgetMachineList_South_activated()7731 void MainWindow::menuTabWidgetMachineList_South_activated()
7732 {
7733 	tabWidgetMachineList->setTabPosition(QTabWidget::South);
7734 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineList/TabPosition", QTabWidget::South);
7735 }
7736 
menuTabWidgetMachineList_West_activated()7737 void MainWindow::menuTabWidgetMachineList_West_activated()
7738 {
7739 	tabWidgetMachineList->setTabPosition(QTabWidget::West);
7740 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineList/TabPosition", QTabWidget::West);
7741 }
7742 
menuTabWidgetMachineList_East_activated()7743 void MainWindow::menuTabWidgetMachineList_East_activated()
7744 {
7745 	tabWidgetMachineList->setTabPosition(QTabWidget::East);
7746 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineList/TabPosition", QTabWidget::East);
7747 }
7748 
menuTabWidgetMachineList_Setup_activated()7749 void MainWindow::menuTabWidgetMachineList_Setup_activated()
7750 {
7751 	if ( !qmc2ComponentSetup )
7752 		return;
7753 
7754 	qmc2ComponentSetup->adjustIconSizes();
7755 
7756 	qmc2ComponentSetup->setParent(this);
7757 	qmc2ComponentSetup->setWindowFlags(Qt::Dialog);
7758 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(0);
7759 
7760 	if ( qmc2ComponentSetup->isHidden() )
7761 		qmc2ComponentSetup->show();
7762 	else if ( qmc2ComponentSetup->isMinimized() )
7763 		qmc2ComponentSetup->showNormal();
7764 
7765 	QTimer::singleShot(0, qmc2ComponentSetup, SLOT(raise()));
7766 }
7767 
7768 
on_tabWidgetMachineList_customContextMenuRequested(const QPoint & p)7769 void MainWindow::on_tabWidgetMachineList_customContextMenuRequested(const QPoint &p)
7770 {
7771 	QTabBar *tabBar = tabWidgetMachineList->findChild<QTabBar *>();
7772 	if ( tabBar ) {
7773 		if ( tabBar->geometry().contains(p) ) {
7774 			while ( menuTabWidgetMachineList->actions().count() > 3 ) {
7775 				QAction *a = menuTabWidgetMachineList->actions().at(2);
7776 				menuTabWidgetMachineList->removeAction(a);
7777 				a->disconnect();
7778 				delete a;
7779 			}
7780 			QAction *insAct = menuTabWidgetMachineList->actions().last();
7781 			for (int i = 0; i < tabBar->count(); i++) {
7782 				QAction *a = new QAction(tabBar->tabIcon(i), tabBar->tabText(i).replace("&", ""), menuTabWidgetMachineList);
7783 				a->setData(i);
7784 				connect(a, SIGNAL(triggered(bool)), this, SLOT(tabWidgetMachineList_actionSwitchTab_triggered(bool)));
7785 				menuTabWidgetMachineList->insertAction(insAct, a);
7786 			}
7787 			QAction *a = new QAction(menuTabWidgetMachineList);
7788 			a->setSeparator(true);
7789 			menuTabWidgetMachineList->insertAction(menuTabWidgetMachineList->actions().last(), a);
7790 			menuTabWidgetMachineList->move(adjustedWidgetPosition(tabWidgetMachineList->mapToGlobal(p), menuTabWidgetMachineList));
7791 			menuTabWidgetMachineList->show();
7792 		}
7793 	}
7794 }
7795 
tabWidgetMachineList_actionSwitchTab_triggered(bool)7796 void MainWindow::tabWidgetMachineList_actionSwitchTab_triggered(bool)
7797 {
7798 	QAction *a = (QAction *)sender();
7799 	tabWidgetMachineList->setCurrentIndex(a->data().toInt());
7800 }
7801 
menuTabWidgetMachineDetail_North_activated()7802 void MainWindow::menuTabWidgetMachineDetail_North_activated()
7803 {
7804 	tabWidgetMachineDetail->setTabPosition(QTabWidget::North);
7805 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineDetail/TabPosition", QTabWidget::North);
7806 }
7807 
menuTabWidgetMachineDetail_South_activated()7808 void MainWindow::menuTabWidgetMachineDetail_South_activated()
7809 {
7810 	tabWidgetMachineDetail->setTabPosition(QTabWidget::South);
7811 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineDetail/TabPosition", QTabWidget::South);
7812 }
7813 
menuTabWidgetMachineDetail_West_activated()7814 void MainWindow::menuTabWidgetMachineDetail_West_activated()
7815 {
7816 	tabWidgetMachineDetail->setTabPosition(QTabWidget::West);
7817 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineDetail/TabPosition", QTabWidget::West);
7818 }
7819 
menuTabWidgetMachineDetail_East_activated()7820 void MainWindow::menuTabWidgetMachineDetail_East_activated()
7821 {
7822 	tabWidgetMachineDetail->setTabPosition(QTabWidget::East);
7823 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MachineDetail/TabPosition", QTabWidget::East);
7824 }
7825 
menuTabWidgetMachineDetail_Setup_activated()7826 void MainWindow::menuTabWidgetMachineDetail_Setup_activated()
7827 {
7828 	if ( !qmc2ComponentSetup )
7829 		return;
7830 
7831 	qmc2ComponentSetup->adjustIconSizes();
7832 
7833 	qmc2ComponentSetup->setParent(this);
7834 	qmc2ComponentSetup->setWindowFlags(Qt::Dialog);
7835 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(1);
7836 
7837 	if ( qmc2ComponentSetup->isHidden() )
7838 		qmc2ComponentSetup->show();
7839 	else if ( qmc2ComponentSetup->isMinimized() )
7840 		qmc2ComponentSetup->showNormal();
7841 
7842 	QTimer::singleShot(0, qmc2ComponentSetup, SLOT(raise()));
7843 }
7844 
on_tabWidgetMachineDetail_customContextMenuRequested(const QPoint & p)7845 void MainWindow::on_tabWidgetMachineDetail_customContextMenuRequested(const QPoint &p)
7846 {
7847 	QTabBar *tabBar = tabWidgetMachineDetail->findChild<QTabBar *>();
7848 	if ( tabBar ) {
7849 		if ( tabBar->geometry().contains(p) ) {
7850 			while ( menuTabWidgetMachineDetail->actions().count() > 3 ) {
7851 				QAction *a = menuTabWidgetMachineDetail->actions().at(2);
7852 				menuTabWidgetMachineDetail->removeAction(a);
7853 				a->disconnect();
7854 				delete a;
7855 			}
7856 			QAction *insAct = menuTabWidgetMachineDetail->actions().last();
7857 			for (int i = 0; i < tabBar->count(); i++) {
7858 				QAction *a = new QAction(tabBar->tabIcon(i), tabBar->tabText(i).replace("&", ""), menuTabWidgetMachineDetail);
7859 				a->setData(i);
7860 				connect(a, SIGNAL(triggered(bool)), this, SLOT(tabWidgetMachineDetail_actionSwitchTab_triggered(bool)));
7861 				menuTabWidgetMachineDetail->insertAction(insAct, a);
7862 			}
7863 			QAction *a = new QAction(menuTabWidgetMachineDetail);
7864 			a->setSeparator(true);
7865 			menuTabWidgetMachineDetail->insertAction(menuTabWidgetMachineDetail->actions().last(), a);
7866 			menuTabWidgetMachineDetail->move(adjustedWidgetPosition(tabWidgetMachineDetail->mapToGlobal(p), menuTabWidgetMachineDetail));
7867 			menuTabWidgetMachineDetail->show();
7868 		}
7869 	}
7870 }
7871 
tabWidgetMachineDetail_actionSwitchTab_triggered(bool)7872 void MainWindow::tabWidgetMachineDetail_actionSwitchTab_triggered(bool)
7873 {
7874 	QAction *a = (QAction *)sender();
7875 	tabWidgetMachineDetail->setCurrentIndex(a->data().toInt());
7876 }
7877 
menuTabWidgetLogsAndEmulators_North_activated()7878 void MainWindow::menuTabWidgetLogsAndEmulators_North_activated()
7879 {
7880 	tabWidgetLogsAndEmulators->setTabPosition(QTabWidget::North);
7881 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/LogsAndEmulators/TabPosition", QTabWidget::North);
7882 }
7883 
menuTabWidgetLogsAndEmulators_South_activated()7884 void MainWindow::menuTabWidgetLogsAndEmulators_South_activated()
7885 {
7886 	tabWidgetLogsAndEmulators->setTabPosition(QTabWidget::South);
7887 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/LogsAndEmulators/TabPosition", QTabWidget::South);
7888 }
7889 
menuTabWidgetLogsAndEmulators_West_activated()7890 void MainWindow::menuTabWidgetLogsAndEmulators_West_activated()
7891 {
7892 	tabWidgetLogsAndEmulators->setTabPosition(QTabWidget::West);
7893 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/LogsAndEmulators/TabPosition", QTabWidget::West);
7894 }
7895 
menuTabWidgetLogsAndEmulators_East_activated()7896 void MainWindow::menuTabWidgetLogsAndEmulators_East_activated()
7897 {
7898 	tabWidgetLogsAndEmulators->setTabPosition(QTabWidget::East);
7899 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/LogsAndEmulators/TabPosition", QTabWidget::East);
7900 }
7901 
menuTabWidgetLogsAndEmulators_Setup_activated()7902 void MainWindow::menuTabWidgetLogsAndEmulators_Setup_activated()
7903 {
7904 	if ( !qmc2ComponentSetup )
7905 		return;
7906 
7907 	qmc2ComponentSetup->adjustIconSizes();
7908 
7909 	// reparent detail setup dialog to the widget it was called from
7910 	qmc2ComponentSetup->setParent(this);
7911 	qmc2ComponentSetup->setWindowFlags(Qt::Dialog);
7912 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(2);
7913 
7914 	if ( qmc2ComponentSetup->isHidden() )
7915 		qmc2ComponentSetup->show();
7916 	else if ( qmc2ComponentSetup->isMinimized() )
7917 		qmc2ComponentSetup->showNormal();
7918 
7919 	QTimer::singleShot(0, qmc2ComponentSetup, SLOT(raise()));
7920 }
7921 
on_tabWidgetLogsAndEmulators_customContextMenuRequested(const QPoint & p)7922 void MainWindow::on_tabWidgetLogsAndEmulators_customContextMenuRequested(const QPoint &p)
7923 {
7924 	QTabBar *tabBar = tabWidgetLogsAndEmulators->findChild<QTabBar *>();
7925 	if ( tabBar ) {
7926 		if ( tabBar->geometry().contains(p) ) {
7927 			while ( menuTabWidgetLogsAndEmulators->actions().count() > 3 ) {
7928 				QAction *a = menuTabWidgetLogsAndEmulators->actions().at(2);
7929 				menuTabWidgetLogsAndEmulators->removeAction(a);
7930 				a->disconnect();
7931 				delete a;
7932 			}
7933 			QAction *insAct = menuTabWidgetLogsAndEmulators->actions().last();
7934 			for (int i = 0; i < tabBar->count(); i++) {
7935 				QAction *a = new QAction(tabBar->tabIcon(i), tabBar->tabText(i).replace("&", ""), menuTabWidgetLogsAndEmulators);
7936 				a->setData(i);
7937 				connect(a, SIGNAL(triggered(bool)), this, SLOT(tabWidgetLogsAndEmulators_actionSwitchTab_triggered(bool)));
7938 				menuTabWidgetLogsAndEmulators->insertAction(insAct, a);
7939 			}
7940 			QAction *a = new QAction(menuTabWidgetLogsAndEmulators);
7941 			a->setSeparator(true);
7942 			menuTabWidgetLogsAndEmulators->insertAction(menuTabWidgetLogsAndEmulators->actions().last(), a);
7943 			menuTabWidgetLogsAndEmulators->move(adjustedWidgetPosition(tabWidgetLogsAndEmulators->mapToGlobal(p), menuTabWidgetLogsAndEmulators));
7944 			menuTabWidgetLogsAndEmulators->show();
7945 		}
7946 	}
7947 }
7948 
tabWidgetLogsAndEmulators_actionSwitchTab_triggered(bool)7949 void MainWindow::tabWidgetLogsAndEmulators_actionSwitchTab_triggered(bool)
7950 {
7951 	QAction *a = (QAction *)sender();
7952 	tabWidgetLogsAndEmulators->setCurrentIndex(a->data().toInt());
7953 }
7954 
menuTabWidgetSoftwareDetail_North_activated()7955 void MainWindow::menuTabWidgetSoftwareDetail_North_activated()
7956 {
7957 	tabWidgetSoftwareDetail->setTabPosition(QTabWidget::North);
7958 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/SoftwareDetail/TabPosition", QTabWidget::North);
7959 }
7960 
menuTabWidgetSoftwareDetail_South_activated()7961 void MainWindow::menuTabWidgetSoftwareDetail_South_activated()
7962 {
7963 	tabWidgetSoftwareDetail->setTabPosition(QTabWidget::South);
7964 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/SoftwareDetail/TabPosition", QTabWidget::South);
7965 }
7966 
menuTabWidgetSoftwareDetail_West_activated()7967 void MainWindow::menuTabWidgetSoftwareDetail_West_activated()
7968 {
7969 	tabWidgetSoftwareDetail->setTabPosition(QTabWidget::West);
7970 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/SoftwareDetail/TabPosition", QTabWidget::West);
7971 }
7972 
menuTabWidgetSoftwareDetail_East_activated()7973 void MainWindow::menuTabWidgetSoftwareDetail_East_activated()
7974 {
7975 	tabWidgetSoftwareDetail->setTabPosition(QTabWidget::East);
7976 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/SoftwareDetail/TabPosition", QTabWidget::East);
7977 }
7978 
menuTabWidgetSoftwareDetail_Setup_activated()7979 void MainWindow::menuTabWidgetSoftwareDetail_Setup_activated()
7980 {
7981 	if ( !qmc2ComponentSetup )
7982 		return;
7983 
7984 	qmc2ComponentSetup->adjustIconSizes();
7985 
7986 	qmc2ComponentSetup->setParent(this);
7987 	qmc2ComponentSetup->setWindowFlags(Qt::Dialog);
7988 	qmc2ComponentSetup->comboBoxComponents->setCurrentIndex(3);
7989 
7990 	if ( qmc2ComponentSetup->isHidden() )
7991 		qmc2ComponentSetup->show();
7992 	else if ( qmc2ComponentSetup->isMinimized() )
7993 		qmc2ComponentSetup->showNormal();
7994 
7995 	QTimer::singleShot(0, qmc2ComponentSetup, SLOT(raise()));
7996 }
7997 
on_tabWidgetSoftwareDetail_customContextMenuRequested(const QPoint & p)7998 void MainWindow::on_tabWidgetSoftwareDetail_customContextMenuRequested(const QPoint &p)
7999 {
8000 	QTabBar *tabBar = tabWidgetSoftwareDetail->findChild<QTabBar *>();
8001 	if ( tabBar ) {
8002 		if ( tabBar->geometry().contains(p) ) {
8003 			while ( menuTabWidgetSoftwareDetail->actions().count() > 3 ) {
8004 				QAction *a = menuTabWidgetSoftwareDetail->actions().at(2);
8005 				menuTabWidgetSoftwareDetail->removeAction(a);
8006 				a->disconnect();
8007 				delete a;
8008 			}
8009 			QAction *insAct = menuTabWidgetSoftwareDetail->actions().last();
8010 			for (int i = 0; i < tabBar->count(); i++) {
8011 				QAction *a = new QAction(tabBar->tabIcon(i), tabBar->tabText(i).replace("&", ""), menuTabWidgetSoftwareDetail);
8012 				a->setData(i);
8013 				connect(a, SIGNAL(triggered(bool)), this, SLOT(tabWidgetSoftwareDetail_actionSwitchTab_triggered(bool)));
8014 				menuTabWidgetSoftwareDetail->insertAction(insAct, a);
8015 			}
8016 			QAction *a = new QAction(menuTabWidgetSoftwareDetail);
8017 			a->setSeparator(true);
8018 			menuTabWidgetSoftwareDetail->insertAction(menuTabWidgetSoftwareDetail->actions().last(), a);
8019 			menuTabWidgetSoftwareDetail->move(adjustedWidgetPosition(tabWidgetSoftwareDetail->mapToGlobal(p), menuTabWidgetSoftwareDetail));
8020 			menuTabWidgetSoftwareDetail->show();
8021 		}
8022 	}
8023 }
8024 
tabWidgetSoftwareDetail_actionSwitchTab_triggered(bool)8025 void MainWindow::tabWidgetSoftwareDetail_actionSwitchTab_triggered(bool)
8026 {
8027 	QAction *a = (QAction *)sender();
8028 	tabWidgetSoftwareDetail->setCurrentIndex(a->data().toInt());
8029 }
8030 
treeWidgetHierarchy_headerSectionClicked(int logicalIndex)8031 void MainWindow::treeWidgetHierarchy_headerSectionClicked(int logicalIndex)
8032 {
8033 	treeWidgetMachineList_headerSectionClicked(logicalIndex);
8034 }
8035 
treeWidgetCategoryView_headerSectionClicked(int logicalIndex)8036 void MainWindow::treeWidgetCategoryView_headerSectionClicked(int logicalIndex)
8037 {
8038 	treeWidgetMachineList_headerSectionClicked(logicalIndex);
8039 }
8040 
on_treeWidgetCategoryView_itemActivated(QTreeWidgetItem * item,int column)8041 void MainWindow::on_treeWidgetCategoryView_itemActivated(QTreeWidgetItem *item, int column)
8042 {
8043 	if ( qmc2DemoModeDialog )
8044 		if ( qmc2DemoModeDialog->demoModeRunning )
8045 			return;
8046 	if ( !item )
8047 		return;
8048 	if ( item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8049 		return;
8050 	qmc2StartEmbedded = false;
8051 	if ( !qmc2IgnoreItemActivation ) {
8052 		switch ( qmc2DefaultLaunchMode ) {
8053 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
8054 			case QMC2_LAUNCH_MODE_EMBEDDED:
8055 				on_actionPlayEmbedded_triggered();
8056 				break;
8057 #endif
8058 			case QMC2_LAUNCH_MODE_INDEPENDENT:
8059 			default:
8060 				on_actionPlay_triggered();
8061 				break;
8062 		}
8063 	}
8064 	qmc2IgnoreItemActivation = false;
8065 }
8066 
on_treeWidgetCategoryView_itemDoubleClicked(QTreeWidgetItem * item,int column)8067 void MainWindow::on_treeWidgetCategoryView_itemDoubleClicked(QTreeWidgetItem *item, int column)
8068 {
8069 	if ( !item )
8070 		return;
8071 	if ( item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8072 		return;
8073 	if ( qmc2DemoModeDialog )
8074 		if ( qmc2DemoModeDialog->demoModeRunning )
8075 			qmc2IgnoreItemActivation = true;
8076 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/DoubleClickActivation").toBool() )
8077 		qmc2IgnoreItemActivation = true;
8078 }
8079 
on_treeWidgetCategoryView_currentItemChanged(QTreeWidgetItem * current,QTreeWidgetItem * previous)8080 void MainWindow::on_treeWidgetCategoryView_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
8081 {
8082 	if ( !current )
8083 		return;
8084 	if ( current->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8085 		return;
8086 	qmc2CheckItemVisibility = false;
8087 	if ( qmc2UpdateDelay > 0 )
8088 		updateTimer.start(qmc2UpdateDelay);
8089 	else
8090 		treeWidgetMachineList_itemSelectionChanged_delayed();
8091 }
8092 
on_treeWidgetCategoryView_itemSelectionChanged()8093 void MainWindow::on_treeWidgetCategoryView_itemSelectionChanged()
8094 {
8095 	qmc2CategoryViewSelectedItem = 0;
8096 	QList<QTreeWidgetItem *>selected = treeWidgetCategoryView->selectedItems();
8097 	if ( selected.count() > 0 ) {
8098 		QTreeWidgetItem *item = selected.at(0);
8099 		if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData || item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8100 			return;
8101 		qmc2CategoryViewSelectedItem = qmc2MachineListItemHash.value(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8102 		qmc2CheckItemVisibility = false;
8103 		treeWidgetMachineList->setCurrentItem(qmc2CategoryViewSelectedItem);
8104 	}
8105 }
8106 
on_treeWidgetCategoryView_customContextMenuRequested(const QPoint & p)8107 void MainWindow::on_treeWidgetCategoryView_customContextMenuRequested(const QPoint &p)
8108 {
8109 	QTreeWidgetItem *item = treeWidgetCategoryView->itemAt(p);
8110 	if ( !item )
8111 		return;
8112 	if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData || item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8113 		return;
8114 	treeWidgetCategoryView->setItemSelected(item, true);
8115 	qmc2MachineMenu->move(adjustedWidgetPosition(treeWidgetCategoryView->viewport()->mapToGlobal(p), qmc2MachineMenu));
8116 	qmc2MachineMenu->show();
8117 }
8118 
treeWidgetVersionView_headerSectionClicked(int logicalIndex)8119 void MainWindow::treeWidgetVersionView_headerSectionClicked(int logicalIndex)
8120 {
8121 	treeWidgetMachineList_headerSectionClicked(logicalIndex);
8122 }
8123 
on_treeWidgetVersionView_itemActivated(QTreeWidgetItem * item,int column)8124 void MainWindow::on_treeWidgetVersionView_itemActivated(QTreeWidgetItem *item, int column)
8125 {
8126 	if ( qmc2DemoModeDialog )
8127 		if ( qmc2DemoModeDialog->demoModeRunning )
8128 			return;
8129 	if ( !item )
8130 		return;
8131 	if ( item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8132 		return;
8133 	qmc2StartEmbedded = false;
8134 	if ( !qmc2IgnoreItemActivation ) {
8135 		switch ( qmc2DefaultLaunchMode ) {
8136 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
8137 			case QMC2_LAUNCH_MODE_EMBEDDED:
8138 				on_actionPlayEmbedded_triggered();
8139 				break;
8140 #endif
8141 			case QMC2_LAUNCH_MODE_INDEPENDENT:
8142 			default:
8143 				on_actionPlay_triggered();
8144 				break;
8145 		}
8146 	}
8147 	qmc2IgnoreItemActivation = false;
8148 }
8149 
on_treeWidgetVersionView_itemDoubleClicked(QTreeWidgetItem * item,int column)8150 void MainWindow::on_treeWidgetVersionView_itemDoubleClicked(QTreeWidgetItem *item, int column)
8151 {
8152 	if ( !item )
8153 		return;
8154 	if ( item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8155 		return;
8156 	if ( !qmc2Config->value(QMC2_FRONTEND_PREFIX + "MachineList/DoubleClickActivation").toBool() )
8157 		qmc2IgnoreItemActivation = true;
8158 }
8159 
on_treeWidgetVersionView_currentItemChanged(QTreeWidgetItem * current,QTreeWidgetItem * previous)8160 void MainWindow::on_treeWidgetVersionView_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
8161 {
8162 	if ( !current )
8163 		return;
8164 	if ( current->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8165 		return;
8166 	qmc2CheckItemVisibility = false;
8167 	if ( qmc2UpdateDelay > 0 )
8168 		updateTimer.start(qmc2UpdateDelay);
8169 	else
8170 		treeWidgetMachineList_itemSelectionChanged_delayed();
8171 }
8172 
on_treeWidgetVersionView_itemSelectionChanged()8173 void MainWindow::on_treeWidgetVersionView_itemSelectionChanged()
8174 {
8175 	qmc2VersionViewSelectedItem = 0;
8176 	QList<QTreeWidgetItem *>selected = treeWidgetVersionView->selectedItems();
8177 	if ( selected.count() > 0 ) {
8178 		QTreeWidgetItem *item = selected.at(0);
8179 		if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData || item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8180 			return;
8181 		qmc2VersionViewSelectedItem = qmc2MachineListItemHash.value(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8182 		qmc2CheckItemVisibility = false;
8183 		treeWidgetMachineList->setCurrentItem(qmc2VersionViewSelectedItem);
8184 	}
8185 }
8186 
on_treeWidgetVersionView_customContextMenuRequested(const QPoint & p)8187 void MainWindow::on_treeWidgetVersionView_customContextMenuRequested(const QPoint &p)
8188 {
8189 	QTreeWidgetItem *item = treeWidgetVersionView->itemAt(p);
8190 	if ( !item )
8191 		return;
8192 	if ( item->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData || item->text(QMC2_MACHINELIST_COLUMN_NAME).isEmpty() )
8193 		return;
8194 	treeWidgetVersionView->setItemSelected(item, true);
8195 	qmc2MachineMenu->move(adjustedWidgetPosition(treeWidgetVersionView->viewport()->mapToGlobal(p), qmc2MachineMenu));
8196 	qmc2MachineMenu->show();
8197 }
8198 
on_comboBoxViewSelect_currentIndexChanged(int index)8199 void MainWindow::on_comboBoxViewSelect_currentIndexChanged(int index)
8200 {
8201 	if ( tabWidgetMachineList->indexOf(tabMachineList) != tabWidgetMachineList->currentIndex() )
8202 		return;
8203 
8204 	bool romFilterActive = qmc2Config->value(QMC2_FRONTEND_PREFIX + "RomStateFilter/Enabled", true).toBool();
8205 	switch ( index ) {
8206 		case QMC2_VIEWHIERARCHY_INDEX:
8207 			toolButtonSelectRomFilter->setVisible(false);
8208 			menuRomStatusFilter->setVisible(false);
8209 			actionTagVisible->setVisible(false);
8210 			actionUntagVisible->setVisible(false);
8211 			actionInvertVisibleTags->setVisible(false);
8212 			viewParentClones();
8213 			break;
8214 		case QMC2_VIEWCATEGORY_INDEX:
8215 			toolButtonSelectRomFilter->setVisible(false);
8216 			menuRomStatusFilter->setVisible(false);
8217 			actionTagVisible->setVisible(false);
8218 			actionUntagVisible->setVisible(false);
8219 			actionInvertVisibleTags->setVisible(false);
8220 			viewByCategory();
8221 			break;
8222 		case QMC2_VIEWVERSION_INDEX:
8223 			toolButtonSelectRomFilter->setVisible(false);
8224 			menuRomStatusFilter->setVisible(false);
8225 			actionTagVisible->setVisible(false);
8226 			actionUntagVisible->setVisible(false);
8227 			actionInvertVisibleTags->setVisible(false);
8228 			viewByVersion();
8229 			break;
8230 		case QMC2_VIEWMACHINELIST_INDEX:
8231 			toolButtonSelectRomFilter->setVisible(romFilterActive);
8232 			actionTagVisible->setVisible(romFilterActive);
8233 			actionUntagVisible->setVisible(romFilterActive);
8234 			actionInvertVisibleTags->setVisible(romFilterActive);
8235 			viewFullDetail();
8236 			break;
8237 		default:
8238 			showAttachedView(comboBoxViewSelect->itemText(index));
8239 			break;
8240 	}
8241 }
8242 
projectMessLoadStarted()8243 void MainWindow::projectMessLoadStarted()
8244 {
8245 }
8246 
projectMessLoadFinished(bool ok)8247 void MainWindow::projectMessLoadFinished(bool ok)
8248 {
8249 	if ( qmc2SoftwareList->currentItem && qmc2ProjectMESS && ok ) {
8250 		// store compressed page to in-memory cache
8251 		QString cacheKey = qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_LIST) + "_" + qmc2SoftwareList->currentItem->text(QMC2_SWLIST_COLUMN_NAME);
8252 		if ( qmc2ProjectMESSCache.contains(cacheKey) )
8253 			qmc2ProjectMESSCache.remove(cacheKey);
8254 		QByteArray data = QMC2_COMPRESS(qmc2ProjectMESS->webViewBrowser->page()->mainFrame()->toHtml().toUtf8());
8255 		qmc2ProjectMESSCache.insert(cacheKey, new QByteArray(data), data.size());
8256 	}
8257 
8258 	// we only want to know this ONCE
8259 	disconnect(qmc2ProjectMESS->webViewBrowser, SIGNAL(loadFinished(bool)), this, SLOT(projectMessLoadFinished(bool)));
8260 }
8261 
projectMessSystemLoadStarted()8262 void MainWindow::projectMessSystemLoadStarted()
8263 {
8264 	// NOP
8265 }
8266 
projectMessSystemLoadFinished(bool ok)8267 void MainWindow::projectMessSystemLoadFinished(bool ok)
8268 {
8269 	if ( ok ) {
8270 		QByteArray projectMessData = QMC2_COMPRESS(qmc2ProjectMESSLookup->webViewBrowser->page()->mainFrame()->toHtml().toUtf8());
8271     		QString machName = qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME);
8272 		if ( qmc2ProjectMESSCache.contains(machName) )
8273 			qmc2ProjectMESSCache.remove(machName);
8274 		qmc2ProjectMESSCache.insert(machName, new QByteArray(projectMessData), projectMessData.size());
8275 	}
8276 }
8277 
startDownload(QWidget * forParent,QNetworkReply * reply,QString saveAsName,QString savePath)8278 void MainWindow::startDownload(QWidget *forParent, QNetworkReply *reply, QString saveAsName, QString savePath)
8279 {
8280 	if ( !reply )
8281 		return;
8282 
8283 	QFileInfo fi(reply->url().path());
8284 	QString proposedName = fi.baseName();
8285 	if ( !saveAsName.isEmpty() )
8286 		proposedName = saveAsName;
8287 	else if ( !fi.completeSuffix().isEmpty() )
8288 		proposedName += "." + fi.completeSuffix();
8289 
8290 	QString filePath;
8291 
8292 	if ( !saveAsName.isEmpty() && !savePath.isEmpty() ) {
8293 		if ( !savePath.endsWith("/") )
8294 			savePath.append("/");
8295 		filePath = savePath + saveAsName;
8296 	} else {
8297 		if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "WebBrowser/LastStoragePath") )
8298 			proposedName.prepend(qmc2Config->value(QMC2_FRONTEND_PREFIX + "WebBrowser/LastStoragePath").toString());
8299 		filePath = QFileDialog::getSaveFileName(forParent, tr("Choose file to store download"), proposedName, tr("All files (*)"), 0, qmc2Options->useNativeFileDialogs() ? (QFileDialog::Options)0 : QFileDialog::DontUseNativeDialog);
8300 	}
8301 
8302 	if ( !filePath.isEmpty() ) {
8303 		DownloadItem *downloadItem = new DownloadItem(reply, filePath, treeWidgetDownloads);
8304 		treeWidgetDownloads->scrollToItem(downloadItem);
8305 		QFileInfo fiFilePath(filePath);
8306 		QString storagePath = fiFilePath.absolutePath();
8307 		if ( !storagePath.endsWith("/") )
8308 			storagePath.append("/");
8309 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "WebBrowser/LastStoragePath", storagePath);
8310 	} else
8311 		reply->close();
8312 }
8313 
on_pushButtonClearFinishedDownloads_clicked()8314 void MainWindow::on_pushButtonClearFinishedDownloads_clicked()
8315 {
8316 	static bool downloadCleanupActive = false;
8317 
8318 	if ( downloadCleanupActive )
8319 		return;
8320 
8321 	downloadCleanupActive = true;
8322 
8323 	QList<int> indexList;
8324 
8325 	QTreeWidgetItemIterator it(treeWidgetDownloads);
8326 	while ( *it ) {
8327 		if ( (*it)->whatsThis(0) == "finished" || (*it)->whatsThis(0) == "aborted" )
8328 			indexList << treeWidgetDownloads->indexOfTopLevelItem(*it);
8329 		it++;
8330 	}
8331 
8332 	for (int i = indexList.count(); i >= 0; i--) {
8333 		DownloadItem *item = (DownloadItem *)treeWidgetDownloads->takeTopLevelItem(indexList[i]);
8334 		if ( item )
8335 			delete item;
8336 		if ( i % 10 == 0 ) qApp->processEvents();
8337 	}
8338 
8339 	downloadCleanupActive = false;
8340 }
8341 
on_pushButtonReloadSelectedDownloads_clicked()8342 void MainWindow::on_pushButtonReloadSelectedDownloads_clicked()
8343 {
8344 	QTreeWidgetItemIterator it(treeWidgetDownloads);
8345 	while ( *it ) {
8346 		if ( (*it)->isSelected() )
8347 			if ( (*it)->whatsThis(0) != "downloading" && (*it)->whatsThis(0) != "initializing" )
8348 				((DownloadItem*)(*it))->itemDownloader->reload();
8349 		it++;
8350 	}
8351 }
8352 
on_pushButtonStopSelectedDownloads_clicked()8353 void MainWindow::on_pushButtonStopSelectedDownloads_clicked()
8354 {
8355 	QTreeWidgetItemIterator it(treeWidgetDownloads);
8356 	while ( *it ) {
8357 		if ( (*it)->isSelected() ) {
8358 			if ( (*it)->whatsThis(0) == "downloading" )
8359 				((DownloadItem*)(*it))->itemDownloader->networkReply->abort();
8360 		}
8361 		it++;
8362 	}
8363 }
8364 
checkActivity()8365 void MainWindow::checkActivity()
8366 {
8367 	// resync timer (as far as possible)
8368 	activityCheckTimer.start(QMC2_ACTIVITY_CHECK_INTERVAL);
8369 
8370 	if ( qmc2ReloadActive || qmc2VerifyActive || qmc2VerifyTaggedActive || qmc2FilterActive || qmc2ImageCheckActive || qmc2SampleCheckActive || (qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->active()) || (qmc2SoftwareROMAlyzer && qmc2SoftwareROMAlyzer->active()) || qmc2LoadingMachineInfoDB || qmc2LoadingSoftwareInfoDB || qmc2LoadingEmuInfoDB || (qmc2SoftwareList && qmc2SoftwareList->isLoading) ) {
8371 		activityState = !activityState;
8372 		if ( activityState )
8373 			actionExitStop->setIcon(QIcon(QString::fromUtf8(":/data/img/activity_green.png")));
8374 		else
8375 			actionExitStop->setIcon(QIcon(QString::fromUtf8(":/data/img/activity_red.png")));
8376 		toolbar->update();
8377 		isActiveState = true;
8378 	} else {
8379 		if ( isActiveState ) {
8380 			actionExitStop->setIcon(QIcon(QString::fromUtf8(":/data/img/exit.png")));
8381 			toolbar->update();
8382 			activityState = false;
8383 		}
8384 		isActiveState = false;
8385 	}
8386 
8387 	if ( qmc2SystemNotesEditor ) {
8388 		qmc2SystemNotesEditor->move(0, 0);
8389 		qmc2SystemNotesEditor->resize(qmc2SystemNotesEditor->parentWidget()->size());
8390 	}
8391 
8392 	if ( menuRank->isVisible() || menuRank->isTearOffMenuVisible() )
8393 		QTimer::singleShot(0, this, SLOT(menuRank_aboutToShow()));
8394 }
8395 
sortCriteriaLogicalIndex()8396 int MainWindow::sortCriteriaLogicalIndex()
8397 {
8398 	switch ( qmc2SortCriteria ) {
8399 		case QMC2_SORT_BY_TAG:
8400 			return QMC2_MACHINELIST_COLUMN_TAG;
8401 		case QMC2_SORT_BY_YEAR:
8402 			return QMC2_MACHINELIST_COLUMN_YEAR;
8403 		case QMC2_SORT_BY_MANUFACTURER:
8404 			return QMC2_MACHINELIST_COLUMN_MANU;
8405 		case QMC2_SORT_BY_NAME:
8406 			return QMC2_MACHINELIST_COLUMN_NAME;
8407 		case QMC2_SORT_BY_ROMTYPES:
8408 			return QMC2_MACHINELIST_COLUMN_RTYPES;
8409 		case QMC2_SORT_BY_PLAYERS:
8410 			return QMC2_MACHINELIST_COLUMN_PLAYERS;
8411 		case QMC2_SORT_BY_DRVSTAT:
8412 			return QMC2_MACHINELIST_COLUMN_DRVSTAT;
8413 		case QMC2_SORT_BY_SRCFILE:
8414 			return QMC2_MACHINELIST_COLUMN_SRCFILE;
8415 		case QMC2_SORT_BY_RANK:
8416 			return QMC2_MACHINELIST_COLUMN_RANK;
8417 		case QMC2_SORT_BY_CATEGORY:
8418 			return QMC2_MACHINELIST_COLUMN_CATEGORY;
8419 		case QMC2_SORT_BY_VERSION:
8420 			return QMC2_MACHINELIST_COLUMN_VERSION;
8421 		case QMC2_SORT_BY_DESCRIPTION:
8422 		case QMC2_SORT_BY_ROM_STATE:
8423 		default:
8424 			return QMC2_MACHINELIST_COLUMN_MACHINE;
8425 	}
8426 }
8427 
adjustedWidgetPosition(QPoint p,QWidget * w)8428 QPoint MainWindow::adjustedWidgetPosition(QPoint p, QWidget *w)
8429 {
8430 	static QPoint adjustedPosition;
8431 	static QList<QWidget *> adjustedWidgets;
8432 
8433 	if ( !adjustedWidgets.contains(w) ) {
8434 		w->move(p);
8435 		w->show();
8436 		adjustedWidgets.append(w);
8437 	}
8438 
8439 	adjustedPosition = p;
8440 	if ( p.x() + w->width() > desktopGeometry.width() )
8441 		adjustedPosition.setX(desktopGeometry.width() - w->width());
8442 	if ( p.y() + w->height() > desktopGeometry.height() )
8443 		adjustedPosition.setY(desktopGeometry.height() - w->height());
8444 
8445 	return adjustedPosition;
8446 }
8447 
enableContextMenuPlayActions(bool enable)8448 void MainWindow::enableContextMenuPlayActions(bool enable)
8449 {
8450 	foreach(QAction *action, contextMenuPlayActions)
8451 		action->setEnabled(enable);
8452 }
8453 
treeWidgetMachineListHeader_customContextMenuRequested(const QPoint & p)8454 void MainWindow::treeWidgetMachineListHeader_customContextMenuRequested(const QPoint &p)
8455 {
8456 	menuMachineListHeader->move(adjustedWidgetPosition(treeWidgetMachineList->header()->viewport()->mapToGlobal(p), menuMachineListHeader));
8457 	menuMachineListHeader->show();
8458 }
8459 
actionMachineListHeader_triggered()8460 void MainWindow::actionMachineListHeader_triggered()
8461 {
8462 	QAction *action = (QAction *)sender();
8463 	int visibleColumns = 0;
8464 	for (int i = 0; i < treeWidgetMachineList->columnCount(); i++)
8465 		if ( !treeWidgetMachineList->isColumnHidden(i) )
8466 			visibleColumns++;
8467 	if ( action ) {
8468 		if ( action->data().toInt() == QMC2_MACHINELIST_RESET ) {
8469 			for (int i = 0; i < treeWidgetMachineList->columnCount(); i++) {
8470 				if ( i == QMC2_MACHINELIST_COLUMN_CATEGORY ) {
8471 				       	if ( qmc2CategoryInfoUsed )
8472 						treeWidgetMachineList->setColumnHidden(i, false);
8473 				} else if ( i == QMC2_MACHINELIST_COLUMN_VERSION ) {
8474 				       	if ( qmc2VersionInfoUsed )
8475 						treeWidgetMachineList->setColumnHidden(i, false);
8476 				} else
8477 					treeWidgetMachineList->setColumnHidden(i, false);
8478 			}
8479 			treeWidgetMachineList->header()->resizeSections(QHeaderView::Stretch);
8480 			foreach (QAction *a, menuMachineListHeader->actions())
8481 				if ( a->isCheckable() ) {
8482 					a->blockSignals(true);
8483 					a->setChecked(true);
8484 					a->blockSignals(false);
8485 				}
8486 			return;
8487 		}
8488 		bool visibility = true;
8489 		if ( action->isChecked() )
8490 			treeWidgetMachineList->setColumnHidden(action->data().toInt(), false);
8491 		else if ( visibleColumns > 1 ) {
8492 			treeWidgetMachineList->setColumnHidden(action->data().toInt(), true);
8493 			visibility = false;
8494 		}
8495 		action->blockSignals(true);
8496 		action->setChecked(visibility);
8497 		action->blockSignals(false);
8498 		QTimer::singleShot(0, this, SLOT(updateUserData()));
8499 	}
8500 }
8501 
treeWidgetHierarchyHeader_customContextMenuRequested(const QPoint & p)8502 void MainWindow::treeWidgetHierarchyHeader_customContextMenuRequested(const QPoint &p)
8503 {
8504 	menuHierarchyHeader->move(adjustedWidgetPosition(treeWidgetHierarchy->header()->viewport()->mapToGlobal(p), menuHierarchyHeader));
8505 	menuHierarchyHeader->show();
8506 }
8507 
actionHierarchyHeader_triggered()8508 void MainWindow::actionHierarchyHeader_triggered()
8509 {
8510 	QAction *action = (QAction *)sender();
8511 	int visibleColumns = 0;
8512 	for (int i = 0; i < treeWidgetHierarchy->columnCount(); i++)
8513 		if ( !treeWidgetHierarchy->isColumnHidden(i) )
8514 			visibleColumns++;
8515 	if ( action ) {
8516 		if ( action->data().toInt() == QMC2_MACHINELIST_RESET ) {
8517 			for (int i = 0; i < treeWidgetHierarchy->columnCount(); i++) {
8518 				if ( i == QMC2_MACHINELIST_COLUMN_CATEGORY ) {
8519 				       	if ( qmc2CategoryInfoUsed )
8520 						treeWidgetHierarchy->setColumnHidden(i, false);
8521 				} else if ( i == QMC2_MACHINELIST_COLUMN_VERSION ) {
8522 				       	if ( qmc2VersionInfoUsed )
8523 						treeWidgetHierarchy->setColumnHidden(i, false);
8524 				} else
8525 					treeWidgetHierarchy->setColumnHidden(i, false);
8526 			}
8527 			treeWidgetHierarchy->header()->resizeSections(QHeaderView::Stretch);
8528 			foreach (QAction *a, menuHierarchyHeader->actions())
8529 				if ( a->isCheckable() ) {
8530 					a->blockSignals(true);
8531 					a->setChecked(true);
8532 					a->blockSignals(false);
8533 				}
8534 			return;
8535 		}
8536 		bool visibility = true;
8537 		if ( action->isChecked() )
8538 			treeWidgetHierarchy->setColumnHidden(action->data().toInt(), false);
8539 		else if ( visibleColumns > 1 ) {
8540 			treeWidgetHierarchy->setColumnHidden(action->data().toInt(), true);
8541 			visibility = false;
8542 		}
8543 		action->blockSignals(true);
8544 		action->setChecked(visibility);
8545 		action->blockSignals(false);
8546 		QTimer::singleShot(0, this, SLOT(updateUserData()));
8547 	}
8548 }
8549 
on_treeWidgetMachineList_itemEntered(QTreeWidgetItem * item,int column)8550 void MainWindow::on_treeWidgetMachineList_itemEntered(QTreeWidgetItem *item, int column)
8551 {
8552 	if ( column == QMC2_MACHINELIST_COLUMN_TAG && item->parent() == 0 ) {
8553 		if ( qApp->mouseButtons() == Qt::LeftButton && qApp->activeWindow() ) {
8554 			QPoint cPos = treeWidgetMachineList->viewport()->mapFromGlobal(QCursor::pos());
8555 			if ( treeWidgetMachineList->itemAt(cPos) == item ) {
8556 				Qt::CheckState cs = (item->checkState(column) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
8557 				bool wasTagged = (cs != Qt::Checked);
8558 				item->setCheckState(column, cs);
8559 				QString machineName(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8560 				item = qmc2HierarchyItemHash.value(machineName);
8561 				if ( item )
8562 					item->setCheckState(column, cs);
8563 				item = qmc2CategoryItemHash.value(machineName);
8564 				if ( item )
8565 					item->setCheckState(column, cs);
8566 				item = qmc2VersionItemHash.value(machineName);
8567 				if ( item )
8568 					item->setCheckState(column, cs);
8569 				if ( wasTagged )
8570 					qmc2MachineList->numTaggedSets--;
8571 				else
8572 					qmc2MachineList->numTaggedSets++;
8573 				foreach (MachineListViewer *v, machineListViewers)
8574 					v->mainTagChanged(machineName, !wasTagged);
8575 				labelMachineListStatus->setText(qmc2MachineList->status());
8576 			}
8577 		}
8578 	}
8579 }
8580 
on_treeWidgetMachineList_itemPressed(QTreeWidgetItem * item,int column)8581 void MainWindow::on_treeWidgetMachineList_itemPressed(QTreeWidgetItem *item, int column)
8582 {
8583 	on_treeWidgetMachineList_itemEntered(item, column);
8584 }
8585 
on_treeWidgetHierarchy_itemEntered(QTreeWidgetItem * item,int column)8586 void MainWindow::on_treeWidgetHierarchy_itemEntered(QTreeWidgetItem *item, int column)
8587 {
8588 	if ( column == QMC2_MACHINELIST_COLUMN_TAG ) {
8589 		if ( qApp->mouseButtons() == Qt::LeftButton && qApp->activeWindow() ) {
8590 			QPoint cPos = treeWidgetHierarchy->viewport()->mapFromGlobal(QCursor::pos());
8591 			if ( treeWidgetHierarchy->itemAt(cPos) == item ) {
8592 				Qt::CheckState cs = (item->checkState(column) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
8593 				bool wasTagged = (cs != Qt::Checked);
8594 				item->setCheckState(column, cs);
8595 				QString machineName(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8596 				item = qmc2MachineListItemHash.value(machineName);
8597 				if ( item )
8598 					item->setCheckState(column, cs);
8599 				item = qmc2CategoryItemHash.value(machineName);
8600 				if ( item )
8601 					item->setCheckState(column, cs);
8602 				item = qmc2VersionItemHash.value(machineName);
8603 				if ( item )
8604 					item->setCheckState(column, cs);
8605 				if ( wasTagged )
8606 					qmc2MachineList->numTaggedSets--;
8607 				else
8608 					qmc2MachineList->numTaggedSets++;
8609 				foreach (MachineListViewer *v, machineListViewers)
8610 					v->mainTagChanged(machineName, !wasTagged);
8611 				labelMachineListStatus->setText(qmc2MachineList->status());
8612 			}
8613 		}
8614 	}
8615 }
8616 
on_treeWidgetHierarchy_itemPressed(QTreeWidgetItem * item,int column)8617 void MainWindow::on_treeWidgetHierarchy_itemPressed(QTreeWidgetItem *item, int column)
8618 {
8619 	on_treeWidgetHierarchy_itemEntered(item, column);
8620 }
8621 
on_treeWidgetCategoryView_itemEntered(QTreeWidgetItem * item,int column)8622 void MainWindow::on_treeWidgetCategoryView_itemEntered(QTreeWidgetItem *item, int column)
8623 {
8624 	if ( column == QMC2_MACHINELIST_COLUMN_TAG ) {
8625 		if ( item->parent() ) {
8626 			if ( qApp->mouseButtons() == Qt::LeftButton && qApp->activeWindow() ) {
8627 				QPoint cPos = treeWidgetCategoryView->viewport()->mapFromGlobal(QCursor::pos());
8628 				if ( treeWidgetCategoryView->itemAt(cPos) == item ) {
8629 					Qt::CheckState cs = (item->checkState(column) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
8630 					bool wasTagged = (cs != Qt::Checked);
8631 					item->setCheckState(column, cs);
8632 					QString machineName(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8633 					item = qmc2MachineListItemHash.value(machineName);
8634 					if ( item )
8635 						item->setCheckState(column, cs);
8636 					item = qmc2HierarchyItemHash.value(machineName);
8637 					if ( item )
8638 						item->setCheckState(column, cs);
8639 					item = qmc2VersionItemHash.value(machineName);
8640 					if ( item )
8641 						item->setCheckState(column, cs);
8642 					if ( wasTagged )
8643 						qmc2MachineList->numTaggedSets--;
8644 					else
8645 						qmc2MachineList->numTaggedSets++;
8646 					foreach (MachineListViewer *v, machineListViewers)
8647 						v->mainTagChanged(machineName, !wasTagged);
8648 					labelMachineListStatus->setText(qmc2MachineList->status());
8649 				}
8650 			}
8651 		}
8652 	}
8653 }
8654 
on_treeWidgetCategoryView_itemPressed(QTreeWidgetItem * item,int column)8655 void MainWindow::on_treeWidgetCategoryView_itemPressed(QTreeWidgetItem *item, int column)
8656 {
8657 	on_treeWidgetCategoryView_itemEntered(item, column);
8658 }
8659 
on_treeWidgetVersionView_itemEntered(QTreeWidgetItem * item,int column)8660 void MainWindow::on_treeWidgetVersionView_itemEntered(QTreeWidgetItem *item, int column)
8661 {
8662 	if ( column == QMC2_MACHINELIST_COLUMN_TAG ) {
8663 		if ( item->parent() ) {
8664 			if ( qApp->mouseButtons() == Qt::LeftButton && qApp->activeWindow() ) {
8665 				QPoint cPos = treeWidgetVersionView->viewport()->mapFromGlobal(QCursor::pos());
8666 				if ( treeWidgetVersionView->itemAt(cPos) == item ) {
8667 					Qt::CheckState cs = (item->checkState(column) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
8668 					bool wasTagged = (cs != Qt::Checked);
8669 					item->setCheckState(column, cs);
8670 					QString machineName(item->text(QMC2_MACHINELIST_COLUMN_NAME));
8671 					item = qmc2MachineListItemHash.value(machineName);
8672 					if ( item )
8673 						item->setCheckState(column, cs);
8674 					item = qmc2HierarchyItemHash.value(machineName);
8675 					if ( item )
8676 						item->setCheckState(column, cs);
8677 					item = qmc2CategoryItemHash.value(machineName);
8678 					if ( item )
8679 						item->setCheckState(column, cs);
8680 					if ( wasTagged )
8681 						qmc2MachineList->numTaggedSets--;
8682 					else
8683 						qmc2MachineList->numTaggedSets++;
8684 					foreach (MachineListViewer *v, machineListViewers)
8685 						v->mainTagChanged(machineName, !wasTagged);
8686 					labelMachineListStatus->setText(qmc2MachineList->status());
8687 				}
8688 			}
8689 		}
8690 	}
8691 }
8692 
on_treeWidgetVersionView_itemPressed(QTreeWidgetItem * item,int column)8693 void MainWindow::on_treeWidgetVersionView_itemPressed(QTreeWidgetItem *item, int column)
8694 {
8695 	on_treeWidgetVersionView_itemEntered(item, column);
8696 }
8697 
treeWidgetCategoryViewHeader_customContextMenuRequested(const QPoint & p)8698 void MainWindow::treeWidgetCategoryViewHeader_customContextMenuRequested(const QPoint &p)
8699 {
8700 	menuCategoryHeader->move(adjustedWidgetPosition(treeWidgetCategoryView->header()->viewport()->mapToGlobal(p), menuCategoryHeader));
8701 	menuCategoryHeader->show();
8702 }
8703 
actionCategoryHeader_triggered()8704 void MainWindow::actionCategoryHeader_triggered()
8705 {
8706 	QAction *action = (QAction *)sender();
8707 	int visibleColumns = 0;
8708 	for (int i = 0; i < treeWidgetCategoryView->columnCount(); i++) if ( !treeWidgetCategoryView->isColumnHidden(i) ) visibleColumns++;
8709 	if ( action ) {
8710 		if ( action->data().toInt() == QMC2_MACHINELIST_RESET ) {
8711 			treeWidgetCategoryView->setColumnHidden(QMC2_MACHINELIST_COLUMN_CATEGORY, true);
8712 			for (int i = 0; i < treeWidgetCategoryView->columnCount(); i++) {
8713 				if ( i == QMC2_MACHINELIST_COLUMN_VERSION ) {
8714 				       	if ( qmc2VersionInfoUsed )
8715 						treeWidgetCategoryView->setColumnHidden(i, false);
8716 				} else if ( i != QMC2_MACHINELIST_COLUMN_CATEGORY )
8717 					treeWidgetCategoryView->setColumnHidden(i, false);
8718 			}
8719 			treeWidgetCategoryView->header()->resizeSections(QHeaderView::Stretch);
8720 			foreach (QAction *a, menuCategoryHeader->actions())
8721 				if ( a->isCheckable() ) {
8722 					a->blockSignals(true);
8723 					a->setChecked(true);
8724 					a->blockSignals(false);
8725 				}
8726 			return;
8727 		}
8728 		bool visibility = true;
8729 		if ( action->isChecked() )
8730 			treeWidgetCategoryView->setColumnHidden(action->data().toInt(), false);
8731 		else if ( visibleColumns > 1 ) {
8732 			treeWidgetCategoryView->setColumnHidden(action->data().toInt(), true);
8733 			visibility = false;
8734 		}
8735 		action->blockSignals(true);
8736 		action->setChecked(visibility);
8737 		action->blockSignals(false);
8738 		QTimer::singleShot(0, this, SLOT(updateUserData()));
8739 	}
8740 }
8741 
treeWidgetVersionViewHeader_customContextMenuRequested(const QPoint & p)8742 void MainWindow::treeWidgetVersionViewHeader_customContextMenuRequested(const QPoint &p)
8743 {
8744 	menuVersionHeader->move(adjustedWidgetPosition(treeWidgetVersionView->header()->viewport()->mapToGlobal(p), menuVersionHeader));
8745 	menuVersionHeader->show();
8746 }
8747 
actionVersionHeader_triggered()8748 void MainWindow::actionVersionHeader_triggered()
8749 {
8750 	QAction *action = (QAction *)sender();
8751 	int visibleColumns = 0;
8752 	for (int i = 0; i < treeWidgetVersionView->columnCount(); i++) if ( !treeWidgetVersionView->isColumnHidden(i) ) visibleColumns++;
8753 	if ( action ) {
8754 		if ( action->data().toInt() == QMC2_MACHINELIST_RESET ) {
8755 			treeWidgetVersionView->setColumnHidden(QMC2_MACHINELIST_COLUMN_VERSION, true);
8756 			for (int i = 0; i < treeWidgetVersionView->columnCount(); i++) {
8757 				if ( i == QMC2_MACHINELIST_COLUMN_CATEGORY ) {
8758 				       	if ( qmc2CategoryInfoUsed )
8759 						treeWidgetVersionView->setColumnHidden(i, false);
8760 				} else if ( i != QMC2_MACHINELIST_COLUMN_VERSION )
8761 					treeWidgetVersionView->setColumnHidden(i, false);
8762 			}
8763 			treeWidgetVersionView->header()->resizeSections(QHeaderView::Stretch);
8764 			foreach (QAction *a, menuVersionHeader->actions())
8765 				if ( a->isCheckable() ) {
8766 					a->blockSignals(true);
8767 					a->setChecked(true);
8768 					a->blockSignals(false);
8769 				}
8770 			return;
8771 		}
8772 		bool visibility = true;
8773 		if ( action->isChecked() )
8774 			treeWidgetVersionView->setColumnHidden(action->data().toInt(), false);
8775 		else if ( visibleColumns > 1 ) {
8776 			treeWidgetVersionView->setColumnHidden(action->data().toInt(), true);
8777 			visibility = false;
8778 		}
8779 		action->blockSignals(true);
8780 		action->setChecked(visibility);
8781 		action->blockSignals(false);
8782 		QTimer::singleShot(0, this, SLOT(updateUserData()));
8783 	}
8784 }
8785 
on_actionPlayTagged_triggered(bool)8786 void MainWindow::on_actionPlayTagged_triggered(bool)
8787 {
8788 	progressBarMachineList->reset();
8789 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
8790 		progressBarMachineList->setFormat(tr("Play tagged - %p%"));
8791 	else
8792 		progressBarMachineList->setFormat("%p%");
8793 	progressBarMachineList->setRange(0, qmc2MachineList->numMachines);
8794 	qApp->processEvents();
8795 	int count = 0;
8796 	QTreeWidgetItem *oldCurrentItem = qmc2CurrentItem;
8797 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8798 	QTreeWidgetItem *item;
8799 	while ( it.hasNext() ) {
8800 		progressBarMachineList->setValue(count++);
8801 		it.next();
8802 		item = qmc2MachineListItemHash.value(it.key());
8803 		if ( item ) {
8804 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked ) {
8805 				qApp->processEvents();
8806 				qmc2CurrentItem = item;
8807 				on_actionPlay_triggered();
8808 			}
8809 		}
8810 	}
8811 	qmc2CurrentItem = oldCurrentItem;
8812 	progressBarMachineList->reset();
8813 }
8814 
on_actionPlayEmbeddedTagged_triggered(bool)8815 void MainWindow::on_actionPlayEmbeddedTagged_triggered(bool)
8816 {
8817 	progressBarMachineList->reset();
8818 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
8819 		progressBarMachineList->setFormat(tr("Play tagged - %p%"));
8820 	else
8821 		progressBarMachineList->setFormat("%p%");
8822 	progressBarMachineList->setRange(0, qmc2MachineList->numMachines);
8823 	qApp->processEvents();
8824 	int count = 0;
8825 	QTreeWidgetItem *oldCurrentItem = qmc2CurrentItem;
8826 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8827 	QTreeWidgetItem *item;
8828 	while ( it.hasNext() ) {
8829 		progressBarMachineList->setValue(count++);
8830 		it.next();
8831 		item = qmc2MachineListItemHash.value(it.key());
8832 		if ( item ) {
8833 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked ) {
8834 				qApp->processEvents();
8835 				qmc2CurrentItem = item;
8836 				qmc2StartEmbedded = true;
8837 				on_actionPlay_triggered();
8838 				QTest::qWait(2*QMC2_EMBED_DELAY);
8839 			}
8840 		}
8841 	}
8842 	qmc2CurrentItem = oldCurrentItem;
8843 	progressBarMachineList->reset();
8844 }
8845 
on_actionToFavoritesTagged_triggered(bool)8846 void MainWindow::on_actionToFavoritesTagged_triggered(bool)
8847 {
8848 	progressBarMachineList->reset();
8849 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
8850 		progressBarMachineList->setFormat(tr("Add favorites - %p%"));
8851 	else
8852 		progressBarMachineList->setFormat("%p%");
8853 	progressBarMachineList->setRange(0, qmc2MachineList->numMachines);
8854 	qApp->processEvents();
8855 	int count = 0;
8856 	QTreeWidgetItem *oldCurrentItem = qmc2CurrentItem;
8857 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8858 	QTreeWidgetItem *item;
8859 	while ( it.hasNext() ) {
8860 		progressBarMachineList->setValue(count++);
8861 		it.next();
8862 		item = qmc2MachineListItemHash.value(it.key());
8863 		if ( item ) {
8864 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked ) {
8865 				qApp->processEvents();
8866 				qmc2CurrentItem = item;
8867 				on_actionToFavorites_triggered();
8868 			}
8869 		}
8870 	}
8871 	qmc2CurrentItem = oldCurrentItem;
8872 	progressBarMachineList->reset();
8873 }
8874 
on_actionCheckROMStateTagged_triggered(bool)8875 void MainWindow::on_actionCheckROMStateTagged_triggered(bool)
8876 {
8877 	if ( isActiveState ) {
8878 		log(QMC2_LOG_FRONTEND, tr("please wait for current activity to finish and try again (this batch-mode operation can only run exclusively)"));
8879 		return;
8880 	}
8881 	if ( qmc2MachineList->numTaggedSets > QMC2_WARN_TAGGED_CHECKS_AMOUNT ) {
8882 		switch ( QMessageBox::question(this, tr("Confirm"), tr("It's likely much faster to do a full audit than to check %1 sets individually. Do you really want to continue?").arg(qmc2MachineList->numTaggedSets), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ) {
8883 			case QMessageBox::Yes:
8884 				break;
8885 			case QMessageBox::No:
8886 			default:
8887 				return;
8888 		}
8889 	}
8890 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8891 	QTreeWidgetItem *item;
8892 	qmc2LoadingInterrupted = false;
8893 	qmc2VerifyTaggedActive = true;
8894 	while ( it.hasNext() && !qmc2LoadingInterrupted ) {
8895 		it.next();
8896 		item = qmc2MachineListItemHash.value(it.key());
8897 		if ( item ) {
8898 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked ) {
8899 				qApp->processEvents();
8900 				qmc2CurrentItem = item;
8901 				on_actionCheckCurrentROM_triggered();
8902 				while ( qmc2VerifyActive && !qmc2LoadingInterrupted )
8903 					QTest::qWait(QMC2_TAGGEDROMCHECK_DELAY);
8904 			}
8905 		}
8906 	}
8907 	qmc2VerifyTaggedActive = false;
8908 }
8909 
on_actionAnalyseROMTagged_triggered(bool)8910 void MainWindow::on_actionAnalyseROMTagged_triggered(bool)
8911 {
8912 	if ( qmc2MachineList->numTaggedSets <= 0 )
8913 		return;
8914 	if ( isActiveState ) {
8915 		log(QMC2_LOG_FRONTEND, tr("please wait for current activity to finish and try again (this batch-mode operation can only run exclusively)"));
8916 		return;
8917 	}
8918 	QStringList setsToAnalyze;
8919 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8920 	QTreeWidgetItem *item;
8921 	while ( it.hasNext() ) {
8922 		it.next();
8923 		item = qmc2MachineListItemHash.value(it.key());
8924 		if ( item )
8925 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked )
8926 				setsToAnalyze << item->text(QMC2_MACHINELIST_COLUMN_NAME);
8927 	}
8928 	std::sort(setsToAnalyze.begin(), setsToAnalyze.end());
8929 	if ( !qmc2SystemROMAlyzer )
8930 		qmc2SystemROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SYSTEM);
8931 	qmc2SystemROMAlyzer->quickSearch = true;
8932 	qmc2SystemROMAlyzer->lineEditSets->setText(setsToAnalyze.join(" "));
8933 	if ( qmc2SystemROMAlyzer->isHidden() )
8934 		qmc2SystemROMAlyzer->show();
8935 	else if ( qmc2SystemROMAlyzer->isMinimized() )
8936 		qmc2SystemROMAlyzer->showNormal();
8937 	if ( qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabAnalyzer && qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabLog )
8938 		qmc2SystemROMAlyzer->tabWidgetAnalysis->setCurrentWidget(qmc2SystemROMAlyzer->tabAnalyzer);
8939 	QTimer::singleShot(0, qmc2SystemROMAlyzer, SLOT(raise()));
8940 	QTimer::singleShot(0, qmc2SystemROMAlyzer->pushButtonAnalyze, SLOT(animateClick()));
8941 }
8942 
on_actionRunRomToolTagged_triggered(bool)8943 void MainWindow::on_actionRunRomToolTagged_triggered(bool)
8944 {
8945 	if ( isActiveState ) {
8946 		log(QMC2_LOG_FRONTEND, tr("please wait for current activity to finish and try again (this batch-mode operation can only run exclusively)"));
8947 		return;
8948 	}
8949 	progressBarMachineList->reset();
8950 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
8951 		progressBarMachineList->setFormat(tr("ROM tool tagged - %p%"));
8952 	else
8953 		progressBarMachineList->setFormat("%p%");
8954 	progressBarMachineList->setRange(0, qmc2MachineList->numMachines);
8955 	qApp->processEvents();
8956 	int count = 0;
8957 	QTreeWidgetItem *oldCurrentItem = qmc2CurrentItem;
8958 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
8959 	QTreeWidgetItem *item;
8960 	while ( it.hasNext() && !qmc2LoadingInterrupted ) {
8961 		progressBarMachineList->setValue(count++);
8962 		it.next();
8963 		item = qmc2MachineListItemHash.value(it.key());
8964 		if ( item ) {
8965 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked ) {
8966 				qApp->processEvents();
8967 				qmc2CurrentItem = item;
8968 				on_actionRunRomTool_triggered();
8969 			}
8970 		}
8971 	}
8972 	qmc2CurrentItem = oldCurrentItem;
8973 	progressBarMachineList->reset();
8974 }
8975 
on_actionSetTag_triggered(bool)8976 void MainWindow::on_actionSetTag_triggered(bool)
8977 {
8978 	if ( !qmc2CurrentItem )
8979 		return;
8980 	bool wasUntagged = false;
8981 	QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
8982 	QTreeWidgetItem *item = qmc2MachineListItemHash.value(machineName);
8983 	if ( item ) {
8984 		wasUntagged = (item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Unchecked);
8985 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
8986 	}
8987 	item = qmc2HierarchyItemHash.value(machineName);
8988 	if ( item )
8989 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
8990 	item = qmc2CategoryItemHash.value(machineName);
8991 	if ( item )
8992 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
8993 	item = qmc2VersionItemHash.value(machineName);
8994 	if ( item )
8995 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
8996 	if ( wasUntagged ) {
8997 		qmc2MachineList->numTaggedSets++;
8998 		labelMachineListStatus->setText(qmc2MachineList->status());
8999 	}
9000 	foreach (MachineListViewer *v, machineListViewers)
9001 		v->mainTagChanged(machineName, true);
9002 }
9003 
on_actionUnsetTag_triggered(bool)9004 void MainWindow::on_actionUnsetTag_triggered(bool)
9005 {
9006 	if ( !qmc2CurrentItem )
9007 		return;
9008 	bool wasTagged = false;
9009 	QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
9010 	QTreeWidgetItem *item = qmc2MachineListItemHash.value(machineName);
9011 	if ( item ) {
9012 		wasTagged = (item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked);
9013 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9014 	}
9015 	item = qmc2HierarchyItemHash.value(machineName);
9016 	if ( item )
9017 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9018 	item = qmc2CategoryItemHash.value(machineName);
9019 	if ( item )
9020 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9021 	item = qmc2VersionItemHash.value(machineName);
9022 	if ( item )
9023 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9024 	if ( wasTagged ) {
9025 		qmc2MachineList->numTaggedSets--;
9026 		labelMachineListStatus->setText(qmc2MachineList->status());
9027 	}
9028 	foreach (MachineListViewer *v, machineListViewers)
9029 		v->mainTagChanged(machineName, false);
9030 }
9031 
on_actionToggleTag_triggered(bool)9032 void MainWindow::on_actionToggleTag_triggered(bool)
9033 {
9034 	if ( !qmc2CurrentItem )
9035 		return;
9036 	QString machineName(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
9037 	QTreeWidgetItem *item = qmc2MachineListItemHash.value(machineName);
9038 	if ( item ) {
9039 		Qt::CheckState cs = (item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
9040 		bool wasTagged = (cs != Qt::Checked);
9041 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9042 		item = qmc2HierarchyItemHash.value(machineName);
9043 		if ( item )
9044 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9045 		item = qmc2CategoryItemHash.value(machineName);
9046 		if ( item )
9047 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9048 		item = qmc2VersionItemHash.value(machineName);
9049 		if ( item )
9050 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9051 		if ( wasTagged )
9052 			qmc2MachineList->numTaggedSets--;
9053 		else
9054 			qmc2MachineList->numTaggedSets++;
9055 		labelMachineListStatus->setText(qmc2MachineList->status());
9056 		foreach (MachineListViewer *v, machineListViewers)
9057 			v->mainTagChanged(machineName, !wasTagged);
9058 	}
9059 }
9060 
on_actionToggleTagCursorDown_triggered(bool)9061 void MainWindow::on_actionToggleTagCursorDown_triggered(bool)
9062 {
9063 	if ( !qmc2CurrentItem )
9064 		return;
9065 	QWidget *focusWidget = qApp->focusWidget();
9066 	if ( qmc2ActiveViews.contains(focusWidget) ) {
9067 		bool doToggle = true;
9068 		if ( focusWidget == treeWidgetMachineList ) {
9069 			QTreeWidgetItem *item = treeWidgetMachineList->selectedItems()[0];
9070 			if ( item->parent() )
9071 				doToggle = false;
9072 			while ( item->parent() )
9073 				item = item->parent();
9074 			qmc2CurrentItem = item;
9075 		} else if ( focusWidget == treeWidgetCategoryView ) {
9076 			QTreeWidgetItem *item = treeWidgetCategoryView->selectedItems()[0];
9077 			if ( !item->parent() )
9078 				doToggle = false;
9079 		} else if ( focusWidget == treeWidgetVersionView ) {
9080 			QTreeWidgetItem *item = treeWidgetVersionView->selectedItems()[0];
9081 			if ( !item->parent() )
9082 				doToggle = false;
9083 		}
9084 		if ( doToggle )
9085 			on_actionToggleTag_triggered();
9086 		QKeyEvent *pressEv = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
9087 		QKeyEvent *releaseEv = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier);
9088 		qApp->postEvent(focusWidget, pressEv);
9089 		qApp->postEvent(focusWidget, releaseEv);
9090 	}
9091 }
9092 
on_actionToggleTagCursorUp_triggered(bool)9093 void MainWindow::on_actionToggleTagCursorUp_triggered(bool)
9094 {
9095 	if ( !qmc2CurrentItem )
9096 		return;
9097 	QWidget *focusWidget = qApp->focusWidget();
9098 	if ( qmc2ActiveViews.contains(focusWidget) ) {
9099 		bool doToggle = true;
9100 		if ( focusWidget == treeWidgetMachineList ) {
9101 			QTreeWidgetItem *item = treeWidgetMachineList->selectedItems()[0];
9102 			if ( item->parent() )
9103 				doToggle = false;
9104 			while ( item->parent() )
9105 				item = item->parent();
9106 			qmc2CurrentItem = item;
9107 		} else if ( focusWidget == treeWidgetCategoryView ) {
9108 			QTreeWidgetItem *item = treeWidgetCategoryView->selectedItems()[0];
9109 			if ( !item->parent() )
9110 				doToggle = false;
9111 		} else if ( focusWidget == treeWidgetVersionView ) {
9112 			QTreeWidgetItem *item = treeWidgetVersionView->selectedItems()[0];
9113 			if ( !item->parent() )
9114 				doToggle = false;
9115 		}
9116 		if ( doToggle )
9117 			on_actionToggleTag_triggered();
9118 		QKeyEvent *pressEv = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
9119 		QKeyEvent *releaseEv = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier);
9120 		qApp->postEvent(focusWidget, pressEv);
9121 		qApp->postEvent(focusWidget, releaseEv);
9122 	}
9123 }
9124 
showLoadAnim(QString text,bool enable)9125 void MainWindow::showLoadAnim(QString text, bool enable)
9126 {
9127 	if ( enable ) {
9128 		treeWidgetMachineList->setVisible(false);
9129 		((AspectRatioLabel *)labelLoadingMachineList)->setLabelText(text);
9130 		labelLoadingMachineList->setVisible(true);
9131 		treeWidgetHierarchy->setVisible(false);
9132 		((AspectRatioLabel *)labelLoadingHierarchy)->setLabelText(text);
9133 		labelLoadingHierarchy->setVisible(true);
9134 		treeWidgetCategoryView->setVisible(false);
9135 		((AspectRatioLabel *)labelCreatingCategoryView)->setLabelText(text);
9136 		labelCreatingCategoryView->setVisible(true);
9137 		treeWidgetVersionView->setVisible(false);
9138 		((AspectRatioLabel *)labelCreatingVersionView)->setLabelText(text);
9139 		labelCreatingVersionView->setVisible(true);
9140 		attachedViewsWidget->setVisible(false);
9141 		((AspectRatioLabel *)labelLoadingAttachedViews)->setLabelText(text);
9142 		labelLoadingAttachedViews->setVisible(true);
9143 		if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ShowLoadingAnimation", true).toBool() )
9144 			loadAnimMovie->start();
9145 	} else {
9146 		loadAnimMovie->setPaused(true);
9147 		treeWidgetMachineList->setVisible(true);
9148 		labelLoadingMachineList->setVisible(false);
9149 		treeWidgetHierarchy->setVisible(true);
9150 		labelLoadingHierarchy->setVisible(false);
9151 		treeWidgetCategoryView->setVisible(true);
9152 		labelCreatingCategoryView->setVisible(false);
9153 		treeWidgetVersionView->setVisible(true);
9154 		labelCreatingVersionView->setVisible(false);
9155 		attachedViewsWidget->setVisible(true);
9156 		labelLoadingAttachedViews->setVisible(false);
9157 	}
9158 	qApp->processEvents();
9159 }
9160 
on_actionTagAll_triggered(bool)9161 void MainWindow::on_actionTagAll_triggered(bool)
9162 {
9163 	if ( qmc2ReloadActive )
9164 		return;
9165 	progressBarMachineList->reset();
9166 	QString oldFormat = progressBarMachineList->format();
9167 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9168 		progressBarMachineList->setFormat(tr("Tag - %p%"));
9169 	else
9170 		progressBarMachineList->setFormat("%p%");
9171 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9172 	showLoadAnim(tr("Tagging, please wait..."));
9173 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9174 	QTreeWidgetItem *item;
9175 	QString id;
9176 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9177 	int count = 0;
9178 	while ( it.hasNext() ) {
9179 		it.next();
9180 		id = it.key();
9181 		item = qmc2MachineListItemHash.value(id);
9182 		if ( !item )
9183 			continue;
9184 		if ( item )
9185 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9186 		item = qmc2HierarchyItemHash.value(id);
9187 		if ( item )
9188 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9189 		item = qmc2CategoryItemHash.value(id);
9190 		if ( item )
9191 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9192 		item = qmc2VersionItemHash.value(id);
9193 		if ( item )
9194 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9195 		qmc2MachineList->numTaggedSets++;
9196 		foreach (MachineListViewer *v, machineListViewers)
9197 			v->mainTagChanged(id, true);
9198 		if ( count++ % taggingResponse == 0 ) {
9199 			progressBarMachineList->setValue(count);
9200 			labelMachineListStatus->setText(qmc2MachineList->status());
9201 			qApp->processEvents();
9202 		}
9203 	}
9204 	qmc2MachineList->numTaggedSets = qmc2MachineList->numMachines;
9205 	progressBarMachineList->setValue(count);
9206 	labelMachineListStatus->setText(qmc2MachineList->status());
9207 	hideLoadAnim();
9208 	progressBarMachineList->setFormat(oldFormat);
9209 	progressBarMachineList->reset();
9210 }
9211 
on_actionUntagAll_triggered(bool)9212 void MainWindow::on_actionUntagAll_triggered(bool)
9213 {
9214 	if ( qmc2ReloadActive )
9215 		return;
9216 	progressBarMachineList->reset();
9217 	QString oldFormat = progressBarMachineList->format();
9218 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9219 		progressBarMachineList->setFormat(tr("Untag - %p%"));
9220 	else
9221 		progressBarMachineList->setFormat("%p%");
9222 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9223 	showLoadAnim(tr("Untagging, please wait..."));
9224 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9225 	QTreeWidgetItem *item;
9226 	QString id;
9227 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9228 	int count = 0;
9229 	while ( it.hasNext() ) {
9230 		it.next();
9231 		id = it.key();
9232 		item = qmc2MachineListItemHash.value(id);
9233 		if ( !item )
9234 			continue;
9235 		if ( item )
9236 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9237 		item = qmc2HierarchyItemHash.value(id);
9238 		if ( item )
9239 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9240 		item = qmc2CategoryItemHash.value(id);
9241 		if ( item )
9242 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9243 		item = qmc2VersionItemHash.value(id);
9244 		if ( item )
9245 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9246 		qmc2MachineList->numTaggedSets--;
9247 		foreach (MachineListViewer *v, machineListViewers)
9248 			v->mainTagChanged(id, false);
9249 		if ( count++ % taggingResponse == 0 ) {
9250 			progressBarMachineList->setValue(count);
9251 			labelMachineListStatus->setText(qmc2MachineList->status());
9252 			qApp->processEvents();
9253 		}
9254 	}
9255 	qmc2MachineList->numTaggedSets = 0;
9256 	progressBarMachineList->setValue(count);
9257 	labelMachineListStatus->setText(qmc2MachineList->status());
9258 	hideLoadAnim();
9259 	progressBarMachineList->setFormat(oldFormat);
9260 	progressBarMachineList->reset();
9261 }
9262 
on_actionInvertTags_triggered(bool)9263 void MainWindow::on_actionInvertTags_triggered(bool)
9264 {
9265 	if ( qmc2ReloadActive )
9266 		return;
9267 	progressBarMachineList->reset();
9268 	QString oldFormat = progressBarMachineList->format();
9269 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9270 		progressBarMachineList->setFormat(tr("Invert tag - %p%"));
9271 	else
9272 		progressBarMachineList->setFormat("%p%");
9273 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9274 	showLoadAnim(tr("Inverting tags, please wait..."));
9275 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9276 	QTreeWidgetItem *item;
9277 	QString id;
9278 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9279 	int count = 0;
9280 	while ( it.hasNext() ) {
9281 		it.next();
9282 		id = it.key();
9283 		item = qmc2MachineListItemHash.value(id);
9284 		if ( !item )
9285 			continue;
9286 		Qt::CheckState cs = (item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
9287 		bool wasTagged = (cs != Qt::Checked);
9288 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9289 		item = qmc2HierarchyItemHash.value(id);
9290 		if ( item )
9291 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9292 		item = qmc2CategoryItemHash.value(id);
9293 		if ( item )
9294 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9295 		item = qmc2VersionItemHash.value(id);
9296 		if ( item )
9297 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9298 		if ( wasTagged )
9299 			qmc2MachineList->numTaggedSets--;
9300 		else
9301 			qmc2MachineList->numTaggedSets++;
9302 		foreach (MachineListViewer *v, machineListViewers)
9303 			v->mainTagChanged(id, !wasTagged);
9304 		if ( count++ % taggingResponse == 0 ) {
9305 			progressBarMachineList->setValue(count);
9306 			labelMachineListStatus->setText(qmc2MachineList->status());
9307 			qApp->processEvents();
9308 		}
9309 	}
9310 	progressBarMachineList->setValue(count);
9311 	labelMachineListStatus->setText(qmc2MachineList->status());
9312 	hideLoadAnim();
9313 	progressBarMachineList->setFormat(oldFormat);
9314 	progressBarMachineList->reset();
9315 }
9316 
on_actionTagVisible_triggered(bool)9317 void MainWindow::on_actionTagVisible_triggered(bool)
9318 {
9319 	if ( qmc2ReloadActive )
9320 		return;
9321 	progressBarMachineList->reset();
9322 	QString oldFormat = progressBarMachineList->format();
9323 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9324 		progressBarMachineList->setFormat(tr("Tag - %p%"));
9325 	else
9326 		progressBarMachineList->setFormat("%p%");
9327 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9328 	showLoadAnim(tr("Tagging, please wait..."));
9329 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9330 	QTreeWidgetItem *item;
9331 	QString id;
9332 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9333 	int count = 0;
9334 	while ( it.hasNext() ) {
9335 		it.next();
9336 		id = it.key();
9337 		item = qmc2MachineListItemHash.value(id);
9338 		if ( !item )
9339 			continue;
9340 		if ( item->isHidden() )
9341 			continue;
9342 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9343 		item = qmc2HierarchyItemHash.value(id);
9344 		if ( item )
9345 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9346 		item = qmc2CategoryItemHash.value(id);
9347 		if ( item )
9348 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9349 		item = qmc2VersionItemHash.value(id);
9350 		if ( item )
9351 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Checked);
9352 		qmc2MachineList->numTaggedSets++;
9353 		foreach (MachineListViewer *v, machineListViewers)
9354 			v->mainTagChanged(id, true);
9355 		if ( count++ % taggingResponse == 0 ) {
9356 			progressBarMachineList->setValue(count);
9357 			labelMachineListStatus->setText(qmc2MachineList->status());
9358 			qApp->processEvents();
9359 		}
9360 	}
9361 	progressBarMachineList->setValue(count);
9362 	labelMachineListStatus->setText(qmc2MachineList->status());
9363 	hideLoadAnim();
9364 	progressBarMachineList->setFormat(oldFormat);
9365 	progressBarMachineList->reset();
9366 }
9367 
on_actionUntagVisible_triggered(bool)9368 void MainWindow::on_actionUntagVisible_triggered(bool)
9369 {
9370 	if ( qmc2ReloadActive )
9371 		return;
9372 	progressBarMachineList->reset();
9373 	QString oldFormat = progressBarMachineList->format();
9374 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9375 		progressBarMachineList->setFormat(tr("Untag - %p%"));
9376 	else
9377 		progressBarMachineList->setFormat("%p%");
9378 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9379 	showLoadAnim(tr("Untagging, please wait..."));
9380 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9381 	QTreeWidgetItem *item;
9382 	QString id;
9383 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9384 	int count = 0;
9385 	while ( it.hasNext() ) {
9386 		it.next();
9387 		id = it.key();
9388 		item = qmc2MachineListItemHash.value(id);
9389 		if ( !item )
9390 			continue;
9391 		if ( item->isHidden() )
9392 			continue;
9393 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9394 		item = qmc2HierarchyItemHash.value(id);
9395 		if ( item )
9396 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9397 		item = qmc2CategoryItemHash.value(id);
9398 		if ( item )
9399 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9400 		item = qmc2VersionItemHash.value(id);
9401 		if ( item )
9402 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, Qt::Unchecked);
9403 		qmc2MachineList->numTaggedSets--;
9404 		foreach (MachineListViewer *v, machineListViewers)
9405 			v->mainTagChanged(id, false);
9406 		if ( count++ % taggingResponse == 0 ) {
9407 			progressBarMachineList->setValue(count);
9408 			labelMachineListStatus->setText(qmc2MachineList->status());
9409 			qApp->processEvents();
9410 		}
9411 	}
9412 	progressBarMachineList->setValue(count);
9413 	labelMachineListStatus->setText(qmc2MachineList->status());
9414 	hideLoadAnim();
9415 	progressBarMachineList->setFormat(oldFormat);
9416 	progressBarMachineList->reset();
9417 }
9418 
on_actionInvertVisibleTags_triggered(bool)9419 void MainWindow::on_actionInvertVisibleTags_triggered(bool)
9420 {
9421 	if ( qmc2ReloadActive )
9422 		return;
9423 	progressBarMachineList->reset();
9424 	QString oldFormat = progressBarMachineList->format();
9425 	if ( qmc2Config->value(QMC2_FRONTEND_PREFIX + "GUI/ProgressTexts").toBool() )
9426 		progressBarMachineList->setFormat(tr("Invert tag - %p%"));
9427 	else
9428 		progressBarMachineList->setFormat("%p%");
9429 	progressBarMachineList->setRange(0, qmc2MachineList->numTotalMachines);
9430 	showLoadAnim(tr("Inverting tags, please wait..."));
9431 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9432 	QTreeWidgetItem *item;
9433 	QString id;
9434 	int taggingResponse = qmc2MachineListItemHash.count() / QMC2_TAGGING_UPDATES;
9435 	int count = 0;
9436 	while ( it.hasNext() ) {
9437 		it.next();
9438 		id = it.key();
9439 		item = qmc2MachineListItemHash.value(id);
9440 		if ( !item )
9441 			continue;
9442 		if ( item->isHidden() )
9443 			continue;
9444 		Qt::CheckState cs = (item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Unchecked ? Qt::Checked : Qt::Unchecked);
9445 		bool wasTagged = (cs != Qt::Checked);
9446 		item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9447 		item = qmc2HierarchyItemHash.value(id);
9448 		if ( item )
9449 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9450 		item = qmc2CategoryItemHash.value(id);
9451 		if ( item )
9452 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9453 		item = qmc2VersionItemHash.value(id);
9454 		if ( item )
9455 			item->setCheckState(QMC2_MACHINELIST_COLUMN_TAG, cs);
9456 		if ( wasTagged )
9457 			qmc2MachineList->numTaggedSets--;
9458 		else
9459 			qmc2MachineList->numTaggedSets++;
9460 		foreach (MachineListViewer *v, machineListViewers)
9461 			v->mainTagChanged(id, !wasTagged);
9462 		if ( count++ % taggingResponse == 0 ) {
9463 			progressBarMachineList->setValue(count);
9464 			labelMachineListStatus->setText(qmc2MachineList->status());
9465 			qApp->processEvents();
9466 		}
9467 	}
9468 	progressBarMachineList->setValue(count);
9469 	labelMachineListStatus->setText(qmc2MachineList->status());
9470 	hideLoadAnim();
9471 	progressBarMachineList->setFormat(oldFormat);
9472 	progressBarMachineList->reset();
9473 }
9474 
commonWebSearch(QString baseUrl,QTreeWidgetItem * item)9475 void MainWindow::commonWebSearch(QString baseUrl, QTreeWidgetItem *item)
9476 {
9477 	if ( !item )
9478 		return;
9479 	QString manu(item->text(QMC2_MACHINELIST_COLUMN_MANU));
9480 	QString searchPattern;
9481 	if ( manu.compare(MachineList::trQuestionMark) != 0 )
9482 		searchPattern = item->text(QMC2_MACHINELIST_COLUMN_MACHINE) + " " + manu;
9483 	else
9484 		searchPattern = item->text(QMC2_MACHINELIST_COLUMN_MACHINE);
9485 	searchPattern = searchPattern.replace(QRegExp("\\((.*)\\)"), "\\1").replace(QRegExp("[\\\\,\\.\\;\\:\\'\\/\\(\\)\\[\\]\\{\\}]"), " ").replace("&", "%26").replace(" - ", " ").simplified().trimmed();
9486 	QStringList wordList(searchPattern.split(' ', QString::SkipEmptyParts));
9487 	wordList.removeAll("<unknown>");
9488 	wordList.removeAll("<generic>");
9489 	wordList.removeDuplicates();
9490 	QString url(wordList.join("+"));
9491 	url.prepend(baseUrl);
9492 	if ( actionSearchInternalBrowser->isChecked() ) {
9493 		MiniWebBrowser *webBrowser = new MiniWebBrowser(0);
9494 		webBrowser->homeUrl = QUrl::fromUserInput(url);
9495 		webBrowser->setAttribute(Qt::WA_DeleteOnClose);
9496 		if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "WebBrowser/Geometry") )
9497 			webBrowser->restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "WebBrowser/Geometry").toByteArray());
9498 		else {
9499 			webBrowser->adjustSize();
9500 			webBrowser->move(QApplication::desktop()->screen()->rect().center() - webBrowser->rect().center());
9501 		}
9502 		connect(webBrowser->webViewBrowser->page(), SIGNAL(windowCloseRequested()), webBrowser, SLOT(close()));
9503 		webBrowser->show();
9504 		webBrowser->webViewBrowser->load(webBrowser->homeUrl);
9505 	} else
9506 		QDesktopServices::openUrl(QUrl::fromUserInput(url));
9507 }
9508 
on_actionSearchDuckDuckGo_triggered(bool)9509 void MainWindow::on_actionSearchDuckDuckGo_triggered(bool)
9510 {
9511 	commonWebSearch("http://duckduckgo.com/?q=", qmc2CurrentItem);
9512 }
9513 
on_actionSearchGoogle_triggered(bool)9514 void MainWindow::on_actionSearchGoogle_triggered(bool)
9515 {
9516 	commonWebSearch("http://www.google.com/search?q=", qmc2CurrentItem);
9517 }
9518 
on_actionSearchWikipedia_triggered(bool)9519 void MainWindow::on_actionSearchWikipedia_triggered(bool)
9520 {
9521 	commonWebSearch("http://en.wikipedia.org/wiki/Special:Search?search=", qmc2CurrentItem);
9522 }
9523 
on_actionSearchYandex_triggered(bool)9524 void MainWindow::on_actionSearchYandex_triggered(bool)
9525 {
9526 	commonWebSearch("http://www.yandex.com/yandsearch?text=", qmc2CurrentItem);
9527 }
9528 
on_actionSearchInternalBrowser_triggered(bool checked)9529 void MainWindow::on_actionSearchInternalBrowser_triggered(bool checked)
9530 {
9531 	if ( checked )
9532 		actionSearchInternalBrowser->setText(tr("Internal browser"));
9533 	else
9534 		actionSearchInternalBrowser->setText(tr("External browser"));
9535 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "WebSearch/InternalBrowser", checked);
9536 }
9537 
on_actionManualInternalViewer_triggered(bool checked)9538 void MainWindow::on_actionManualInternalViewer_triggered(bool checked)
9539 {
9540 	if ( checked )
9541 		actionManualInternalViewer->setText(tr("Internal PDF viewer"));
9542 	else
9543 		actionManualInternalViewer->setText(tr("External PDF viewer"));
9544 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "PdfViewer/Internal", checked);
9545 }
9546 
on_actionManualOpenInViewer_triggered(bool)9547 void MainWindow::on_actionManualOpenInViewer_triggered(bool)
9548 {
9549 	if ( !qmc2CurrentItem )
9550 		return;
9551 	QStringList manualPaths(userDataDb->systemManualPaths(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)));
9552 	if ( manualPaths.isEmpty() ) {
9553 		QString parentName(qmc2ParentHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)));
9554 		if ( !parentName.isEmpty() )
9555 			manualPaths = userDataDb->systemManualPaths(parentName);
9556 	}
9557 	if ( manualPaths.count() > 1 ) {
9558 		ItemSelector itemSelector(this, manualPaths);
9559 		itemSelector.setWindowTitle(tr("Manual selection"));
9560 		itemSelector.labelMessage->setText(tr("Multiple PDF manuals exist. Select the ones you want to open:"));
9561 		itemSelector.listWidgetItems->setSelectionMode(QAbstractItemView::ExtendedSelection);
9562 		if ( itemSelector.exec() != QDialog::Rejected ) {
9563 			QList<QListWidgetItem *> itemList(itemSelector.listWidgetItems->selectedItems());
9564 			for (int i = 0; i < itemList.count(); i++) {
9565 				QFileInfo fi(itemList.at(i)->text());
9566 				if ( actionManualInternalViewer->isChecked() )
9567 					viewPdf(fi.absoluteFilePath());
9568 				else
9569 					QDesktopServices::openUrl(QUrl::fromUserInput(fi.absoluteFilePath()));
9570 			}
9571 		}
9572 	} else if ( manualPaths.count() > 0 ) {
9573 		QFileInfo fi(manualPaths.first());
9574 		if ( actionManualInternalViewer->isChecked() )
9575 			viewPdf(fi.absoluteFilePath());
9576 		else
9577 			QDesktopServices::openUrl(QUrl::fromUserInput(fi.absoluteFilePath()));
9578 	}
9579 }
9580 
checkSystemManualAvailability()9581 void MainWindow::checkSystemManualAvailability()
9582 {
9583 	if ( !qmc2CurrentItem ) {
9584 		actionManualOpenInViewer->setEnabled(false);
9585 		actionManualOpenInViewer->setIcon(QIcon(QString::fromUtf8(":/data/img/no_book.png")));
9586 		return;
9587 	}
9588 	bool enable = !userDataDb->systemManualPaths(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)).isEmpty();
9589 	if ( !enable ) {
9590 		QString parentName(qmc2ParentHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME)));
9591 		if ( !parentName.isEmpty() )
9592 			enable = !userDataDb->systemManualPaths(parentName).isEmpty();
9593 	}
9594 	actionManualOpenInViewer->setEnabled(enable);
9595 	if ( enable )
9596 		actionManualOpenInViewer->setIcon(QIcon(QString::fromUtf8(":/data/img/book.png")));
9597 	else
9598 		actionManualOpenInViewer->setIcon(QIcon(QString::fromUtf8(":/data/img/no_book.png")));
9599 }
9600 
on_actionRebuildROMTagged_triggered(bool)9601 void MainWindow::on_actionRebuildROMTagged_triggered(bool)
9602 {
9603 	if ( qmc2MachineList->numTaggedSets <= 0 )
9604 		return;
9605 
9606 	if ( isActiveState ) {
9607 		log(QMC2_LOG_FRONTEND, tr("please wait for current activity to finish and try again (this batch-mode operation can only run exclusively)"));
9608 		return;
9609 	}
9610 
9611 	if ( qmc2SystemROMAlyzer && qmc2SystemROMAlyzer->rebuilderActive() ) {
9612 		log(QMC2_LOG_FRONTEND, tr("please wait for ROMAlyzer to finish the current rebuild and try again"));
9613 		return;
9614 	}
9615 
9616 	QStringList setsToRebuild;
9617 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
9618 	QTreeWidgetItem *item;
9619 	while ( it.hasNext() ) {
9620 		it.next();
9621 		item = qmc2MachineListItemHash.value(it.key());
9622 		if ( item )
9623 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked )
9624 				setsToRebuild << item->text(QMC2_MACHINELIST_COLUMN_NAME);
9625 	}
9626 
9627 	std::sort(setsToRebuild.begin(), setsToRebuild.end());
9628 
9629 	bool initial = false;
9630 	if ( !qmc2SystemROMAlyzer ) {
9631 		qmc2SystemROMAlyzer = new ROMAlyzer(0, QMC2_ROMALYZER_MODE_SYSTEM);
9632 		initial = true;
9633 	}
9634 
9635 	if ( qmc2SystemROMAlyzer->tabWidgetAnalysis->currentWidget() != qmc2SystemROMAlyzer->tabCollectionRebuilder )
9636 		qmc2SystemROMAlyzer->tabWidgetAnalysis->setCurrentWidget(qmc2SystemROMAlyzer->tabCollectionRebuilder);
9637 
9638 	if ( qmc2SystemROMAlyzer->isHidden() )
9639 		qmc2SystemROMAlyzer->show();
9640 	else if ( qmc2SystemROMAlyzer->isMinimized() )
9641 		qmc2SystemROMAlyzer->showNormal();
9642 
9643 	QTimer::singleShot(0, qmc2SystemROMAlyzer, SLOT(raise()));
9644 
9645 	CollectionRebuilder *cr = qmc2SystemROMAlyzer->collectionRebuilder();
9646 	if ( cr ) {
9647 		cr->comboBoxXmlSource->setCurrentIndex(0);
9648 		cr->setIgnoreCheckpoint(true);
9649 		cr->checkBoxFilterExpression->setChecked(true);
9650 		cr->comboBoxFilterSyntax->setCurrentIndex(0);
9651 		cr->comboBoxFilterType->setCurrentIndex(0);
9652 		cr->toolButtonExactMatch->setChecked(true);
9653 		cr->checkBoxFilterStates->setChecked(false);
9654 		cr->lineEditFilterExpression->setText(setsToRebuild.join("|"));
9655 		if ( !initial )
9656 			cr->plainTextEditLog->clear();
9657 		QTimer::singleShot(0, cr->pushButtonStartStop, SLOT(click()));
9658 	}
9659 }
9660 
9661 // note: - this routine is far from "elegant" but basically works (there may be minor conversion "bugs", though, depending on the quality of the wiki source data)
9662 //       - if someone knows a CLEAN wiki2html converter that's not "bloated" and written in C/C++ (and legally redistributable open source code), please let us know!
messWikiToHtml(QString & wikiText)9663 QString &MainWindow::messWikiToHtml(QString &wikiText)
9664 {
9665 	int ulLevel = 0;
9666 	int olLevel = 0;
9667 	bool tableOpen = false;
9668 	bool preOn = false;
9669 	bool codeOn = false;
9670 	int preCounter = 0;
9671 	QStringList wikiLines(wikiText.split("<p>"));
9672 	wikiText.clear();
9673 	foreach (QString wikiLine, wikiLines) {
9674 		QString wikiLineTrimmed = wikiLine.trimmed();
9675 		if ( wikiLine.indexOf(QRegExp("\\s*<code>")) == 0 ) {
9676 			codeOn = true;
9677 			continue;
9678 		}
9679 		if ( wikiLine.indexOf(QRegExp("\\s*</code>")) == 0 )
9680 			codeOn = false;
9681 		bool listDetected = ( (wikiLineTrimmed.startsWith("* ") && wikiLine[wikiLine.indexOf("*") + 2] != ' ') || wikiLineTrimmed.startsWith("- ") );
9682 		if ( wikiLine == "  * " || wikiLine == "  - " || wikiLine == "  *" || wikiLine == "  -" ) continue; // this is an "artifact"... ignore :)
9683 		if ( !listDetected && (wikiLine.startsWith("  ") || codeOn) ) {
9684 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9685 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9686 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9687 			if ( wikiLine == "  "  && preCounter == 0 ) {
9688 				preCounter++;
9689 				wikiText += "\n";
9690 				continue;
9691 			}
9692 			if ( !preOn ) {
9693 				wikiText += "<p><table border=\"1\"><tr><td><pre>";
9694 				preOn = true;
9695 			}
9696 			if ( wikiLine == "  " ) {
9697 				wikiText += "\n";
9698 				continue;
9699 			}
9700 		} else if ( preOn ) {
9701 			preCounter++;
9702 			wikiText += "</pre></td></tr></table><p>";
9703 			preOn = codeOn = false;
9704 		}
9705 		int listDepth = 0;
9706 		if ( listDetected ) listDepth = wikiLine.indexOf(QRegExp("[\\-\\*]")) / 2;
9707 		if ( !preOn ) {
9708 			wikiLine = wikiLineTrimmed;
9709 			preCounter = 0;
9710 		}
9711 		if ( wikiLine.isEmpty() )
9712 			continue;
9713 		wikiLine.replace("<", "&lt;").replace(">", "&gt;");
9714 		if ( wikiLine.startsWith("//") && wikiLine.endsWith("//") ) {
9715 			wikiLine.replace(0, 2, "<i>");
9716 			wikiLine.replace(wikiLine.length() - 2, 2, "</i>");
9717 		}
9718 		foreach (QString snippet, wikiLine.split("//")) {
9719 			if ( snippet.indexOf(QRegExp("^.*(http:|https:|ftp:)$")) < 0 )
9720 				wikiLine.replace(QString("//%1//").arg(snippet), QString("<i>%1</i>").arg(snippet));
9721 		}
9722 		wikiLine.replace(QRegExp("\\*\\*(.*)\\*\\*"), "<b>\\1</b>");
9723 		wikiLine.replace(QRegExp("__(.*)__"), "<u>\\1</u>");
9724 		wikiLine.replace(QRegExp("\\[\\[wp>([^\\]]*)\\]\\]"), QLatin1String("\\1 -- http://en.wikipedia.org/wiki/\\1"));
9725 		foreach (QString snippet, wikiLine.split("[[")) {
9726 			if ( snippet.indexOf(QRegExp("\\]\\]|\\|")) > 0 ) {
9727 				QStringList subSnippets(snippet.split(QRegExp("\\]\\]|\\|")));
9728 				wikiLine.replace(QString("[[%1]]").arg(snippet), subSnippets[0]);
9729 			}
9730 		}
9731 		wikiLine.replace(QRegExp(QString("((http|https|ftp)://%1)").arg(urlSectionRegExp)), QLatin1String("<a href=\"\\1\">\\1</a>"));
9732 		if ( wikiLine.startsWith("&lt;h2&gt;======") && wikiLine.endsWith("======&lt;/h2&gt;") ) {
9733 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9734 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9735 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9736 			wikiText += "<h2>" + wikiLine.mid(16, wikiLine.length() - 33) + "</h2>";
9737 		} else if ( wikiLine.startsWith("=====") && wikiLine.endsWith("=====") ) {
9738 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9739 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9740 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9741 			wikiText += "<h3>" + wikiLine.mid(6, wikiLine.length() - 12) + "</h3>";
9742 		} else if ( wikiLine.startsWith("====") && wikiLine.endsWith("====") ) {
9743 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9744 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9745 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9746 			wikiText += "<h4>" + wikiLine.mid(5, wikiLine.length() - 10) + "</h4>";
9747 		} else if ( wikiLine.startsWith("===") && wikiLine.endsWith("===") ) {
9748 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9749 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9750 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9751 			wikiText += "<b>" + wikiLine.mid(4, wikiLine.length() - 8) + "</b>";
9752 		} else if ( wikiLine.startsWith("==") && wikiLine.endsWith("==") ) {
9753 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9754 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9755 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9756 			wikiText += "<b>" + wikiLine.mid(3, wikiLine.length() - 6) + "</b>";
9757 		} else if ( wikiLine.indexOf(QRegExp("\\* \\S")) == 0 ) {
9758 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9759 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9760 			if ( listDepth > ulLevel ) {
9761 				wikiText += "<ul style=\"list-style-type:square;\">";
9762 				ulLevel++;
9763 			} else if ( listDepth < ulLevel ) {
9764 				wikiText += "</ul>";
9765 				ulLevel--;
9766 			}
9767 			wikiText += "<li>" + wikiLine.mid(2) + "</li>";
9768 		} else if ( wikiLine.indexOf(QRegExp("\\- \\S")) == 0 ) {
9769 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9770 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9771 			if ( listDepth > olLevel ) {
9772 				wikiText += "<ol style=\"list-style-type:decimal;\">";
9773 				olLevel++;
9774 			} else if ( listDepth < olLevel ) {
9775 				wikiText += "</ol>";
9776 				olLevel--;
9777 			}
9778 			wikiText += "<li>" + wikiLine.mid(2) + "</li>";
9779 		} else if ( ( wikiLine.startsWith("| ") && wikiLine.endsWith(" |") ) || ( wikiLine.startsWith("^ ") && wikiLine.endsWith(" |") ) ) {
9780 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9781 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9782 			if ( !tableOpen ) { wikiText += "<p><table border=\"1\">"; tableOpen = true; }
9783 			wikiText += "<tr>";
9784 			foreach (QString cell, wikiLine.split(QRegExp("\\^|\\|"), QString::SkipEmptyParts)) wikiText += "<td>" + cell + "</td>";
9785 			wikiText += "</tr>";
9786 		} else if ( wikiLine.startsWith("^ ") && wikiLine.endsWith(" ^") ) {
9787 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9788 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9789 			if ( !tableOpen ) { wikiText += "<p><table border=\"1\">"; tableOpen = true; }
9790 			wikiText += "<tr>";
9791 			foreach (QString cell, wikiLine.split("^", QString::SkipEmptyParts)) wikiText += "<td><b>" + cell + "</b></td>";
9792 			wikiText += "</tr>";
9793 		} else {
9794 			if ( tableOpen ) { wikiText += "</table><p>"; tableOpen = false; }
9795 			if ( ulLevel > 0 ) { for (int i = 0; i < ulLevel; i++) wikiText += "</ul>"; ulLevel = 0; wikiText += "<p>"; }
9796 			if ( olLevel > 0 ) { for (int i = 0; i < olLevel; i++) wikiText += "</ol>"; olLevel = 0; wikiText += "<p>"; }
9797 			if ( preOn ) {
9798 				wikiText += wikiLine.mid(2) + "\n";
9799 			} else if ( codeOn ) {
9800 				wikiText += wikiLine + "\n";
9801 			} else
9802 				wikiText += "<p>" + wikiLine + "</p>";
9803 		}
9804 	}
9805 
9806 	if ( ulLevel > 0 )
9807 		for (int i = 0; i < ulLevel; i++) wikiText += "</ul>";
9808 	else if ( olLevel > 0 )
9809 		for (int i = 0; i < olLevel; i++) wikiText += "</ol>";
9810 
9811 	return wikiText;
9812 }
9813 
floatToggleButtonSoftwareDetail_toggled(bool checked)9814 void MainWindow::floatToggleButtonSoftwareDetail_toggled(bool checked)
9815 {
9816 	if ( qmc2EarlyStartup )
9817 		return;
9818 
9819 	if ( checked ) {
9820 		if ( tabWidgetSoftwareDetail->parent() == this ) {
9821 			qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry", tabWidgetSoftwareDetail->saveGeometry());
9822 			stackedWidgetSpecial->insertWidget(QMC2_SPECIAL_SOFTWARE_PAGE, tabWidgetSoftwareDetail);
9823 			stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_SOFTWARE_PAGE);
9824 			adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizesSoftwareDetail, true);
9825 			lastPageSoftware = true;
9826 		}
9827 	} else {
9828 		stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_DEFAULT_PAGE);
9829 		stackedWidgetSpecial->removeWidget(tabWidgetSoftwareDetail);
9830 		tabWidgetSoftwareDetail->setParent(this);
9831 		tabWidgetSoftwareDetail->setAttribute(Qt::WA_ShowWithoutActivating);
9832 		tabWidgetSoftwareDetail->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
9833 		tabWidgetSoftwareDetail->setWindowIcon(qApp->windowIcon());
9834 		tabWidgetSoftwareDetail->setWindowTitle(tr("Software detail"));
9835 		if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry") )
9836 			tabWidgetSoftwareDetail->restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry").toByteArray());
9837 		if ( qmc2SoftwareList ) {
9838 			tabWidgetSoftwareDetail->showNormal();
9839 			tabWidgetSoftwareDetail->raise();
9840 		}
9841 		adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizes, false);
9842 		if ( lastPageSoftware ) {
9843 			ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
9844 			switch ( componentInfo->appliedFeatureList().at(tabWidgetLogsAndEmulators->currentIndex()) ) {
9845 				case QMC2_FRONTENDLOG_INDEX:
9846 					logScrollToEnd(QMC2_LOG_FRONTEND);
9847 					break;
9848 				case QMC2_EMULATORLOG_INDEX:
9849 					logScrollToEnd(QMC2_LOG_EMULATOR);
9850 					break;
9851 			}
9852 		}
9853 		lastPageSoftware = false;
9854 	}
9855 }
9856 
adjustSplitter(QSplitter * splitter,QTabWidget * tabWidget,QList<int> & sizes,bool enable)9857 void MainWindow::adjustSplitter(QSplitter *splitter, QTabWidget *tabWidget, QList<int> &sizes, bool enable)
9858 {
9859 	if ( tabWidget->count() > 0 || enable ) {
9860 		splitter->handle(1)->setEnabled(true);
9861 		if ( splitter->orientation() == Qt::Horizontal )
9862 			splitter->handle(1)->setFixedWidth(4);
9863 		else
9864 			splitter->handle(1)->setFixedHeight(4);
9865 		splitter->setSizes(sizes);
9866 		splitter->setHandleWidth(4);
9867 	} else {
9868 		splitter->handle(1)->setEnabled(false);
9869 		if ( splitter->orientation() == Qt::Horizontal )
9870 			splitter->handle(1)->setFixedWidth(0);
9871 		else
9872 			splitter->handle(1)->setFixedHeight(0);
9873 		splitter->setSizes(sizes);
9874 		splitter->setHandleWidth(1);
9875 	}
9876 }
9877 
stackedWidgetSpecial_setCurrentIndex(int index)9878 void MainWindow::stackedWidgetSpecial_setCurrentIndex(int index)
9879 {
9880 	switch ( index ) {
9881 		case QMC2_SPECIAL_DEFAULT_PAGE:
9882 			stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_DEFAULT_PAGE);
9883 			if ( tabWidgetSoftwareDetail->parent() == this )
9884 				tabWidgetSoftwareDetail->hide();
9885 			if ( qmc2SoftwareNotesEditor )
9886 				qmc2SoftwareNotesEditor->hideTearOffMenus();
9887 			adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizes, false);
9888 			if ( lastPageSoftware ) {
9889 				ComponentInfo *componentInfo = qmc2ComponentSetup->componentInfoHash().value("Component2");
9890 				switch ( componentInfo->appliedFeatureList().at(tabWidgetLogsAndEmulators->currentIndex()) ) {
9891 					case QMC2_FRONTENDLOG_INDEX:
9892 						logScrollToEnd(QMC2_LOG_FRONTEND);
9893 						break;
9894 					case QMC2_EMULATORLOG_INDEX:
9895 						logScrollToEnd(QMC2_LOG_EMULATOR);
9896 						break;
9897 				}
9898 			}
9899 			lastPageSoftware = false;
9900 			break;
9901 
9902 		case QMC2_SPECIAL_SOFTWARE_PAGE:
9903 			if ( qmc2SoftwareList ) {
9904 				if ( !floatToggleButtonSoftwareDetail->isChecked() ) {
9905 					stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_DEFAULT_PAGE);
9906 					if ( tabWidgetSoftwareDetail->parent() != this ) {
9907 						stackedWidgetSpecial->removeWidget(tabWidgetSoftwareDetail);
9908 						tabWidgetSoftwareDetail->setParent(this);
9909 						tabWidgetSoftwareDetail->setAttribute(Qt::WA_ShowWithoutActivating);
9910 						tabWidgetSoftwareDetail->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
9911 						tabWidgetSoftwareDetail->setWindowIcon(qApp->windowIcon());
9912 						tabWidgetSoftwareDetail->setWindowTitle(tr("Software detail"));
9913 						if ( qmc2Config->contains(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry") )
9914 							tabWidgetSoftwareDetail->restoreGeometry(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailGeometry").toByteArray());
9915 
9916 					}
9917 					adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizes, false);
9918 					qmc2SoftwareList->detailUpdateTimer.start(qmc2UpdateDelay);
9919 					tabWidgetSoftwareDetail->showNormal();
9920 					tabWidgetSoftwareDetail->raise();
9921 					lastPageSoftware = false;
9922 				} else {
9923 					stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_SOFTWARE_PAGE);
9924 					adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizesSoftwareDetail, true);
9925 					lastPageSoftware = true;
9926 				}
9927 			} else {
9928 				stackedWidgetSpecial->setCurrentIndex(QMC2_SPECIAL_SOFTWARE_PAGE);
9929 				adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizesSoftwareDetail, true);
9930 				lastPageSoftware = true;
9931 			}
9932 			break;
9933 
9934 		default:
9935 			stackedWidgetSpecial->setCurrentIndex(index);
9936 			adjustSplitter(vSplitter, tabWidgetLogsAndEmulators, vSplitterSizes, false);
9937 			lastPageSoftware = false;
9938 			break;
9939 	}
9940 }
9941 
comboBoxToolbarSearch_activated(const QString & text)9942 void MainWindow::comboBoxToolbarSearch_activated(const QString &text)
9943 {
9944 	comboBoxSearch->lineEdit()->setText(text);
9945 	int index = comboBoxSearch->findText(text);
9946 	if ( index < 0 ) {
9947 		comboBoxSearch->insertItem(0, text);
9948 		comboBoxSearch->setCurrentIndex(0);
9949 		if ( comboBoxSearch->count() > QMC2_MACHINE_SEARCH_HISTORY_LENGTH )
9950 			comboBoxSearch->removeItem(QMC2_MACHINE_SEARCH_HISTORY_LENGTH);
9951 	} else {
9952 		comboBoxSearch->blockSignals(true);
9953 		comboBoxSearch->removeItem(index);
9954 		comboBoxSearch->insertItem(0, text);
9955 		comboBoxSearch->setCurrentIndex(0);
9956 		comboBoxSearch->blockSignals(false);
9957 	}
9958 	index = comboBoxToolbarSearch->findText(text);
9959 	if ( index >= 0 ) {
9960 		comboBoxToolbarSearch->removeItem(index);
9961 		comboBoxToolbarSearch->insertItem(0, text);
9962 		comboBoxToolbarSearch->setCurrentIndex(0);
9963 	}
9964 	if ( comboBoxToolbarSearch->count() > QMC2_MACHINE_SEARCH_HISTORY_LENGTH )
9965 		comboBoxToolbarSearch->removeItem(QMC2_MACHINE_SEARCH_HISTORY_LENGTH);
9966 	if ( tabWidgetMachineList->currentWidget() != tabSearch ) {
9967 		tabWidgetMachineList->blockSignals(true);
9968 		tabWidgetMachineList->setCurrentWidget(tabSearch);
9969 		tabWidgetMachineList->blockSignals(false);
9970 	}
9971 	m_focusSearchResults = true;
9972 	comboBoxSearch_editTextChanged_delayed();
9973 }
9974 
comboBoxToolbarSearch_editTextChanged(const QString & text)9975 void MainWindow::comboBoxToolbarSearch_editTextChanged(const QString &text)
9976 {
9977 	comboBoxSearch->lineEdit()->setText(text);
9978 }
9979 
treeWidgetMachineList_verticalScrollChanged(int)9980 void MainWindow::treeWidgetMachineList_verticalScrollChanged(int)
9981 {
9982 	if ( !treeWidgetMachineList->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK) )
9983 		m_mlRankUpdateTimer.start(QMC2_RANK_UPDATE_DELAY);
9984 }
9985 
treeWidgetMachineList_updateRanks()9986 void MainWindow::treeWidgetMachineList_updateRanks()
9987 {
9988   	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
9989 		return;
9990 	QTreeWidget *treeWidget = treeWidgetMachineList;
9991 	treeWidget->setUpdatesEnabled(false);
9992 	QTreeWidgetItem *startItem = treeWidget->itemAt(treeWidget->viewport()->rect().topLeft());
9993 	QTreeWidgetItem *endItem = treeWidget->itemAt(treeWidget->viewport()->rect().bottomLeft());
9994 	QFontMetrics fm(treeWidget->fontMetrics());
9995 	if ( startItem && endItem ) {
9996 		while ( startItem->parent() )
9997 			startItem = startItem->parent();
9998 		while ( endItem->parent() )
9999 			endItem = endItem->parent();
10000 		int startIndex = treeWidget->indexOfTopLevelItem(startItem);
10001 		if ( startIndex > 0 )
10002 			startIndex--;
10003 		int endIndex = treeWidget->indexOfTopLevelItem(endItem);
10004 		if ( endIndex + 1 < treeWidget->topLevelItemCount() )
10005 			endIndex++;
10006 		int minWidth = 0;
10007 		for (int i = startIndex; i <= endIndex && !m_mlRankUpdateTimer.isActive(); i++) {
10008 			QTreeWidgetItem *item = treeWidget->topLevelItem(i);
10009 			if ( item->isHidden() )
10010 				continue;
10011 			RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10012 			if ( riw ) {
10013 				riw->setUpdatesEnabled(false);
10014 				riw->updateSize(&fm);
10015 				if ( minWidth == 0 )
10016 					minWidth = riw->width();
10017 				if ( riw->rank() > 0 )
10018 					riw->updateRankImage();
10019 				riw->setUpdatesEnabled(true);
10020 			} else
10021 				treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10022 		}
10023 		if ( treeWidget->columnWidth(QMC2_MACHINELIST_COLUMN_RANK) < minWidth )
10024 			treeWidget->resizeColumnToContents(QMC2_MACHINELIST_COLUMN_RANK);
10025 	}
10026 	treeWidget->setUpdatesEnabled(true);
10027 }
10028 
treeWidgetHierarchy_verticalScrollChanged(int)10029 void MainWindow::treeWidgetHierarchy_verticalScrollChanged(int)
10030 {
10031 	if ( !treeWidgetHierarchy->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK) )
10032 		m_hlRankUpdateTimer.start(QMC2_RANK_UPDATE_DELAY);
10033 }
10034 
treeWidgetHierarchy_updateRanks()10035 void MainWindow::treeWidgetHierarchy_updateRanks()
10036 {
10037   	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
10038 		return;
10039 	QTreeWidget *treeWidget = treeWidgetHierarchy;
10040 	treeWidget->setUpdatesEnabled(false);
10041 	QTreeWidgetItem *startItem = treeWidget->itemAt(treeWidget->viewport()->rect().topLeft());
10042 	QTreeWidgetItem *endItem = treeWidget->itemAt(treeWidget->viewport()->rect().bottomLeft());
10043 	QFontMetrics fm(treeWidget->fontMetrics());
10044 	if ( startItem && endItem ) {
10045 		QTreeWidgetItem *item;
10046 		item = treeWidget->itemBelow(endItem);
10047 		if ( item )
10048 			endItem = item;
10049 		item = treeWidget->itemAbove(startItem);
10050 		if ( item )
10051 			startItem = item;
10052 		item = startItem;
10053 		int minWidth = 0;
10054 		while ( item && item != endItem && !m_hlRankUpdateTimer.isActive() ) {
10055 			RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10056 			if ( riw ) {
10057 				riw->updateSize(&fm);
10058 				if ( minWidth == 0 )
10059 					minWidth = riw->width();
10060 				if ( riw->rank() > 0 )
10061 					riw->updateRankImage();
10062 			} else
10063 				treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10064 			item = treeWidget->itemBelow(item);
10065 		}
10066 		if ( item == endItem && !m_hlRankUpdateTimer.isActive() ) {
10067 			RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10068 			if ( riw ) {
10069 				riw->updateSize(&fm);
10070 				if ( minWidth == 0 )
10071 					minWidth = riw->width();
10072 				if ( riw->rank() > 0 )
10073 					riw->updateRankImage();
10074 			} else
10075 				treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10076 		}
10077 		if ( treeWidget->columnWidth(QMC2_MACHINELIST_COLUMN_RANK) < minWidth )
10078 			treeWidget->resizeColumnToContents(QMC2_MACHINELIST_COLUMN_RANK);
10079 	}
10080 	treeWidget->setUpdatesEnabled(true);
10081 }
10082 
on_treeWidgetHierarchy_itemExpanded(QTreeWidgetItem *)10083 void MainWindow::on_treeWidgetHierarchy_itemExpanded(QTreeWidgetItem * /*item*/)
10084 {
10085 	treeWidgetHierarchy_verticalScrollChanged();
10086 }
10087 
treeWidgetCategoryView_verticalScrollChanged(int)10088 void MainWindow::treeWidgetCategoryView_verticalScrollChanged(int)
10089 {
10090 	if ( !treeWidgetCategoryView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK) )
10091 		m_clRankUpdateTimer.start(QMC2_RANK_UPDATE_DELAY);
10092 }
10093 
treeWidgetCategoryView_updateRanks()10094 void MainWindow::treeWidgetCategoryView_updateRanks()
10095 {
10096   	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
10097 		return;
10098 	QTreeWidget *treeWidget = treeWidgetCategoryView;
10099 	treeWidget->setUpdatesEnabled(false);
10100 	QTreeWidgetItem *startItem = treeWidget->itemAt(treeWidget->viewport()->rect().topLeft());
10101 	QTreeWidgetItem *endItem = treeWidget->itemAt(treeWidget->viewport()->rect().bottomLeft());
10102 	QFontMetrics fm(treeWidget->fontMetrics());
10103 	if ( startItem && endItem ) {
10104 		QTreeWidgetItem *item;
10105 		item = treeWidget->itemBelow(endItem);
10106 		if ( item )
10107 			endItem = item;
10108 		item = treeWidget->itemAbove(startItem);
10109 		if ( item )
10110 			startItem = item;
10111 		item = startItem;
10112 		int minWidth = 0;
10113 		while ( item && item != endItem && !m_clRankUpdateTimer.isActive() ) {
10114 			if ( item->parent() ) {
10115 				RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10116 				if ( riw ) {
10117 					riw->updateSize(&fm);
10118 					if ( minWidth == 0 )
10119 						minWidth = riw->width();
10120 					if ( riw->rank() > 0 )
10121 						riw->updateRankImage();
10122 				} else
10123 					treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10124 			}
10125 			item = treeWidget->itemBelow(item);
10126 		}
10127 		if ( item == endItem && !m_clRankUpdateTimer.isActive() ) {
10128 			if ( item->parent() ) {
10129 				RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10130 				if ( riw ) {
10131 					riw->updateSize(&fm);
10132 					if ( minWidth == 0 )
10133 						minWidth = riw->width();
10134 					if ( riw->rank() > 0 )
10135 						riw->updateRankImage();
10136 				} else
10137 					treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10138 			}
10139 		}
10140 		if ( treeWidget->columnWidth(QMC2_MACHINELIST_COLUMN_RANK) < minWidth )
10141 			treeWidget->resizeColumnToContents(QMC2_MACHINELIST_COLUMN_RANK);
10142 	}
10143 	treeWidget->setUpdatesEnabled(true);
10144 }
10145 
on_treeWidgetCategoryView_itemExpanded(QTreeWidgetItem *)10146 void MainWindow::on_treeWidgetCategoryView_itemExpanded(QTreeWidgetItem * /*item*/)
10147 {
10148 	treeWidgetCategoryView_verticalScrollChanged();
10149 }
10150 
treeWidgetVersionView_verticalScrollChanged(int)10151 void MainWindow::treeWidgetVersionView_verticalScrollChanged(int)
10152 {
10153 	if ( !treeWidgetVersionView->isColumnHidden(QMC2_MACHINELIST_COLUMN_RANK) )
10154 		m_vlRankUpdateTimer.start(QMC2_RANK_UPDATE_DELAY);
10155 }
10156 
treeWidgetVersionView_updateRanks()10157 void MainWindow::treeWidgetVersionView_updateRanks()
10158 {
10159   	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
10160 		return;
10161 	QTreeWidget *treeWidget = treeWidgetVersionView;
10162 	treeWidget->setUpdatesEnabled(false);
10163 	QTreeWidgetItem *startItem = treeWidget->itemAt(treeWidget->viewport()->rect().topLeft());
10164 	QTreeWidgetItem *endItem = treeWidget->itemAt(treeWidget->viewport()->rect().bottomLeft());
10165 	QFontMetrics fm(treeWidget->fontMetrics());
10166 	if ( startItem && endItem ) {
10167 		QTreeWidgetItem *item;
10168 		item = treeWidget->itemBelow(endItem);
10169 		if ( item )
10170 			endItem = item;
10171 		item = treeWidget->itemAbove(startItem);
10172 		if ( item )
10173 			startItem = item;
10174 		item = startItem;
10175 		int minWidth = 0;
10176 		while ( item && item != endItem && !m_clRankUpdateTimer.isActive() ) {
10177 			if ( item->parent() ) {
10178 				RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10179 				if ( riw ) {
10180 					riw->updateSize(&fm);
10181 					if ( minWidth == 0 )
10182 						minWidth = riw->width();
10183 					if ( riw->rank() > 0 )
10184 						riw->updateRankImage();
10185 				} else
10186 					treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10187 			}
10188 			item = treeWidget->itemBelow(item);
10189 		}
10190 		if ( item == endItem && !m_clRankUpdateTimer.isActive() ) {
10191 			if ( item->parent() ) {
10192 				RankItemWidget *riw = (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10193 				if ( riw ) {
10194 					riw->updateSize(&fm);
10195 					if ( minWidth == 0 )
10196 						minWidth = riw->width();
10197 					if ( riw->rank() > 0 )
10198 						riw->updateRankImage();
10199 				} else
10200 					treeWidget->setItemWidget(item, QMC2_MACHINELIST_COLUMN_RANK, new RankItemWidget(item));
10201 			}
10202 		}
10203 		if ( treeWidget->columnWidth(QMC2_MACHINELIST_COLUMN_RANK) < minWidth )
10204 			treeWidget->resizeColumnToContents(QMC2_MACHINELIST_COLUMN_RANK);
10205 	}
10206 	treeWidget->setUpdatesEnabled(true);
10207 }
10208 
on_treeWidgetVersionView_itemExpanded(QTreeWidgetItem * item)10209 void MainWindow::on_treeWidgetVersionView_itemExpanded(QTreeWidgetItem *item)
10210 {
10211 	treeWidgetVersionView_verticalScrollChanged();
10212 }
10213 
on_actionIncreaseRank_triggered(bool)10214 void MainWindow::on_actionIncreaseRank_triggered(bool)
10215 {
10216 	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
10217 		return;
10218 	RankItemWidget *riw = getCurrentRankItemWidget();
10219 	if ( riw )
10220 		riw->increaseRank();
10221 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10222 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10223 		if ( foreignItem ) {
10224 			int rank = foreignItem->rank();
10225 			if ( rank < 5 )
10226 				rank++;
10227 			foreignItem->setRank(rank);
10228 			userDataDb->setRank(foreignItem->id(), rank);
10229 		}
10230 		v->treeView->viewport()->update();
10231 	}
10232 }
10233 
on_actionDecreaseRank_triggered(bool)10234 void MainWindow::on_actionDecreaseRank_triggered(bool)
10235 {
10236 	if ( !qmc2CurrentItem || qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_MACHINE) == MachineList::trWaitingForData )
10237 		return;
10238 	RankItemWidget *riw = getCurrentRankItemWidget();
10239 	if ( riw )
10240 		riw->decreaseRank();
10241 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10242 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10243 		if ( foreignItem ) {
10244 			int rank = foreignItem->rank();
10245 			if ( rank > 0 )
10246 				rank--;
10247 			foreignItem->setRank(rank);
10248 			userDataDb->setRank(foreignItem->id(), rank);
10249 		}
10250 		v->treeView->viewport()->update();
10251 	}
10252 }
10253 
updateUserData()10254 void MainWindow::updateUserData()
10255 {
10256 	if ( tabWidgetMachineList->indexOf(tabMachineList) == tabWidgetMachineList->currentIndex() ) {
10257 		switch ( stackedWidgetView->currentIndex() ) {
10258 			case QMC2_VIEWHIERARCHY_INDEX:
10259 				treeWidgetHierarchy_verticalScrollChanged();
10260 				break;
10261 			case QMC2_VIEWCATEGORY_INDEX:
10262 				treeWidgetCategoryView_verticalScrollChanged();
10263 				break;
10264 			case QMC2_VIEWVERSION_INDEX:
10265 				treeWidgetVersionView_verticalScrollChanged();
10266 				break;
10267 			case QMC2_VIEWCUSTOM_INDEX:
10268 				// handled by custom view
10269 				break;
10270 			case QMC2_VIEWMACHINELIST_INDEX:
10271 			default:
10272 				treeWidgetMachineList_verticalScrollChanged();
10273 				break;
10274 		}
10275 	}
10276 }
10277 
on_actionRankImageGradient_triggered(bool)10278 void MainWindow::on_actionRankImageGradient_triggered(bool)
10279 {
10280 	actionRankImageGradient->setChecked(true);
10281 	actionRankImageFlat->setChecked(false);
10282 	actionRankImagePlain->setChecked(false);
10283 	RankItemWidget::useFlatRankImage = false;
10284 	RankItemWidget::useColorRankImage = false;
10285 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/FlatRankImage", RankItemWidget::useFlatRankImage);
10286 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ColorRankImage", RankItemWidget::useColorRankImage);
10287 	menuRank->setIcon(RankItemWidget::gradientRankIcon());
10288 	actionRankImageGradient->setIcon(RankItemWidget::gradientRankIcon());
10289 	actionRankImageFlat->setIcon(RankItemWidget::flatRankIcon());
10290 	actionRankImagePlain->setIcon(RankItemWidget::colorRankIcon());
10291 	QTimer::singleShot(0, this, SLOT(updateUserData()));
10292 	foreach (MachineListViewer *v, machineListViewers)
10293 		v->treeView->viewport()->update();
10294 }
10295 
on_actionRankImageFlat_triggered(bool)10296 void MainWindow::on_actionRankImageFlat_triggered(bool)
10297 {
10298 	actionRankImageGradient->setChecked(false);
10299 	actionRankImageFlat->setChecked(true);
10300 	actionRankImagePlain->setChecked(false);
10301 	RankItemWidget::useFlatRankImage = true;
10302 	RankItemWidget::useColorRankImage = false;
10303 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/FlatRankImage", RankItemWidget::useFlatRankImage);
10304 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ColorRankImage", RankItemWidget::useColorRankImage);
10305 	menuRank->setIcon(RankItemWidget::flatRankIcon());
10306 	actionRankImageGradient->setIcon(RankItemWidget::gradientRankIcon());
10307 	actionRankImageFlat->setIcon(RankItemWidget::flatRankIcon());
10308 	actionRankImagePlain->setIcon(RankItemWidget::colorRankIcon());
10309 	QTimer::singleShot(0, this, SLOT(updateUserData()));
10310 	foreach (MachineListViewer *v, machineListViewers)
10311 		v->treeView->viewport()->update();
10312 }
10313 
on_actionRankImagePlain_triggered(bool)10314 void MainWindow::on_actionRankImagePlain_triggered(bool)
10315 {
10316 	actionRankImageGradient->setChecked(false);
10317 	actionRankImageFlat->setChecked(false);
10318 	actionRankImagePlain->setChecked(true);
10319 	RankItemWidget::useFlatRankImage = true;
10320 	RankItemWidget::useColorRankImage = true;
10321 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/FlatRankImage", RankItemWidget::useFlatRankImage);
10322 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/ColorRankImage", RankItemWidget::useColorRankImage);
10323 	menuRank->setIcon(RankItemWidget::colorRankIcon());
10324 	actionRankImageGradient->setIcon(RankItemWidget::gradientRankIcon());
10325 	actionRankImageFlat->setIcon(RankItemWidget::flatRankIcon());
10326 	actionRankImagePlain->setIcon(RankItemWidget::colorRankIcon());
10327 	QTimer::singleShot(0, this, SLOT(updateUserData()));
10328 	foreach (MachineListViewer *v, machineListViewers)
10329 		v->treeView->viewport()->update();
10330 }
10331 
on_actionRankImageColor_triggered(bool)10332 void MainWindow::on_actionRankImageColor_triggered(bool)
10333 {
10334 	QColor color(QColorDialog::getColor(RankItemWidget::rankImageColor, this, tr("Choose overlay color"), QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel));
10335 	if ( color.isValid() ) {
10336 		RankItemWidget::rankImageColor = color;
10337 		qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/RankImageColor", RankItemWidget::rankImageColor.name());
10338 		menuRank->setIcon(RankItemWidget::currentRankIcon());
10339 		actionRankImageGradient->setIcon(RankItemWidget::gradientRankIcon());
10340 		actionRankImageFlat->setIcon(RankItemWidget::flatRankIcon());
10341 		actionRankImagePlain->setIcon(RankItemWidget::colorRankIcon());
10342 		QTimer::singleShot(0, this, SLOT(updateUserData()));
10343 		foreach (MachineListViewer *v, machineListViewers)
10344 			v->treeView->viewport()->update();
10345 	}
10346 }
10347 
on_actionSetRank0_triggered(bool)10348 void MainWindow::on_actionSetRank0_triggered(bool)
10349 {
10350 	RankItemWidget *riw = getCurrentRankItemWidget();
10351 	if ( riw )
10352 		riw->setRankComplete(0);
10353 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10354 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10355 		if ( foreignItem ) {
10356 			foreignItem->setRank(0);
10357 			userDataDb->setRank(foreignItem->id(), 0);
10358 		}
10359 		v->treeView->viewport()->update();
10360 	}
10361 }
10362 
on_actionSetRank1_triggered(bool)10363 void MainWindow::on_actionSetRank1_triggered(bool)
10364 {
10365 	RankItemWidget *riw = getCurrentRankItemWidget();
10366 	if ( riw )
10367 		riw->setRankComplete(1);
10368 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10369 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10370 		if ( foreignItem ) {
10371 			foreignItem->setRank(1);
10372 			userDataDb->setRank(foreignItem->id(), 1);
10373 		}
10374 		v->treeView->viewport()->update();
10375 	}
10376 }
10377 
on_actionSetRank2_triggered(bool)10378 void MainWindow::on_actionSetRank2_triggered(bool)
10379 {
10380 	RankItemWidget *riw = getCurrentRankItemWidget();
10381 	if ( riw )
10382 		riw->setRankComplete(2);
10383 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10384 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10385 		if ( foreignItem ) {
10386 			foreignItem->setRank(2);
10387 			userDataDb->setRank(foreignItem->id(), 2);
10388 		}
10389 		v->treeView->viewport()->update();
10390 	}
10391 }
10392 
on_actionSetRank3_triggered(bool)10393 void MainWindow::on_actionSetRank3_triggered(bool)
10394 {
10395 	RankItemWidget *riw = getCurrentRankItemWidget();
10396 	if ( riw )
10397 		riw->setRankComplete(3);
10398 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10399 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10400 		if ( foreignItem ) {
10401 			foreignItem->setRank(3);
10402 			userDataDb->setRank(foreignItem->id(), 3);
10403 		}
10404 		v->treeView->viewport()->update();
10405 	}
10406 }
10407 
on_actionSetRank4_triggered(bool)10408 void MainWindow::on_actionSetRank4_triggered(bool)
10409 {
10410 	RankItemWidget *riw = getCurrentRankItemWidget();
10411 	if ( riw )
10412 		riw->setRankComplete(4);
10413 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10414 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10415 		if ( foreignItem ) {
10416 			foreignItem->setRank(4);
10417 			userDataDb->setRank(foreignItem->id(), 4);
10418 		}
10419 		v->treeView->viewport()->update();
10420 	}
10421 }
10422 
on_actionSetRank5_triggered(bool)10423 void MainWindow::on_actionSetRank5_triggered(bool)
10424 {
10425 	RankItemWidget *riw = getCurrentRankItemWidget();
10426 	if ( riw )
10427 		riw->setRankComplete(5);
10428 	else foreach (MachineListViewer *v, MainWindow::machineListViewers) {
10429 		MachineListModelItem *foreignItem = v->model()->itemHash().value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10430 		if ( foreignItem ) {
10431 			foreignItem->setRank(5);
10432 			userDataDb->setRank(foreignItem->id(), 5);
10433 		}
10434 		v->treeView->viewport()->update();
10435 	}
10436 }
10437 
on_actionTaggedIncreaseRank_triggered(bool)10438 void MainWindow::on_actionTaggedIncreaseRank_triggered(bool)
10439 {
10440 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10441 	foreach (RankItemWidget *riw, *riwList)
10442 		riw->increaseRank();
10443 }
10444 
on_actionTaggedDecreaseRank_triggered(bool)10445 void MainWindow::on_actionTaggedDecreaseRank_triggered(bool)
10446 {
10447 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10448 	foreach (RankItemWidget *riw, *riwList)
10449 		riw->decreaseRank();
10450 }
10451 
on_actionTaggedSetRank0_triggered(bool)10452 void MainWindow::on_actionTaggedSetRank0_triggered(bool)
10453 {
10454 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10455 	foreach (RankItemWidget *riw, *riwList)
10456 		riw->setRankComplete(0);
10457 }
10458 
on_actionTaggedSetRank1_triggered(bool)10459 void MainWindow::on_actionTaggedSetRank1_triggered(bool)
10460 {
10461 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10462 	foreach (RankItemWidget *riw, *riwList)
10463 		riw->setRankComplete(1);
10464 }
10465 
on_actionTaggedSetRank2_triggered(bool)10466 void MainWindow::on_actionTaggedSetRank2_triggered(bool)
10467 {
10468 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10469 	foreach (RankItemWidget *riw, *riwList)
10470 		riw->setRankComplete(2);
10471 }
10472 
on_actionTaggedSetRank3_triggered(bool)10473 void MainWindow::on_actionTaggedSetRank3_triggered(bool)
10474 {
10475 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10476 	foreach (RankItemWidget *riw, *riwList)
10477 		riw->setRankComplete(3);
10478 }
10479 
on_actionTaggedSetRank4_triggered(bool)10480 void MainWindow::on_actionTaggedSetRank4_triggered(bool)
10481 {
10482 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10483 	foreach (RankItemWidget *riw, *riwList)
10484 		riw->setRankComplete(4);
10485 }
10486 
on_actionTaggedSetRank5_triggered(bool)10487 void MainWindow::on_actionTaggedSetRank5_triggered(bool)
10488 {
10489 	QList<RankItemWidget *> *riwList = getTaggedRankItemWidgets();
10490 	foreach (RankItemWidget *riw, *riwList)
10491 		riw->setRankComplete(5);
10492 }
10493 
on_actionLockRanks_triggered(bool)10494 void MainWindow::on_actionLockRanks_triggered(bool)
10495 {
10496 	RankItemWidget::ranksLocked = !RankItemWidget::ranksLocked;
10497 	if ( RankItemWidget::ranksLocked ) {
10498 		actionLockRanks->setIcon(QIcon(QString::fromUtf8(":/data/img/unlock.png")));
10499 		actionLockRanks->setText(tr("Unlock ranks"));
10500 		actionLockRanks->setToolTip(tr("Unlock ranks"));
10501 		actionLockRanks->setStatusTip(tr("Unlock ranks"));
10502 	} else {
10503 		actionLockRanks->setIcon(QIcon(QString::fromUtf8(":/data/img/lock.png")));
10504 		actionLockRanks->setText(tr("Lock ranks"));
10505 		actionLockRanks->setToolTip(tr("Lock ranks"));
10506 		actionLockRanks->setStatusTip(tr("Lock ranks"));
10507 	}
10508 	menuRank_enableActions(!RankItemWidget::ranksLocked);
10509 }
10510 
menuRank_enableActions(bool enable)10511 void MainWindow::menuRank_enableActions(bool enable)
10512 {
10513 	menuSetRank->menuAction()->setEnabled(enable);
10514 	menuTaggedSetRank->menuAction()->setEnabled(enable);
10515 	actionIncreaseRank->setEnabled(enable);
10516 	actionTaggedIncreaseRank->setEnabled(enable);
10517 	actionDecreaseRank->setEnabled(enable);
10518 	actionTaggedDecreaseRank->setEnabled(enable);
10519 }
10520 
menuRank_aboutToShow()10521 void MainWindow::menuRank_aboutToShow()
10522 {
10523 	bool taggedItemsVisible = (qmc2MachineList->numTaggedSets > 0 && (menuGame->isVisible() || menuRank->isTearOffMenuVisible()));
10524 	menuTaggedSetRank->menuAction()->setVisible(taggedItemsVisible);
10525 	actionTaggedIncreaseRank->setVisible(taggedItemsVisible);
10526 	actionTaggedDecreaseRank->setVisible(taggedItemsVisible);
10527 }
10528 
getCurrentRankItemWidget()10529 RankItemWidget *MainWindow::getCurrentRankItemWidget()
10530 {
10531 	QTreeWidget *treeWidget;
10532 	QTreeWidgetItem *item;
10533 	switch ( stackedWidgetView->currentIndex() ) {
10534 		case QMC2_VIEWHIERARCHY_INDEX:
10535 			treeWidget = treeWidgetHierarchy;
10536 			item = qmc2HierarchyItemHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10537 			break;
10538 		case QMC2_VIEWCATEGORY_INDEX:
10539 			treeWidget = treeWidgetCategoryView;
10540 			item = qmc2CategoryItemHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10541 			break;
10542 		case QMC2_VIEWVERSION_INDEX:
10543 			treeWidget = treeWidgetVersionView;
10544 			item = qmc2VersionItemHash.value(qmc2CurrentItem->text(QMC2_MACHINELIST_COLUMN_NAME));
10545 			break;
10546 		case QMC2_VIEWMACHINELIST_INDEX:
10547 		default:
10548 			treeWidget = treeWidgetMachineList;
10549 			item = qmc2CurrentItem;
10550 			break;
10551 	}
10552 	return (RankItemWidget *)treeWidget->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10553 }
10554 
getTaggedRankItemWidgets()10555 QList<RankItemWidget *> *MainWindow::getTaggedRankItemWidgets()
10556 {
10557 	static QList<RankItemWidget *> taggedRiwList;
10558 
10559 	taggedRiwList.clear();
10560 
10561 	QHashIterator<QString, QTreeWidgetItem *> it(qmc2MachineListItemHash);
10562 	QTreeWidgetItem *item;
10563 	while ( it.hasNext() ) {
10564 		it.next();
10565 		item = qmc2MachineListItemHash.value(it.key());
10566 		if ( item ) {
10567 			if ( item->checkState(QMC2_MACHINELIST_COLUMN_TAG) == Qt::Checked )
10568 				taggedRiwList << (RankItemWidget *)treeWidgetMachineList->itemWidget(item, QMC2_MACHINELIST_COLUMN_RANK);
10569 		}
10570 	}
10571 
10572 	return &taggedRiwList;
10573 }
10574 
checkRomPath()10575 void MainWindow::checkRomPath()
10576 {
10577 	if ( !qmc2Config->value(QMC2_EMULATOR_PREFIX + "CheckRomPath", true).toBool() )
10578 		return;
10579 
10580 	QString myRomPath;
10581 
10582 	if ( qmc2Config->contains(QMC2_EMULATOR_PREFIX + "Configuration/Global/rompath") ) {
10583 		QStringList romPaths;
10584 		foreach (QString romPath, qmc2Config->value(QMC2_EMULATOR_PREFIX + "Configuration/Global/rompath").toString().split(";", QString::SkipEmptyParts)) {
10585 			QDir romDir(romPath);
10586 			if ( romDir.isRelative() ) {
10587 				if ( qmc2Config->contains(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/WorkingDirectory") ) {
10588 					QString workPath = qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/WorkingDirectory", QString()).toString();
10589 					if ( !workPath.isEmpty() )
10590 						romPaths << QDir::cleanPath(workPath + "/" + romPath);
10591 					else
10592 						romPaths << romPath;
10593 				}
10594 			} else
10595 				romPaths << romPath;
10596 		}
10597 		myRomPath = romPaths.join(";");
10598 	} else if ( qmc2Config->contains(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/WorkingDirectory") )
10599 		myRomPath = QDir::cleanPath(qmc2Config->value(QMC2_EMULATOR_PREFIX + "FilesAndDirectories/WorkingDirectory", QString()).toString() + "/roms");
10600 	else
10601 		myRomPath = QDir::cleanPath(QDir::currentPath() + "/roms");
10602 
10603 	bool allRomPathsOk = true;
10604 	QStringList pathsToCheck;
10605 
10606 	foreach (QString romPath, myRomPath.split(";", QString::SkipEmptyParts)) {
10607 		QDir romDir(romPath);
10608 		if ( !romDir.exists() ) {
10609 			log(QMC2_LOG_FRONTEND, tr("WARNING: ROM path '%1' doesn't exist").arg(romPath));
10610 			allRomPathsOk = false;
10611 			pathsToCheck << romPath;
10612 		} else if ( !romDir.isReadable() ) {
10613 			log(QMC2_LOG_FRONTEND, tr("WARNING: ROM path '%1' isn't accessible").arg(romPath));;
10614 			allRomPathsOk = false;
10615 			pathsToCheck << romPath;
10616 		}
10617 	}
10618 
10619 	if ( !allRomPathsOk ) {
10620 		QString message;
10621 		if ( pathsToCheck.count() == 1 ) {
10622 			message = tr("The ROM path '%1' doesn't exist or isn't accessible.\n\n"
10623 				     "Please check the 'rompath' option in the global emulator configuration to fix this, otherwise ROMs will probably not be available to the emulator!").arg(pathsToCheck[0]);
10624 		} else {
10625 			message = tr("The ROM paths\n\n%1\n\ndon't exist or aren't accessible.\n\n"
10626 				     "Please check the 'rompath' option in the global emulator configuration to fix this, otherwise ROMs will probably not be available to the emulator!").arg(pathsToCheck.join("\n"));
10627 		}
10628 		switch ( QMessageBox::warning(this, tr("Check ROM path"), message, QMessageBox::Ok | QMessageBox::Ignore, QMessageBox::Ok) ) {
10629 			case QMessageBox::Ignore:
10630 				qmc2Config->setValue(QMC2_EMULATOR_PREFIX + "CheckRomPath", false);
10631 				break;
10632 			case QMessageBox::Ok:
10633 			default:
10634 				break;
10635 		}
10636 	}
10637 }
10638 
negateSearchTriggered(bool negate)10639 void MainWindow::negateSearchTriggered(bool negate)
10640 {
10641 	negatedMatch = negate;
10642 	IconLineEdit *ileSearch = ((IconLineEdit *)comboBoxSearch->lineEdit());
10643 	IconLineEdit *ileToolbarSearch = ((IconLineEdit *)comboBoxToolbarSearch->lineEdit());
10644 	if ( negatedMatch ) {
10645 		ileSearch->button()->setIcon(QIcon(QString::fromUtf8(":/data/img/find_negate.png")));
10646 		ileToolbarSearch->button()->setIcon(QIcon(QString::fromUtf8(":/data/img/find_negate.png")));
10647 	} else {
10648 		ileSearch->button()->setIcon(QIcon(QString::fromUtf8(":/data/img/find.png")));
10649 		ileToolbarSearch->button()->setIcon(QIcon(QString::fromUtf8(":/data/img/find.png")));
10650 	}
10651 	actionNegateSearch->setChecked(negatedMatch);
10652 	searchTimer.start(QMC2_SEARCH_DELAY);
10653 }
10654 
searchIncludeBiosSetsTriggered(bool includeBioses)10655 void MainWindow::searchIncludeBiosSetsTriggered(bool includeBioses)
10656 {
10657 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SearchIncludeBiosSets", includeBioses);
10658 	searchTimer.start(QMC2_SEARCH_DELAY);
10659 }
10660 
searchIncludeDeviceSetsTriggered(bool includeDevices)10661 void MainWindow::searchIncludeDeviceSetsTriggered(bool includeDevices)
10662 {
10663 	qmc2Config->setValue(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SearchIncludeDeviceSets", includeDevices);
10664 	searchTimer.start(QMC2_SEARCH_DELAY);
10665 }
10666 
updateTabWidgets()10667 void MainWindow::updateTabWidgets()
10668 {
10669 	tabWidgetMachineDetail->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineDetailTab", 0).toInt());
10670 	tabWidgetLogsAndEmulators->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/LogsAndEmulatorsTab", 0).toInt());
10671 	on_tabWidgetLogsAndEmulators_currentChanged(tabWidgetLogsAndEmulators->currentIndex());
10672 	tabWidgetMachineList->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/MachineListTab", 0).toInt());
10673 	tabWidgetSoftwareDetail->setCurrentIndex(qmc2Config->value(QMC2_FRONTEND_PREFIX + "Layout/MainWidget/SoftwareDetailTab", 0).toInt());
10674 }
10675 
10676 #if QT_VERSION < 0x050000
myQtMessageHandler(QtMsgType type,const char * msg)10677 void myQtMessageHandler(QtMsgType type, const char *msg)
10678 #else
10679 void myQtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg)
10680 #endif
10681 {
10682 	if ( qmc2SuppressQtMessages )
10683 		return;
10684 	QString msgString;
10685 	switch ( type ) {
10686 		case QtDebugMsg:
10687 			msgString = "QtDebugMsg: " + QString(msg);
10688 			break;
10689 		case QtWarningMsg:
10690 			msgString = "QtWarningMsg: " + QString(msg);
10691 			break;
10692 		case QtCriticalMsg:
10693 			msgString = "QtCriticalMsg: " + QString(msg);
10694 			break;
10695 		case QtFatalMsg:
10696 			msgString = "QtFatalMsg: " + QString(msg);
10697 			break;
10698 		default:
10699 			return;
10700 	}
10701 	if ( qmc2GuiReady )
10702 		qmc2MainWindow->log(QMC2_LOG_FRONTEND, msgString);
10703 	else {
10704 		printf("%s: %s\n", QTime::currentTime().toString("hh:mm:ss.zzz").toUtf8().constData(), msgString.toUtf8().constData());
10705 		fflush(stdout);
10706 	}
10707 }
10708 
processGlobalEmuConfig()10709 void MainWindow::processGlobalEmuConfig()
10710 {
10711 	log(QMC2_LOG_FRONTEND, tr("processing global emulator configuration"));
10712 	int left, top, right, bottom;
10713 	gridLayout->getContentsMargins(&left, &top, &right, &bottom);
10714 	QVBoxLayout *layout = new QVBoxLayout;
10715 	qmc2GlobalEmulatorOptions = new EmulatorOptions(QMC2_EMULATOR_PREFIX + "Configuration/Global", qmc2Options->tabGlobalConfiguration);
10716 	qmc2GlobalEmulatorOptions->load();
10717 	layout->addWidget(qmc2GlobalEmulatorOptions);
10718 	layout->setContentsMargins(left, top, right, bottom);
10719 	QHBoxLayout *buttonLayout = new QHBoxLayout();
10720 	pushButtonGlobalEmulatorOptionsExportToFile = new QPushButton(tr("Export to..."), qmc2Options);
10721 	pushButtonGlobalEmulatorOptionsExportToFile->setToolTip(tr("Export global MAME configuration"));
10722 	pushButtonGlobalEmulatorOptionsExportToFile->setToolTip(tr("Export global MAME configuration"));
10723 	pushButtonGlobalEmulatorOptionsImportFromFile = new QPushButton(tr("Import from..."), qmc2Options);
10724 	pushButtonGlobalEmulatorOptionsImportFromFile->setToolTip(tr("Import global MAME configuration"));
10725 	pushButtonGlobalEmulatorOptionsImportFromFile->setStatusTip(tr("Import global MAME configuration"));
10726 	buttonLayout->addWidget(pushButtonGlobalEmulatorOptionsExportToFile);
10727 	buttonLayout->addWidget(pushButtonGlobalEmulatorOptionsImportFromFile);
10728 	layout->addLayout(buttonLayout);
10729 	qmc2Options->checkBoxEnableOutputNotifiers = new QCheckBox(qmc2Options);
10730 	qmc2Options->checkBoxEnableOutputNotifiers->setText(tr("Enable processing of MAME output notifiers (this forces '-output console')"));
10731 	qmc2Options->checkBoxEnableOutputNotifiers->setToolTip(tr("Enable processing of MAME output notifiers (this forces '-output console')"));
10732 	qmc2Options->checkBoxEnableOutputNotifiers->setChecked(qmc2Config->value(QMC2_EMULATOR_PREFIX + "EnableOutputNotifiers", true).toBool());
10733 	qmc2Options->setEnableOutputNotifiers(qmc2Options->checkBoxEnableOutputNotifiers->isChecked());
10734 	layout->addWidget(qmc2Options->checkBoxEnableOutputNotifiers);
10735 	qmc2Options->tabGlobalConfiguration->setLayout(layout);
10736 	selectMenuGlobalEmulatorOptionsExportToFile = new QMenu(pushButtonGlobalEmulatorOptionsExportToFile);
10737 	connect(selectMenuGlobalEmulatorOptionsExportToFile->addAction(QIcon(QString::fromUtf8(":/data/img/work.png")), tr("<inipath>/mame.ini")), SIGNAL(triggered()), this, SLOT(pushButtonGlobalEmulatorOptionsExportToFile_clicked()));
10738 	connect(selectMenuGlobalEmulatorOptionsExportToFile->addAction(QIcon(QString::fromUtf8(":/data/img/fileopen.png")), tr("Select file...")), SIGNAL(triggered()), this, SLOT(pushButtonGlobalEmulatorOptionsSelectExportFile_clicked()));
10739 	pushButtonGlobalEmulatorOptionsExportToFile->setMenu(selectMenuGlobalEmulatorOptionsExportToFile);
10740 	selectMenuGlobalEmulatorOptionsImportFromFile = new QMenu(pushButtonGlobalEmulatorOptionsImportFromFile);
10741 	connect(selectMenuGlobalEmulatorOptionsImportFromFile->addAction(QIcon(QString::fromUtf8(":/data/img/work.png")), tr("<inipath>/mame.ini")), SIGNAL(triggered()), this, SLOT(pushButtonGlobalEmulatorOptionsImportFromFile_clicked()));
10742 	connect(selectMenuGlobalEmulatorOptionsImportFromFile->addAction(QIcon(QString::fromUtf8(":/data/img/fileopen.png")), tr("Select file...")), SIGNAL(triggered()), this, SLOT(pushButtonGlobalEmulatorOptionsSelectImportFile_clicked()));
10743 	pushButtonGlobalEmulatorOptionsImportFromFile->setMenu(selectMenuGlobalEmulatorOptionsImportFromFile);
10744 }
10745 
prepareShortcuts()10746 void MainWindow::prepareShortcuts()
10747 {
10748 	// shortcuts
10749 	qmc2ShortcutHash["Ctrl+1"].second = actionCheckROMs;
10750 	qmc2ShortcutHash["Ctrl+2"].second = actionCheckSamples;
10751 	qmc2ShortcutHash["Ctrl+3"].second = actionCheckImagesAndIcons;
10752 	qmc2ShortcutHash["Ctrl+B"].second = actionAbout;
10753 	qmc2ShortcutHash["Ctrl+D"].second = actionAnalyseCurrentROM;
10754 	qmc2ShortcutHash["Ctrl+Shift+D"].second = actionAnalyseROMTagged;
10755 	qmc2ShortcutHash["Ctrl+E"].second = actionExportROMStatus;
10756 	qmc2ShortcutHash["Ctrl+J"].second = actionToFavorites;
10757 	qmc2ShortcutHash["Ctrl+Shift+J"].second = actionToFavoritesTagged;
10758 	qmc2ShortcutHash["Ctrl+H"].second = actionDocumentation;
10759 	qmc2ShortcutHash["Ctrl+I"].second = actionClearImageCache;
10760 	qmc2ShortcutHash["Ctrl+Shift+A"].second = actionArcadeSetup;
10761 	qmc2ShortcutHash["Ctrl+M"].second = actionClearProjectMESSCache;
10762 	qmc2ShortcutHash["Ctrl+N"].second = actionClearIconCache;
10763 #if defined(QMC2_OS_MAC)
10764 	qmc2ShortcutHash["Ctrl+,"].second = actionOptions;
10765 #else
10766 	qmc2ShortcutHash["Ctrl+O"].second = actionOptions;
10767 #endif
10768 	qmc2ShortcutHash["Ctrl+P"].second = actionPlay;
10769 #if (defined(QMC2_OS_UNIX) && QT_VERSION < 0x050000) || defined(QMC2_OS_WIN)
10770 	qmc2ShortcutHash["Ctrl+Shift+P"].second = actionPlayEmbedded;
10771 #endif
10772 #if !defined(QMC2_OS_MAC)
10773 	qmc2ShortcutHash["Ctrl+Q"].second = actionAboutQt;
10774 #endif
10775 	qmc2ShortcutHash["Ctrl+R"].second = actionReload;
10776 	qmc2ShortcutHash["Ctrl+S"].second = actionCheckCurrentROM;
10777 	qmc2ShortcutHash["Ctrl+Shift+S"].second = actionCheckROMStateTagged;
10778 	qmc2ShortcutHash["Ctrl+T"].second = actionRecreateTemplateMap;
10779 	qmc2ShortcutHash["Ctrl+Shift+C"].second = actionCheckTemplateMap;
10780 #if defined(QMC2_OS_MAC)
10781 	qmc2ShortcutHash["Ctrl+Q"].second = actionExitStop;
10782 #else
10783 	qmc2ShortcutHash["Ctrl+X"].second = actionExitStop;
10784 #endif
10785 #if defined(QMC2_YOUTUBE_ENABLED)
10786 	qmc2ShortcutHash["Ctrl+Y"].second = actionClearYouTubeCache;
10787 #endif
10788 	qmc2ShortcutHash["Ctrl+Z"].second = actionSystemROMAlyzer;
10789 	qmc2ShortcutHash["Ctrl+W"].second = actionSoftwareROMAlyzer;
10790 	qmc2ShortcutHash["Ctrl+Alt+C"].second = romStateFilter->actionShowCorrect;
10791 	qmc2ShortcutHash["Ctrl+Alt+M"].second = romStateFilter->actionShowMostlyCorrect;
10792 	qmc2ShortcutHash["Ctrl+Alt+I"].second = romStateFilter->actionShowIncorrect;
10793 	qmc2ShortcutHash["Ctrl+Alt+N"].second = romStateFilter->actionShowNotFound;
10794 	qmc2ShortcutHash["Ctrl+Alt+U"].second = romStateFilter->actionShowUnknown;
10795 	qmc2ShortcutHash["Ctrl+Shift+T"].second = actionSetTag;
10796 	qmc2ShortcutHash["Ctrl+Shift+U"].second = actionUnsetTag;
10797 	qmc2ShortcutHash["Ctrl+Shift+G"].second = actionToggleTag;
10798 	qmc2ShortcutHash["Shift+Down"].second = actionToggleTagCursorDown;
10799 	qmc2ShortcutHash["Shift+Up"].second = actionToggleTagCursorUp;
10800 	qmc2ShortcutHash["Ctrl+Shift+L"].second = actionTagAll;
10801 	qmc2ShortcutHash["Ctrl+Shift+N"].second = actionUntagAll;
10802 	qmc2ShortcutHash["Ctrl+Shift+I"].second = actionInvertTags;
10803 	qmc2ShortcutHash["Ctrl+Shift+X"].second = actionTagVisible;
10804 	qmc2ShortcutHash["Ctrl+Shift+Y"].second = actionUntagVisible;
10805 	qmc2ShortcutHash["Ctrl+Shift+Z"].second = actionInvertVisibleTags;
10806 	qmc2ShortcutHash["F2"].second = actionRebuildROM;
10807 	qmc2ShortcutHash["Ctrl+Shift+F2"].second = actionRebuildROMTagged;
10808 	qmc2ShortcutHash["F5"].second = actionViewFullDetail;
10809 	qmc2ShortcutHash["F6"].second = actionViewParentClones;
10810 	qmc2ShortcutHash["F7"].second = actionViewByCategory;
10811 	qmc2ShortcutHash["F8"].second = actionViewByVersion;
10812 #if defined(QMC2_WIP_ENABLED)
10813 	qmc2ShortcutHash["F9"].second = actionCustomView;
10814 #endif
10815 	qmc2ShortcutHash["Shift+F9"].second = actionRunRomTool;
10816 	qmc2ShortcutHash["Ctrl+Shift+F9"].second = actionRunRomToolTagged;
10817 	qmc2ShortcutHash["F10"].second = 0; // for "check software-states"
10818 	qmc2ShortcutHash["F11"].second = actionFullscreenToggle;
10819 	qmc2ShortcutHash["F12"].second = actionLaunchArcade;
10820 	qmc2ShortcutHash["Shift+F5"].second = 0; // for "software-list view flat"
10821 	qmc2ShortcutHash["Shift+F6"].second = 0; // for "software-list view tree"
10822 #if QMC2_USE_PHONON_API
10823 	qmc2ShortcutHash["Ctrl+Alt+Left"].second = actionAudioPreviousTrack;
10824 	qmc2ShortcutHash["Ctrl+Alt+Right"].second = actionAudioNextTrack;
10825 	qmc2ShortcutHash["Ctrl+Alt+B"].second = actionAudioFastBackward;
10826 	qmc2ShortcutHash["Ctrl+Alt+F"].second = actionAudioFastForward;
10827 	qmc2ShortcutHash["Ctrl+Alt+S"].second = actionAudioStopTrack;
10828 	qmc2ShortcutHash["Ctrl+Alt+#"].second = actionAudioPauseTrack;
10829 	qmc2ShortcutHash["Ctrl+Alt+P"].second = actionAudioPlayTrack;
10830 	qmc2ShortcutHash["Ctrl+Alt+PgUp"].second = actionAudioRaiseVolume;
10831 	qmc2ShortcutHash["Ctrl+Alt+PgDown"].second = actionAudioLowerVolume;
10832 #endif
10833 	qmc2ShortcutHash["Alt+PgUp"].second = actionIncreaseRank;
10834 	qmc2ShortcutHash["Alt+PgDown"].second = actionDecreaseRank;
10835 
10836 	// special keys
10837 	qmc2QtKeyHash.insert("+", QKeySequence("+", QKeySequence::PortableText));
10838 	qmc2QtKeyHash.insert("-", QKeySequence("-", QKeySequence::PortableText));
10839 	qmc2QtKeyHash.insert("Down", QKeySequence("Down", QKeySequence::PortableText));
10840 	qmc2QtKeyHash.insert("End", QKeySequence("End", QKeySequence::PortableText));
10841 	qmc2QtKeyHash.insert("Esc", QKeySequence("Esc", QKeySequence::PortableText));
10842 	qmc2QtKeyHash.insert("Left", QKeySequence("Left", QKeySequence::PortableText));
10843 	qmc2QtKeyHash.insert("Home", QKeySequence("Home", QKeySequence::PortableText));
10844 	qmc2QtKeyHash.insert("PgDown", QKeySequence("PgDown", QKeySequence::PortableText));
10845 	qmc2QtKeyHash.insert("PgUp", QKeySequence("PgUp", QKeySequence::PortableText));
10846 	qmc2QtKeyHash.insert("Return", QKeySequence("Return", QKeySequence::PortableText));
10847 	qmc2QtKeyHash.insert("Enter", QKeySequence("Enter", QKeySequence::PortableText));
10848 	qmc2QtKeyHash.insert("Right", QKeySequence("Right", QKeySequence::PortableText));
10849 	qmc2QtKeyHash.insert("Tab", QKeySequence("Tab", QKeySequence::PortableText));
10850 	qmc2QtKeyHash.insert("Up", QKeySequence("Up", QKeySequence::PortableText));
10851 #if defined(QMC2_OS_MAC)
10852 	qmc2QtKeyHash.insert("Ctrl+O", QKeySequence("Ctrl+O", QKeySequence::PortableText));
10853 #endif
10854 
10855 	QTimer::singleShot(0, qmc2Options, SLOT(setupShortcutActions()));
10856 }
10857 
10858 #if defined(QMC2_OS_WIN)
10859 #if defined(TCOD_VISUAL_STUDIO)
SDL_main(int argc,char * argv[])10860 int SDL_main(int argc, char *argv[])
10861 {
10862 	return main(argc, argv);
10863 }
10864 #endif
10865 #if defined(QMC2_MINGW)
10866 #undef main
10867 #endif
10868 #endif
10869 
main(int argc,char ** argv)10870 int main(int argc, char **argv)
10871 {
10872 #if defined(QMC2_OS_MAC)
10873 	// this hack ensures that we're using the bundled plugins rather than the ones from a Qt SDK installation
10874 	char exec_path[4096];
10875 	uint32_t exec_path_size = sizeof(exec_path);
10876 	if ( _NSGetExecutablePath(exec_path, &exec_path_size) == 0 ) {
10877 		QFileInfo fi(exec_path);
10878 		QCoreApplication::addLibraryPath(fi.absoluteDir().absolutePath() + "/../PlugIns");
10879 	}
10880 #endif
10881 
10882 	qsrand(QDateTime::currentDateTime().toTime_t());
10883 
10884 	// install message handler
10885 #if QT_VERSION < 0x050000
10886 	qInstallMsgHandler(myQtMessageHandler);
10887 #else
10888 	qInstallMessageHandler(myQtMessageHandler);
10889 #endif
10890 
10891 	// prepare application and resources
10892 	QApplication qmc2App(argc, argv);
10893 
10894 	if ( QMC2_CLI_OPT_HELP ) {
10895 #if defined(QMC2_OS_WIN)
10896 		winAllocConsole();
10897 #endif
10898 		printf("Usage: %s [-config_path <config_path>] [-cc] [-tc] [-r] [-h|-?|-help] [qt_arguments]\n\n"
10899 		       "-config_path    Use specified configuration path (default: %s)\n"
10900 		       "-cc             Clear all emulator caches before starting up\n"
10901 		       "-tc             Check the emulator configuration template and exit\n"
10902 		       "-r		Reconfigure (runs the setup wizard before starting)\n"
10903 		       "-h|-?|-help     Show this help text and exit\n", argv[0], QString(QMC2_DOT_PATH).toUtf8().constData());
10904 #if defined(QMC2_OS_WIN)
10905 		winFreeConsole();
10906 #endif
10907 		return 1;
10908 	}
10909 
10910 	Q_INIT_RESOURCE(qmc2);
10911 
10912 	qmc2App.setWindowIcon(QIcon(QString::fromUtf8(":/data/img/mame.png")));
10913 	QPixmap splashPixmap(QString::fromUtf8(":/data/img/qmc2_mame_splash.png"));
10914 
10915 	qmc2TemplateCheck = QMC2_CLI_OPT_TEMPLATE_CHECK;
10916 
10917 	// check configuration
10918 	int checkReturn = QDialog::Accepted;
10919 	qmc2Welcome = new Welcome(0);
10920 	if ( !qmc2Welcome->checkOkay ) {
10921 		checkReturn = qmc2Welcome->exec();
10922 		qmc2TemplateCheck = false;
10923 	}
10924 	if ( checkReturn != QDialog::Accepted )
10925 		return 1;
10926 
10927 	bool showSplashScreen = qmc2Welcome->startupConfig->value(QMC2_FRONTEND_PREFIX + "GUI/ShowSplashScreen", true).toBool() && !qmc2TemplateCheck;
10928 	QFont splashFont(qApp->font());
10929 	if ( !qmc2Welcome->startupConfig->value(QMC2_FRONTEND_PREFIX + "GUI/Font").toString().isEmpty() )
10930 		splashFont.fromString(qmc2Welcome->startupConfig->value(QMC2_FRONTEND_PREFIX + "GUI/Font").toString());
10931 	delete qmc2Welcome;
10932 
10933 	// setup splash screen
10934 	if ( showSplashScreen ) {
10935 		qmc2SplashScreen = new QSplashScreen(splashPixmap);
10936 		splashFont.setBold(true);
10937 		qmc2SplashScreen->setFont(splashFont);
10938 		qmc2SplashScreen->setAttribute(Qt::WA_ShowWithoutActivating);
10939 		qmc2SplashScreen->setMask(splashPixmap.mask());
10940 		qmc2SplashScreen->setWindowOpacity(0.8);
10941 		qmc2SplashScreen->showMessage(QObject::tr("Setting up the GUI, please wait..."), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
10942 		qmc2SplashScreen->show();
10943 	}
10944 
10945 	// setup event filter
10946 	qmc2MainEventFilter = new MainEventFilter(0);
10947 	qmc2App.installEventFilter(qmc2MainEventFilter);
10948 
10949 	// create mandatory objects
10950 	qmc2Options = new Options(0);
10951 	qmc2Config = qmc2Options->config;
10952 	qmc2ProcessManager = new ProcessManager(0);
10953 	qmc2MainWindow = new MainWindow(0);
10954 	qmc2ComponentSetup = new ComponentSetup(qmc2MainWindow);
10955 
10956 	// finalize initial setup
10957 	qmc2Options->apply();
10958 	qmc2GuiReady = true;
10959 	qmc2MainWindow->prepareShortcuts();
10960 
10961 #if QT_VERSION < 0x050000
10962 	// this effectively enables support for unicode characters in C strings
10963 	QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
10964 	QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
10965 #endif
10966 
10967 	// create & show the greeting string
10968 	QString greeting(QObject::tr("M.A.M.E. Catalog / Launcher II v") + QString(XSTR(QMC2_VERSION)) +
10969 #if QMC2_SVN_REV > 0
10970 			   ", " + QObject::tr("SVN r%1").arg(QMC2_SVN_REV) +
10971 #endif
10972 			   " (Qt " + qVersion() + ", " + QMC2_EMU_NAME_VARIANT + ", " + QMC2_OS_NAME + " " + QMC2_MACHINE_ARCHITECTURE + ")");
10973 	qmc2StartupTimer.start();
10974 	qmc2MainWindow->log(QMC2_LOG_FRONTEND, greeting);
10975 
10976 #if QMC2_USE_PHONON_API
10977 	qmc2MainWindow->log(QMC2_LOG_FRONTEND, QObject::tr("Phonon features enabled - using Phonon v%1").arg(Phonon::phononVersion()));
10978 #endif
10979 
10980 #if QMC2_JOYSTICK == 1
10981 #if SDL_MAJOR_VERSION == 1
10982 	const SDL_version *sdlVersion = SDL_Linked_Version();
10983 	qmc2MainWindow->log(QMC2_LOG_FRONTEND, QObject::tr("SDL joystick support enabled - using SDL v%1.%2.%3").arg(sdlVersion->major).arg(sdlVersion->minor).arg(sdlVersion->patch));
10984 #elif SDL_MAJOR_VERSION == 2
10985 	SDL_version sdlVersion;
10986 	SDL_GetVersion(&sdlVersion);
10987 	qmc2MainWindow->log(QMC2_LOG_FRONTEND, QObject::tr("SDL joystick support enabled - using SDL v%1.%2.%3").arg(sdlVersion.major).arg(sdlVersion.minor).arg(sdlVersion.patch));
10988 #endif
10989 #endif
10990 
10991 	// process global emulator configuration and create import/export popup menus
10992 	qmc2MainWindow->processGlobalEmuConfig();
10993 
10994 	int retCode = 0;
10995 	if ( qmc2TemplateCheck ) {
10996 #if defined(QMC2_OS_WIN)
10997 		winAllocConsole();
10998 #endif
10999 		qmc2GlobalEmulatorOptions->checkTemplateMap();
11000 #if defined(QMC2_OS_WIN)
11001 		winFreeConsole();
11002 #endif
11003 		qmc2Options->applied = true;
11004 		qmc2MainWindow->close();
11005 	} else {
11006 		QTimer::singleShot(0, qmc2Options, SLOT(checkShortcuts()));
11007 #if QMC2_JOYSTICK == 1
11008 		QTimer::singleShot(0, qmc2Options, SLOT(checkJoystickMappings()));
11009 #endif
11010 		qmc2Options->on_pushButtonApply_clicked();
11011 		// finally run the application
11012 		retCode = qmc2App.exec();
11013 	}
11014 
11015 	if ( qmc2SplashScreen )
11016 		qmc2SplashScreen->deleteLater();
11017 
11018 	// wait for all application threads to finish
11019 	QThreadPool::globalInstance()->waitForDone();
11020 
11021 	return retCode;
11022 }
11023