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("<", "<").replace(">", ">");
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("<h2>======") && wikiLine.endsWith("======</h2>") ) {
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