summaryrefslogtreecommitdiff
path: root/src/citra_qt/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/main.cpp')
-rw-r--r--src/citra_qt/main.cpp135
1 files changed, 79 insertions, 56 deletions
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index cf467532f..e10314856 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -10,9 +10,9 @@
10 10
11#define QT_NO_OPENGL 11#define QT_NO_OPENGL
12#include <QDesktopWidget> 12#include <QDesktopWidget>
13#include <QtGui>
14#include <QFileDialog> 13#include <QFileDialog>
15#include <QMessageBox> 14#include <QMessageBox>
15#include <QtGui>
16#include "qhexedit.h" 16#include "qhexedit.h"
17 17
18#include "citra_qt/bootmanager.h" 18#include "citra_qt/bootmanager.h"
@@ -36,27 +36,26 @@
36#include "citra_qt/debugger/ramview.h" 36#include "citra_qt/debugger/ramview.h"
37#include "citra_qt/debugger/registers.h" 37#include "citra_qt/debugger/registers.h"
38 38
39#include "common/logging/backend.h"
40#include "common/logging/filter.h"
41#include "common/logging/log.h"
42#include "common/logging/text_formatter.h"
39#include "common/microprofile.h" 43#include "common/microprofile.h"
40#include "common/platform.h" 44#include "common/platform.h"
41#include "common/scm_rev.h" 45#include "common/scm_rev.h"
42#include "common/scope_exit.h" 46#include "common/scope_exit.h"
43#include "common/string_util.h" 47#include "common/string_util.h"
44#include "common/logging/backend.h"
45#include "common/logging/filter.h"
46#include "common/logging/log.h"
47#include "common/logging/text_formatter.h"
48 48
49#include "core/core.h"
50#include "core/settings.h"
51#include "core/system.h"
52#include "core/arm/disassembler/load_symbol_map.h" 49#include "core/arm/disassembler/load_symbol_map.h"
50#include "core/core.h"
53#include "core/gdbstub/gdbstub.h" 51#include "core/gdbstub/gdbstub.h"
54#include "core/loader/loader.h" 52#include "core/loader/loader.h"
53#include "core/settings.h"
54#include "core/system.h"
55 55
56#include "video_core/video_core.h" 56#include "video_core/video_core.h"
57 57
58GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) 58GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
59{
60 Pica::g_debug_context = Pica::DebugContext::Construct(); 59 Pica::g_debug_context = Pica::DebugContext::Construct();
61 60
62 ui.setupUi(this); 61 ui.setupUi(this);
@@ -91,7 +90,7 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
91 90
92 graphicsWidget = new GPUCommandStreamWidget(this); 91 graphicsWidget = new GPUCommandStreamWidget(this);
93 addDockWidget(Qt::RightDockWidgetArea, graphicsWidget); 92 addDockWidget(Qt::RightDockWidgetArea, graphicsWidget);
94 graphicsWidget ->hide(); 93 graphicsWidget->hide();
95 94
96 graphicsCommandsWidget = new GPUCommandListWidget(this); 95 graphicsCommandsWidget = new GPUCommandListWidget(this);
97 addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); 96 addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
@@ -110,7 +109,8 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
110 graphicsTracingWidget->hide(); 109 graphicsTracingWidget->hide();
111 110
112 auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica surface viewer"), this); 111 auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica surface viewer"), this);
113 connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, SLOT(OnCreateGraphicsSurfaceViewer())); 112 connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this,
113 SLOT(OnCreateGraphicsSurfaceViewer()));
114 114
115 QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); 115 QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging"));
116 debug_menu->addAction(graphicsSurfaceViewerAction); 116 debug_menu->addAction(graphicsSurfaceViewerAction);
@@ -167,35 +167,44 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
167 UpdateRecentFiles(); 167 UpdateRecentFiles();
168 168
169 // Setup connections 169 // Setup connections
170 connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection); 170 connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)),
171 Qt::DirectConnection);
171 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure())); 172 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure()));
172 connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection); 173 connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),
174 Qt::DirectConnection);
173 connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); 175 connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap()));
174 connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot())); 176 connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this,
177 SLOT(OnMenuSelectGameListRoot()));
175 connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); 178 connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame()));
176 connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); 179 connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame()));
177 connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); 180 connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame()));
178 connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode())); 181 connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode()));
179 182
180 connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*))); 183 connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget,
184 SLOT(OnEmulationStarting(EmuThread*)));
181 connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping())); 185 connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping()));
182 connect(this, SIGNAL(EmulationStarting(EmuThread*)), registersWidget, SLOT(OnEmulationStarting(EmuThread*))); 186 connect(this, SIGNAL(EmulationStarting(EmuThread*)), registersWidget,
187 SLOT(OnEmulationStarting(EmuThread*)));
183 connect(this, SIGNAL(EmulationStopping()), registersWidget, SLOT(OnEmulationStopping())); 188 connect(this, SIGNAL(EmulationStopping()), registersWidget, SLOT(OnEmulationStopping()));
184 connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window, SLOT(OnEmulationStarting(EmuThread*))); 189 connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window,
190 SLOT(OnEmulationStarting(EmuThread*)));
185 connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping())); 191 connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping()));
186 connect(this, SIGNAL(EmulationStarting(EmuThread*)), graphicsTracingWidget, SLOT(OnEmulationStarting(EmuThread*))); 192 connect(this, SIGNAL(EmulationStarting(EmuThread*)), graphicsTracingWidget,
193 SLOT(OnEmulationStarting(EmuThread*)));
187 connect(this, SIGNAL(EmulationStopping()), graphicsTracingWidget, SLOT(OnEmulationStopping())); 194 connect(this, SIGNAL(EmulationStopping()), graphicsTracingWidget, SLOT(OnEmulationStopping()));
188 195
189
190 // Setup hotkeys 196 // Setup hotkeys
191 RegisterHotkey("Main Window", "Load File", QKeySequence::Open); 197 RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
192 RegisterHotkey("Main Window", "Start Emulation"); 198 RegisterHotkey("Main Window", "Start Emulation");
193 LoadHotkeys(); 199 LoadHotkeys();
194 200
195 connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); 201 connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this,
196 connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); 202 SLOT(OnMenuLoadFile()));
203 connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this,
204 SLOT(OnStartGame()));
197 205
198 std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); 206 std::string window_title =
207 Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
199 setWindowTitle(window_title.c_str()); 208 setWindowTitle(window_title.c_str());
200 209
201 show(); 210 show();
@@ -208,8 +217,7 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
208 } 217 }
209} 218}
210 219
211GMainWindow::~GMainWindow() 220GMainWindow::~GMainWindow() {
212{
213 // will get automatically deleted otherwise 221 // will get automatically deleted otherwise
214 if (render_window->parent() == nullptr) 222 if (render_window->parent() == nullptr)
215 delete render_window; 223 delete render_window;
@@ -217,19 +225,18 @@ GMainWindow::~GMainWindow()
217 Pica::g_debug_context.reset(); 225 Pica::g_debug_context.reset();
218} 226}
219 227
220void GMainWindow::OnDisplayTitleBars(bool show) 228void GMainWindow::OnDisplayTitleBars(bool show) {
221{
222 QList<QDockWidget*> widgets = findChildren<QDockWidget*>(); 229 QList<QDockWidget*> widgets = findChildren<QDockWidget*>();
223 230
224 if (show) { 231 if (show) {
225 for (QDockWidget* widget: widgets) { 232 for (QDockWidget* widget : widgets) {
226 QWidget* old = widget->titleBarWidget(); 233 QWidget* old = widget->titleBarWidget();
227 widget->setTitleBarWidget(nullptr); 234 widget->setTitleBarWidget(nullptr);
228 if (old != nullptr) 235 if (old != nullptr)
229 delete old; 236 delete old;
230 } 237 }
231 } else { 238 } else {
232 for (QDockWidget* widget: widgets) { 239 for (QDockWidget* widget : widgets) {
233 QWidget* old = widget->titleBarWidget(); 240 QWidget* old = widget->titleBarWidget();
234 widget->setTitleBarWidget(new QWidget()); 241 widget->setTitleBarWidget(new QWidget());
235 if (old != nullptr) 242 if (old != nullptr)
@@ -249,7 +256,8 @@ bool GMainWindow::InitializeSystem() {
249 if (!gladLoadGL()) { 256 if (!gladLoadGL()) {
250 QMessageBox::critical(this, tr("Error while starting Citra!"), 257 QMessageBox::critical(this, tr("Error while starting Citra!"),
251 tr("Failed to initialize the video core!\n\n" 258 tr("Failed to initialize the video core!\n\n"
252 "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver.")); 259 "Please ensure that your GPU supports OpenGL 3.3 and that you "
260 "have the latest graphics driver."));
253 return false; 261 return false;
254 } 262 }
255 263
@@ -260,7 +268,8 @@ bool GMainWindow::InitializeSystem() {
260 case System::Result::ErrorInitVideoCore: 268 case System::Result::ErrorInitVideoCore:
261 QMessageBox::critical(this, tr("Error while starting Citra!"), 269 QMessageBox::critical(this, tr("Error while starting Citra!"),
262 tr("Failed to initialize the video core!\n\n" 270 tr("Failed to initialize the video core!\n\n"
263 "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver.")); 271 "Please ensure that your GPU supports OpenGL 3.3 and that you "
272 "have the latest graphics driver."));
264 break; 273 break;
265 274
266 default: 275 default:
@@ -293,8 +302,12 @@ bool GMainWindow::LoadROM(const std::string& filename) {
293 QMessageBox popup_error; 302 QMessageBox popup_error;
294 popup_error.setTextFormat(Qt::RichText); 303 popup_error.setTextFormat(Qt::RichText);
295 popup_error.setWindowTitle(tr("Error while loading ROM!")); 304 popup_error.setWindowTitle(tr("Error while loading ROM!"));
296 popup_error.setText(tr("The game that you are trying to load must be decrypted before being used with Citra.<br/><br/>" 305 popup_error.setText(
297 "For more information on dumping and decrypting games, please see: <a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://citra-emu.org/wiki/Dumping-Game-Cartridges</a>")); 306 tr("The game that you are trying to load must be decrypted before being used with "
307 "Citra.<br/><br/>"
308 "For more information on dumping and decrypting games, please see: <a "
309 "href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://"
310 "citra-emu.org/wiki/Dumping-Game-Cartridges</a>"));
298 popup_error.setIcon(QMessageBox::Critical); 311 popup_error.setIcon(QMessageBox::Critical);
299 popup_error.exec(); 312 popup_error.exec();
300 break; 313 break;
@@ -306,8 +319,7 @@ bool GMainWindow::LoadROM(const std::string& filename) {
306 case Loader::ResultStatus::Error: 319 case Loader::ResultStatus::Error:
307 320
308 default: 321 default:
309 QMessageBox::critical(this, tr("Error while loading ROM!"), 322 QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!"));
310 tr("Unknown error!"));
311 break; 323 break;
312 } 324 }
313 return false; 325 return false;
@@ -332,13 +344,20 @@ void GMainWindow::BootGame(const std::string& filename) {
332 emu_thread->start(); 344 emu_thread->start();
333 345
334 connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame())); 346 connect(render_window, SIGNAL(Closed()), this, SLOT(OnStopGame()));
335 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views before the CPU continues 347 // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views
336 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 348 // before the CPU continues
337 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 349 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), disasmWidget, SLOT(OnDebugModeEntered()),
338 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget, SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection); 350 Qt::BlockingQueuedConnection);
339 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); 351 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), registersWidget,
340 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); 352 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
341 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()), Qt::BlockingQueuedConnection); 353 connect(emu_thread.get(), SIGNAL(DebugModeEntered()), callstackWidget,
354 SLOT(OnDebugModeEntered()), Qt::BlockingQueuedConnection);
355 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), disasmWidget, SLOT(OnDebugModeLeft()),
356 Qt::BlockingQueuedConnection);
357 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), registersWidget, SLOT(OnDebugModeLeft()),
358 Qt::BlockingQueuedConnection);
359 connect(emu_thread.get(), SIGNAL(DebugModeLeft()), callstackWidget, SLOT(OnDebugModeLeft()),
360 Qt::BlockingQueuedConnection);
342 361
343 // Update the GUI 362 // Update the GUI
344 registersWidget->OnDebugModeEntered(); 363 registersWidget->OnDebugModeEntered();
@@ -393,10 +412,12 @@ void GMainWindow::StoreRecentFile(const std::string& filename) {
393} 412}
394 413
395void GMainWindow::UpdateRecentFiles() { 414void GMainWindow::UpdateRecentFiles() {
396 unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item)); 415 unsigned int num_recent_files =
416 std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item));
397 417
398 for (unsigned int i = 0; i < num_recent_files; i++) { 418 for (unsigned int i = 0; i < num_recent_files; i++) {
399 QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName()); 419 QString text = QString("&%1. %2").arg(i + 1).arg(
420 QFileInfo(UISettings::values.recent_files[i]).fileName());
400 actions_recent_files[i]->setText(text); 421 actions_recent_files[i]->setText(text);
401 actions_recent_files[i]->setData(UISettings::values.recent_files[i]); 422 actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
402 actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]); 423 actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]);
@@ -420,7 +441,9 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
420} 441}
421 442
422void GMainWindow::OnMenuLoadFile() { 443void GMainWindow::OnMenuLoadFile() {
423 QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); 444 QString filename =
445 QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path,
446 tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
424 if (!filename.isEmpty()) { 447 if (!filename.isEmpty()) {
425 UISettings::values.roms_path = QFileInfo(filename).path(); 448 UISettings::values.roms_path = QFileInfo(filename).path();
426 449
@@ -429,7 +452,8 @@ void GMainWindow::OnMenuLoadFile() {
429} 452}
430 453
431void GMainWindow::OnMenuLoadSymbolMap() { 454void GMainWindow::OnMenuLoadSymbolMap() {
432 QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)")); 455 QString filename = QFileDialog::getOpenFileName(
456 this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)"));
433 if (!filename.isEmpty()) { 457 if (!filename.isEmpty()) {
434 UISettings::values.symbols_path = QFileInfo(filename).path(); 458 UISettings::values.symbols_path = QFileInfo(filename).path();
435 459
@@ -455,7 +479,8 @@ void GMainWindow::OnMenuRecentFile() {
455 BootGame(filename.toStdString()); 479 BootGame(filename.toStdString());
456 } else { 480 } else {
457 // Display an error message and remove the file from the list. 481 // Display an error message and remove the file from the list.
458 QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename)); 482 QMessageBox::information(this, tr("File not found"),
483 tr("File \"%1\" not found").arg(filename));
459 484
460 UISettings::values.recent_files.removeOne(filename); 485 UISettings::values.recent_files.removeOne(filename);
461 UpdateRecentFiles(); 486 UpdateRecentFiles();
@@ -512,8 +537,7 @@ void GMainWindow::ToggleWindowMode() {
512void GMainWindow::OnConfigure() { 537void GMainWindow::OnConfigure() {
513 ConfigureDialog configureDialog(this); 538 ConfigureDialog configureDialog(this);
514 auto result = configureDialog.exec(); 539 auto result = configureDialog.exec();
515 if (result == QDialog::Accepted) 540 if (result == QDialog::Accepted) {
516 {
517 configureDialog.applyConfiguration(); 541 configureDialog.applyConfiguration();
518 render_window->ReloadSetKeymaps(); 542 render_window->ReloadSetKeymaps();
519 config->Save(); 543 config->Save();
@@ -531,9 +555,9 @@ bool GMainWindow::ConfirmClose() {
531 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) 555 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
532 return true; 556 return true;
533 557
534 auto answer = QMessageBox::question(this, tr("Citra"), 558 auto answer =
535 tr("Are you sure you want to close Citra?"), 559 QMessageBox::question(this, tr("Citra"), tr("Are you sure you want to close Citra?"),
536 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 560 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
537 return answer != QMessageBox::No; 561 return answer != QMessageBox::No;
538} 562}
539 563
@@ -575,9 +599,7 @@ int main(int argc, char* argv[]) {
575 Log::SetFilter(&log_filter); 599 Log::SetFilter(&log_filter);
576 600
577 MicroProfileOnThreadCreate("Frontend"); 601 MicroProfileOnThreadCreate("Frontend");
578 SCOPE_EXIT({ 602 SCOPE_EXIT({ MicroProfileShutdown(); });
579 MicroProfileShutdown();
580 });
581 603
582 // Init settings params 604 // Init settings params
583 QCoreApplication::setOrganizationName("Citra team"); 605 QCoreApplication::setOrganizationName("Citra team");
@@ -586,7 +608,8 @@ int main(int argc, char* argv[]) {
586 QApplication::setAttribute(Qt::AA_X11InitThreads); 608 QApplication::setAttribute(Qt::AA_X11InitThreads);
587 QApplication app(argc, argv); 609 QApplication app(argc, argv);
588 610
589 // Qt changes the locale and causes issues in float conversion using std::to_string() when generating shaders 611 // Qt changes the locale and causes issues in float conversion using std::to_string() when
612 // generating shaders
590 setlocale(LC_ALL, "C"); 613 setlocale(LC_ALL, "C");
591 614
592 GMainWindow main_window; 615 GMainWindow main_window;