2022-06-12 12:50:58 +01:00
// SPDX-License-Identifier: GPL-3.0-only
/*
2022-12-14 15:02:04 +00:00
* Prism Launcher - Minecraft Launcher
2022-06-12 12:50:58 +01:00
* Copyright ( C ) 2022 Sefa Eyeoglu < contact @ scrumplex . net >
2022-12-14 15:02:04 +00:00
* Copyright ( C ) 2022 TheKodeToad < TheKodeToad @ proton . me >
2013-02-19 23:07:52 +00:00
*
2022-06-12 12:50:58 +01:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , version 3.
2013-01-09 18:22:22 +00:00
*
2022-06-12 12:50:58 +01:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2013-03-11 21:19:17 +00:00
*
2022-06-12 12:50:58 +01:00
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2013-01-09 18:22:22 +00:00
*
2022-06-12 12:50:58 +01:00
* This file incorporates work covered by the following copyright and
* permission notice :
2013-02-19 23:07:52 +00:00
*
2022-06-12 12:50:58 +01:00
* Copyright 2013 - 2021 MultiMC Contributors
2013-01-09 18:22:22 +00:00
*
2022-06-12 12:50:58 +01:00
* Authors : Andrew Okin
* Peterix
* Orochimarufan < orochimarufan . x3 @ gmail . com >
2013-03-11 21:19:17 +00:00
*
2022-06-12 12:50:58 +01:00
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2013-01-09 18:22:22 +00:00
*
2022-06-12 12:50:58 +01:00
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
2013-01-09 18:22:22 +00:00
*/
2022-06-12 12:50:58 +01:00
2021-11-20 15:22:22 +00:00
# include "Application.h"
2014-04-06 02:59:37 +01:00
# include "BuildConfig.h"
2022-10-22 15:56:27 +01:00
# include "FileSystem.h"
2013-01-09 18:22:22 +00:00
2013-11-04 01:53:05 +00:00
# include "MainWindow.h"
2022-12-31 00:08:10 +00:00
# include "ui_MainWindow.h"
2015-03-01 21:20:57 +00:00
2022-05-02 18:10:45 +01:00
# include <QVariant>
# include <QUrl>
# include <QDir>
# include <QFileInfo>
# include <QKeyEvent>
# include <QAction>
2022-11-15 08:19:46 +00:00
# include <QActionGroup>
2022-05-02 18:10:45 +01:00
# include <QApplication>
# include <QButtonGroup>
# include <QHBoxLayout>
# include <QHeaderView>
# include <QMainWindow>
# include <QStatusBar>
# include <QToolBar>
# include <QWidget>
# include <QMenu>
# include <QMenuBar>
# include <QMessageBox>
2022-10-19 14:53:57 +01:00
# include <QFileDialog>
2022-05-02 18:10:45 +01:00
# include <QInputDialog>
# include <QLabel>
# include <QToolButton>
# include <QWidgetAction>
# include <QProgressDialog>
# include <QShortcut>
2015-10-20 16:18:53 +01:00
# include <BaseInstance.h>
# include <InstanceList.h>
2022-11-19 16:31:58 +00:00
# include <minecraft/MinecraftInstance.h>
2015-10-20 16:18:53 +01:00
# include <MMCZip.h>
# include <icons/IconList.h>
# include <java/JavaUtils.h>
2016-01-01 23:35:54 +00:00
# include <java/JavaInstallList.h>
2015-10-20 16:18:53 +01:00
# include <launch/LaunchTask.h>
2021-07-26 20:44:11 +01:00
# include <minecraft/auth/AccountList.h>
2016-04-10 03:29:29 +01:00
# include <SkinUtils.h>
2020-07-18 15:18:02 +01:00
# include <BuildConfig.h>
2015-10-20 16:18:53 +01:00
# include <net/NetJob.h>
2016-05-28 18:54:17 +01:00
# include <net/Download.h>
2022-02-10 11:55:07 +00:00
# include <news/NewsChecker.h>
2015-10-20 16:18:53 +01:00
# include <tools/BaseProfiler.h>
# include <updater/DownloadTask.h>
# include <updater/UpdateChecker.h>
2016-01-05 06:32:52 +00:00
# include <DesktopServices.h>
2016-08-06 14:39:29 +01:00
# include "InstanceWindow.h"
2015-10-20 16:18:53 +01:00
# include "InstancePageProvider.h"
# include "JavaCommon.h"
2016-08-10 23:44:01 +01:00
# include "LaunchController.h"
2021-11-22 02:55:16 +00:00
# include "ui/instanceview/InstanceProxyModel.h"
# include "ui/instanceview/InstanceView.h"
# include "ui/instanceview/InstanceDelegate.h"
# include "ui/widgets/LabeledToolButton.h"
# include "ui/dialogs/NewInstanceDialog.h"
2022-06-26 00:15:16 +01:00
# include "ui/dialogs/NewsDialog.h"
2021-11-22 02:55:16 +00:00
# include "ui/dialogs/ProgressDialog.h"
# include "ui/dialogs/AboutDialog.h"
# include "ui/dialogs/VersionSelectDialog.h"
# include "ui/dialogs/CustomMessageBox.h"
# include "ui/dialogs/IconPickerDialog.h"
# include "ui/dialogs/CopyInstanceDialog.h"
# include "ui/dialogs/UpdateDialog.h"
# include "ui/dialogs/EditAccountDialog.h"
# include "ui/dialogs/ExportInstanceDialog.h"
2022-12-31 01:06:17 +00:00
# include "ui/dialogs/ImportResourceDialog.h"
2022-11-14 22:59:26 +00:00
# include "ui/themes/ITheme.h"
2023-01-09 15:58:27 +00:00
# include "ui/themes/ThemeManager.h"
2021-11-22 02:55:16 +00:00
2022-12-31 01:06:17 +00:00
# include "minecraft/mod/tasks/LocalResourceParse.h"
# include "minecraft/mod/ModFolderModel.h"
# include "minecraft/WorldList.h"
2022-11-19 16:28:35 +00:00
2016-11-18 15:04:08 +00:00
# include "UpdateController.h"
2018-03-15 08:27:45 +00:00
# include "KonamiCode.h"
2021-11-22 02:55:16 +00:00
# include "InstanceImportTask.h"
# include "InstanceCopyTask.h"
2021-09-28 23:20:34 +01:00
# include "MMCTime.h"
2015-10-20 16:18:53 +01:00
2021-07-26 20:44:11 +01:00
namespace {
QString profileInUseFilter ( const QString & profile , bool used )
{
if ( used )
{
return QObject : : tr ( " %1 (in use) " ) . arg ( profile ) ;
}
else
{
return profile ;
}
}
}
2022-12-31 00:08:10 +00:00
MainWindow : : MainWindow ( QWidget * parent ) : QMainWindow ( parent ) , ui ( new Ui : : MainWindow )
2017-10-01 23:55:34 +01:00
{
2022-12-31 00:08:10 +00:00
ui - > setupUi ( this ) ;
2022-04-16 08:32:08 +01:00
2023-01-17 22:51:56 +00:00
setWindowIcon ( APPLICATION - > getThemedIcon ( " logo " ) ) ;
setWindowTitle ( APPLICATION - > applicationDisplayName ( ) ) ;
# ifndef QT_NO_ACCESSIBILITY
setAccessibleName ( BuildConfig . LAUNCHER_DISPLAYNAME ) ;
# endif
2022-12-31 00:08:10 +00:00
// instance toolbar stuff
2022-04-16 08:32:08 +01:00
{
2022-12-31 00:08:10 +00:00
// Qt doesn't like vertical moving toolbars, so we have to force them...
// See https://github.com/PolyMC/PolyMC/issues/493
connect ( ui - > instanceToolBar , & QToolBar : : orientationChanged ,
[ = ] ( Qt : : Orientation ) { ui - > instanceToolBar - > setOrientation ( Qt : : Vertical ) ; } ) ;
2022-04-16 08:32:08 +01:00
2022-12-31 00:08:10 +00:00
// if you try to add a widget to a toolbar in a .ui file
// qt designer will delete it when you save the file >:(
changeIconButton = new LabeledToolButton ( this ) ;
2018-07-15 13:51:05 +01:00
changeIconButton - > setObjectName ( QStringLiteral ( " changeIconButton " ) ) ;
2021-11-20 15:22:22 +00:00
changeIconButton - > setIcon ( APPLICATION - > getThemedIcon ( " news " ) ) ;
2018-07-15 13:51:05 +01:00
changeIconButton - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Preferred ) ;
2022-12-31 00:08:10 +00:00
connect ( changeIconButton , & QToolButton : : clicked , this , & MainWindow : : on_actionChangeInstIcon_triggered ) ;
ui - > instanceToolBar - > insertWidgetBefore ( ui - > actionLaunchInstance , changeIconButton ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
renameButton = new LabeledToolButton ( this ) ;
2018-07-15 13:51:05 +01:00
renameButton - > setObjectName ( QStringLiteral ( " renameButton " ) ) ;
renameButton - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Preferred ) ;
2022-12-31 00:08:10 +00:00
connect ( renameButton , & QToolButton : : clicked , this , & MainWindow : : on_actionRenameInstance_triggered ) ;
ui - > instanceToolBar - > insertWidgetBefore ( ui - > actionLaunchInstance , renameButton ) ;
2018-07-15 13:51:05 +01:00
2023-01-09 03:51:46 +00:00
ui - > instanceToolBar - > insertSeparator ( ui - > actionLaunchInstance ) ;
2022-12-31 00:08:10 +00:00
// restore the instance toolbar settings
auto const setting_name = QString ( " WideBarVisibility_%1 " ) . arg ( ui - > instanceToolBar - > objectName ( ) ) ;
if ( ! APPLICATION - > settings ( ) - > contains ( setting_name ) )
instanceToolbarSetting = APPLICATION - > settings ( ) - > registerSetting ( setting_name ) ;
else
instanceToolbarSetting = APPLICATION - > settings ( ) - > getSetting ( setting_name ) ;
2022-10-22 13:39:53 +01:00
2022-12-31 00:08:10 +00:00
ui - > instanceToolBar - > setVisibilityState ( instanceToolbarSetting - > get ( ) . toByteArray ( ) ) ;
2023-01-09 01:47:38 +00:00
2023-01-10 15:02:02 +00:00
ui - > instanceToolBar - > addContextMenuAction ( ui - > newsToolBar - > toggleViewAction ( ) ) ;
ui - > instanceToolBar - > addContextMenuAction ( ui - > instanceToolBar - > toggleViewAction ( ) ) ;
ui - > instanceToolBar - > addContextMenuAction ( ui - > actionLockToolbars ) ;
2022-04-16 08:32:08 +01:00
}
2023-01-26 22:48:21 +00:00
// set the menu for the folders help, and accounts tool buttons
2022-04-16 08:32:08 +01:00
{
2022-12-31 00:08:10 +00:00
auto foldersMenuButton = dynamic_cast < QToolButton * > ( ui - > mainToolBar - > widgetForAction ( ui - > actionFoldersButton ) ) ;
2023-01-26 22:48:21 +00:00
ui - > actionFoldersButton - > setMenu ( ui - > foldersMenu ) ;
2022-12-31 00:08:10 +00:00
foldersMenuButton - > setPopupMode ( QToolButton : : InstantPopup ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
helpMenuButton = dynamic_cast < QToolButton * > ( ui - > mainToolBar - > widgetForAction ( ui - > actionHelpButton ) ) ;
2023-01-26 22:48:21 +00:00
ui - > actionHelpButton - > setMenu ( ui - > helpMenu ) ;
2022-12-31 00:08:10 +00:00
helpMenuButton - > setPopupMode ( QToolButton : : InstantPopup ) ;
2023-01-26 22:48:21 +00:00
auto accountMenuButton = dynamic_cast < QToolButton * > ( ui - > mainToolBar - > widgetForAction ( ui - > actionAccountsButton ) ) ;
ui - > actionAccountsButton - > setMenu ( ui - > accountsMenu ) ;
accountMenuButton - > setPopupMode ( QToolButton : : InstantPopup ) ;
2018-07-15 13:51:05 +01:00
}
2022-12-31 00:08:10 +00:00
// hide, disable and show stuff
2018-07-15 13:51:05 +01:00
{
2022-12-31 00:08:10 +00:00
ui - > actionReportBug - > setVisible ( ! BuildConfig . BUG_TRACKER_URL . isEmpty ( ) ) ;
ui - > actionMATRIX - > setVisible ( ! BuildConfig . MATRIX_URL . isEmpty ( ) ) ;
ui - > actionDISCORD - > setVisible ( ! BuildConfig . DISCORD_URL . isEmpty ( ) ) ;
ui - > actionREDDIT - > setVisible ( ! BuildConfig . SUBREDDIT_URL . isEmpty ( ) ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
ui - > actionCheckUpdate - > setVisible ( BuildConfig . UPDATER_ENABLED ) ;
2018-07-15 13:51:05 +01:00
2023-01-26 22:48:21 +00:00
# ifndef Q_OS_MAC
2022-12-31 00:08:10 +00:00
ui - > actionAddToPATH - > setVisible ( false ) ;
# endif
2022-05-09 04:42:37 +01:00
2022-12-31 00:08:10 +00:00
// disabled until we have an instance selected
ui - > instanceToolBar - > setEnabled ( false ) ;
setInstanceActionsEnabled ( false ) ;
}
2015-03-01 21:20:57 +00:00
2022-12-31 00:08:10 +00:00
// add the toolbar toggles to the view menu
ui - > viewMenu - > addAction ( ui - > instanceToolBar - > toggleViewAction ( ) ) ;
ui - > viewMenu - > addAction ( ui - > newsToolBar - > toggleViewAction ( ) ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
updateThemeMenu ( ) ;
updateMainToolBar ( ) ;
2018-07-15 13:51:05 +01:00
// OSX magic.
setUnifiedTitleAndToolBarOnMac ( true ) ;
// Global shortcuts
{
2022-12-31 00:08:10 +00:00
// you can't set QKeySequence::StandardKey shortcuts in qt designer >:(
ui - > actionAddInstance - > setShortcut ( QKeySequence : : New ) ;
ui - > actionSettings - > setShortcut ( QKeySequence : : Preferences ) ;
ui - > actionUndoTrashInstance - > setShortcut ( QKeySequence : : Undo ) ;
ui - > actionDeleteInstance - > setShortcuts ( { QKeySequence ( tr ( " Backspace " ) ) , QKeySequence : : Delete } ) ;
ui - > actionCloseWindow - > setShortcut ( QKeySequence : : Close ) ;
connect ( ui - > actionCloseWindow , & QAction : : triggered , APPLICATION , & Application : : closeCurrentWindow ) ;
2018-07-15 13:51:05 +01:00
// FIXME: This is kinda weird. and bad. We need some kind of managed shutdown.
auto q = new QShortcut ( QKeySequence : : Quit , this ) ;
2022-12-31 00:08:10 +00:00
connect ( q , & QShortcut : : activated , APPLICATION , & Application : : quit ) ;
2018-07-15 13:51:05 +01:00
}
// Konami Code
{
secretEventFilter = new KonamiCode ( this ) ;
connect ( secretEventFilter , & KonamiCode : : triggered , this , & MainWindow : : konamiTriggered ) ;
}
2022-02-10 11:55:07 +00:00
// Add the news label to the news toolbar.
{
m_newsChecker . reset ( new NewsChecker ( APPLICATION - > network ( ) , BuildConfig . NEWS_RSS_URL ) ) ;
2023-01-13 19:51:19 +00:00
newsLabel = new QToolButton ( ) ;
newsLabel - > setIcon ( APPLICATION - > getThemedIcon ( " news " ) ) ;
newsLabel - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Preferred ) ;
newsLabel - > setToolButtonStyle ( Qt : : ToolButtonTextBesideIcon ) ;
newsLabel - > setFocusPolicy ( Qt : : NoFocus ) ;
ui - > newsToolBar - > insertWidget ( ui - > actionMoreNews , newsLabel ) ;
2022-12-31 00:08:10 +00:00
2022-02-10 11:55:07 +00:00
QObject : : connect ( newsLabel , & QAbstractButton : : clicked , this , & MainWindow : : newsButtonClicked ) ;
QObject : : connect ( m_newsChecker . get ( ) , & NewsChecker : : newsLoaded , this , & MainWindow : : updateNewsLabel ) ;
updateNewsLabel ( ) ;
}
2018-07-15 13:51:05 +01:00
// Create the instance list widget
{
2021-10-25 22:51:42 +01:00
view = new InstanceView ( ui - > centralWidget ) ;
2018-07-15 13:51:05 +01:00
view - > setSelectionMode ( QAbstractItemView : : SingleSelection ) ;
// FIXME: leaks ListViewDelegate
view - > setItemDelegate ( new ListViewDelegate ( this ) ) ;
view - > setFrameShape ( QFrame : : NoFrame ) ;
// do not show ugly blue border on the mac
view - > setAttribute ( Qt : : WA_MacShowFocusRect , false ) ;
view - > installEventFilter ( this ) ;
view - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
connect ( view , & QWidget : : customContextMenuRequested , this , & MainWindow : : showInstanceContextMenu ) ;
2022-12-31 01:06:17 +00:00
connect ( view , & InstanceView : : droppedURLs , this , & MainWindow : : processURLs , Qt : : QueuedConnection ) ;
2018-07-15 13:51:05 +01:00
proxymodel = new InstanceProxyModel ( this ) ;
2021-11-20 15:22:22 +00:00
proxymodel - > setSourceModel ( APPLICATION - > instances ( ) . get ( ) ) ;
2018-07-15 13:51:05 +01:00
proxymodel - > sort ( 0 ) ;
connect ( proxymodel , & InstanceProxyModel : : dataChanged , this , & MainWindow : : instanceDataChanged ) ;
view - > setModel ( proxymodel ) ;
2019-08-20 01:58:27 +01:00
view - > setSourceOfGroupCollapseStatus ( [ ] ( const QString & groupName ) - > bool {
2021-11-20 15:22:22 +00:00
return APPLICATION - > instances ( ) - > isGroupCollapsed ( groupName ) ;
2019-08-20 01:58:27 +01:00
} ) ;
2021-11-20 15:22:22 +00:00
connect ( view , & InstanceView : : groupStateChanged , APPLICATION - > instances ( ) . get ( ) , & InstanceList : : on_GroupStateChanged ) ;
2018-07-15 13:51:05 +01:00
ui - > horizontalLayout - > addWidget ( view ) ;
}
// The cat background
{
2022-12-31 00:08:10 +00:00
// set the cat action priority here so you can still see the action in qt designer
ui - > actionCAT - > setPriority ( QAction : : LowPriority ) ;
2021-11-20 15:22:22 +00:00
bool cat_enable = APPLICATION - > settings ( ) - > get ( " TheCat " ) . toBool ( ) ;
2018-07-15 13:51:05 +01:00
ui - > actionCAT - > setChecked ( cat_enable ) ;
2022-12-31 00:08:10 +00:00
connect ( ui - > actionCAT , & QAction : : toggled , this , & MainWindow : : onCatToggled ) ;
2023-01-20 14:13:25 +00:00
connect ( APPLICATION , & Application : : currentCatChanged , this , & MainWindow : : onCatChanged ) ;
2018-07-15 13:51:05 +01:00
setCatBackground ( cat_enable ) ;
}
2022-10-25 23:22:11 +01:00
// Lock toolbars
{
bool toolbarsLocked = APPLICATION - > settings ( ) - > get ( " ToolbarsLocked " ) . toBool ( ) ;
ui - > actionLockToolbars - > setChecked ( toolbarsLocked ) ;
2022-11-05 21:10:36 +00:00
connect ( ui - > actionLockToolbars , & QAction : : toggled , this , & MainWindow : : lockToolbars ) ;
2022-10-25 23:22:11 +01:00
lockToolbars ( toolbarsLocked ) ;
}
2018-07-15 13:51:05 +01:00
// start instance when double-clicked
2021-10-25 22:51:42 +01:00
connect ( view , & InstanceView : : activated , this , & MainWindow : : instanceActivated ) ;
2018-07-15 13:51:05 +01:00
// track the selection -- update the instance toolbar
connect ( view - > selectionModel ( ) , & QItemSelectionModel : : currentChanged , this , & MainWindow : : instanceChanged ) ;
// track icon changes and update the toolbar!
2021-11-20 15:22:22 +00:00
connect ( APPLICATION - > icons ( ) . get ( ) , & IconList : : iconUpdated , this , & MainWindow : : iconUpdated ) ;
2018-07-15 13:51:05 +01:00
// model reset -> selection is invalid. All the instance pointers are wrong.
2021-11-20 15:22:22 +00:00
connect ( APPLICATION - > instances ( ) . get ( ) , & InstanceList : : dataIsInvalid , this , & MainWindow : : selectionBad ) ;
2018-07-15 13:51:05 +01:00
2019-06-17 15:13:52 +01:00
// handle newly added instances
2021-11-20 15:22:22 +00:00
connect ( APPLICATION - > instances ( ) . get ( ) , & InstanceList : : instanceSelectRequest , this , & MainWindow : : instanceSelectRequest ) ;
2019-06-17 15:13:52 +01:00
2019-06-01 11:28:53 +01:00
// When the global settings page closes, we want to know about it and update our state
2021-11-20 15:22:22 +00:00
connect ( APPLICATION , & Application : : globalSettingsClosed , this , & MainWindow : : globalSettingsClosed ) ;
2019-06-01 11:28:53 +01:00
2018-07-15 13:51:05 +01:00
m_statusLeft = new QLabel ( tr ( " No instance selected " ) , this ) ;
2021-10-01 23:20:25 +01:00
m_statusCenter = new QLabel ( tr ( " Total playtime: 0s " ) , this ) ;
2018-07-15 13:51:05 +01:00
statusBar ( ) - > addPermanentWidget ( m_statusLeft , 1 ) ;
2021-10-10 00:25:31 +01:00
statusBar ( ) - > addPermanentWidget ( m_statusCenter , 0 ) ;
2018-07-15 13:51:05 +01:00
// Add "manage accounts" button, right align
QWidget * spacer = new QWidget ( ) ;
spacer - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
2022-12-31 00:08:10 +00:00
ui - > mainToolBar - > insertWidget ( ui - > actionAccountsButton , spacer ) ;
2018-07-15 13:51:05 +01:00
2022-05-09 08:20:53 +01:00
// Use undocumented property... https://stackoverflow.com/questions/7121718/create-a-scrollbar-in-a-submenu-qt
2023-01-26 22:48:21 +00:00
ui - > accountsMenu - > setStyleSheet ( " QMenu { menu-scrollable: 1; } " ) ;
2018-07-15 13:51:05 +01:00
repopulateAccountsMenu ( ) ;
// Update the menu when the active account changes.
// Shouldn't have to use lambdas here like this, but if I don't, the compiler throws a fit.
// Template hell sucks...
2021-07-26 20:44:11 +01:00
connect (
2021-11-20 15:22:22 +00:00
APPLICATION - > accounts ( ) . get ( ) ,
& AccountList : : defaultAccountChanged ,
2021-07-26 20:44:11 +01:00
[ this ] {
2021-11-20 15:22:22 +00:00
defaultAccountChanged ( ) ;
2021-07-26 20:44:11 +01:00
}
) ;
connect (
2021-11-20 15:22:22 +00:00
APPLICATION - > accounts ( ) . get ( ) ,
2021-07-26 20:44:11 +01:00
& AccountList : : listChanged ,
[ this ]
{
repopulateAccountsMenu ( ) ;
}
) ;
2018-07-15 13:51:05 +01:00
// Show initial account
2021-11-20 15:22:22 +00:00
defaultAccountChanged ( ) ;
2018-07-15 13:51:05 +01:00
2021-07-26 20:44:11 +01:00
// TODO: refresh accounts here?
2021-11-20 15:22:22 +00:00
// auto accounts = APPLICATION->accounts();
2018-07-15 13:51:05 +01:00
2022-02-10 11:55:07 +00:00
// load the news
{
m_newsChecker - > reloadNews ( ) ;
updateNewsLabel ( ) ;
}
2018-07-15 13:51:05 +01:00
if ( BuildConfig . UPDATER_ENABLED )
{
2021-11-20 15:22:22 +00:00
bool updatesAllowed = APPLICATION - > updatesAreAllowed ( ) ;
2018-07-15 13:51:05 +01:00
updatesAllowedChanged ( updatesAllowed ) ;
2022-12-31 00:08:10 +00:00
connect ( ui - > actionCheckUpdate , & QAction : : triggered , this , & MainWindow : : checkForUpdates ) ;
2018-07-15 13:51:05 +01:00
// set up the updater object.
2021-11-20 15:22:22 +00:00
auto updater = APPLICATION - > updateChecker ( ) ;
2018-07-15 13:51:05 +01:00
connect ( updater . get ( ) , & UpdateChecker : : updateAvailable , this , & MainWindow : : updateAvailable ) ;
connect ( updater . get ( ) , & UpdateChecker : : noUpdateFound , this , & MainWindow : : updateNotAvailable ) ;
// if automatic update checks are allowed, start one.
2021-11-20 15:22:22 +00:00
if ( APPLICATION - > settings ( ) - > get ( " AutoUpdate " ) . toBool ( ) & & updatesAllowed )
2018-07-15 13:51:05 +01:00
{
2021-11-20 15:22:22 +00:00
updater - > checkForUpdate ( APPLICATION - > settings ( ) - > get ( " UpdateChannel " ) . toString ( ) , false ) ;
2018-07-15 13:51:05 +01:00
}
2022-04-21 03:34:13 +01:00
2022-04-26 00:33:17 +01:00
if ( APPLICATION - > updateChecker ( ) - > getExternalUpdater ( ) )
{
connect ( APPLICATION - > updateChecker ( ) - > getExternalUpdater ( ) ,
& ExternalUpdater : : canCheckForUpdatesChanged ,
this ,
& MainWindow : : updatesAllowedChanged ) ;
}
2018-07-15 13:51:05 +01:00
}
2022-12-31 00:08:10 +00:00
connect ( ui - > actionUndoTrashInstance , & QAction : : triggered , this , & MainWindow : : undoTrashInstance ) ;
2022-10-30 18:08:02 +00:00
2021-11-20 15:22:22 +00:00
setSelectedInstanceById ( APPLICATION - > settings ( ) - > get ( " SelectedInstance " ) . toString ( ) ) ;
2018-07-15 13:51:05 +01:00
// removing this looks stupid
view - > setFocus ( ) ;
2021-06-19 00:12:54 +01:00
retranslateUi ( ) ;
}
2022-04-08 21:21:52 +01:00
// macOS always has a native menu bar, so these fixes are not applicable
// Other systems may or may not have a native menu bar (most do not - it seems like only Ubuntu Unity does)
2022-04-08 22:00:42 +01:00
# ifndef Q_OS_MAC
2022-04-08 21:21:52 +01:00
void MainWindow : : keyReleaseEvent ( QKeyEvent * event )
{
2022-04-15 23:25:37 +01:00
if ( event - > key ( ) = = Qt : : Key_Alt & & ! APPLICATION - > settings ( ) - > get ( " MenuBarInsteadOfToolBar " ) . toBool ( ) )
2022-04-08 21:21:52 +01:00
ui - > menuBar - > setVisible ( ! ui - > menuBar - > isVisible ( ) ) ;
2022-04-08 22:00:42 +01:00
else
QMainWindow : : keyReleaseEvent ( event ) ;
2022-04-08 21:21:52 +01:00
}
# endif
2021-06-19 00:12:54 +01:00
void MainWindow : : retranslateUi ( )
{
2021-11-20 15:22:22 +00:00
auto accounts = APPLICATION - > accounts ( ) ;
MinecraftAccountPtr defaultAccount = accounts - > defaultAccount ( ) ;
if ( defaultAccount ) {
auto profileLabel = profileInUseFilter ( defaultAccount - > profileName ( ) , defaultAccount - > isInUse ( ) ) ;
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setText ( profileLabel ) ;
2021-07-26 20:44:11 +01:00
}
else {
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setText ( tr ( " Accounts " ) ) ;
2021-07-26 20:44:11 +01:00
}
2021-06-19 00:12:54 +01:00
if ( m_selectedInstance ) {
m_statusLeft - > setText ( m_selectedInstance - > getStatusbarDescription ( ) ) ;
} else {
m_statusLeft - > setText ( tr ( " No instance selected " ) ) ;
}
ui - > retranslateUi ( this ) ;
2022-12-31 00:08:10 +00:00
changeIconButton - > setToolTip ( ui - > actionChangeInstIcon - > toolTip ( ) ) ;
renameButton - > setToolTip ( ui - > actionRenameInstance - > toolTip ( ) ) ;
// replace the %1 with the launcher display name in some actions
if ( helpMenuButton - > toolTip ( ) . contains ( " %1 " ) )
helpMenuButton - > setToolTip ( helpMenuButton - > toolTip ( ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ) ;
for ( auto action : ui - > helpMenu - > actions ( ) ) {
if ( action - > text ( ) . contains ( " %1 " ) )
action - > setText ( action - > text ( ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ) ;
if ( action - > toolTip ( ) . contains ( " %1 " ) )
action - > setToolTip ( action - > toolTip ( ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ) ;
}
2013-01-09 18:22:22 +00:00
}
MainWindow : : ~ MainWindow ( )
{
2013-03-11 21:19:17 +00:00
}
2019-07-16 00:30:09 +01:00
QMenu * MainWindow : : createPopupMenu ( )
{
QMenu * filteredMenu = QMainWindow : : createPopupMenu ( ) ;
filteredMenu - > removeAction ( ui - > mainToolBar - > toggleViewAction ( ) ) ;
2022-10-25 23:22:11 +01:00
filteredMenu - > addAction ( ui - > actionLockToolbars ) ;
2019-07-16 00:30:09 +01:00
return filteredMenu ;
}
2022-10-25 23:22:11 +01:00
void MainWindow : : lockToolbars ( bool state )
{
ui - > mainToolBar - > setMovable ( ! state ) ;
ui - > instanceToolBar - > setMovable ( ! state ) ;
ui - > newsToolBar - > setMovable ( ! state ) ;
APPLICATION - > settings ( ) - > set ( " ToolbarsLocked " , state ) ;
}
2019-07-16 00:30:09 +01:00
2018-03-15 08:27:45 +00:00
void MainWindow : : konamiTriggered ( )
{
2018-07-15 13:51:05 +01:00
qDebug ( ) < < " Super Secret Mode ACTIVATED! " ;
2018-03-15 08:27:45 +00:00
}
2014-01-27 02:00:49 +00:00
void MainWindow : : showInstanceContextMenu ( const QPoint & pos )
2014-01-05 00:06:59 +00:00
{
2018-07-15 13:51:05 +01:00
QList < QAction * > actions ;
QAction * actionSep = new QAction ( " " , this ) ;
actionSep - > setSeparator ( true ) ;
bool onInstance = view - > indexAt ( pos ) . isValid ( ) ;
if ( onInstance )
{
2022-12-31 00:08:10 +00:00
// reuse the file menu actions
actions = ui - > fileMenu - > actions ( ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
// remove the add instance action, launcher settings action and close action
actions . removeFirst ( ) ;
actions . removeLast ( ) ;
actions . removeLast ( ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
actions . prepend ( ui - > actionChangeInstIcon ) ;
actions . prepend ( ui - > actionRenameInstance ) ;
2018-07-15 13:51:05 +01:00
// add header
actions . prepend ( actionSep ) ;
QAction * actionVoid = new QAction ( m_selectedInstance - > name ( ) , this ) ;
actionVoid - > setEnabled ( false ) ;
actions . prepend ( actionVoid ) ;
}
else
{
auto group = view - > groupNameAt ( pos ) ;
2022-10-18 08:50:27 +01:00
QAction * actionVoid = new QAction ( BuildConfig . LAUNCHER_DISPLAYNAME , this ) ;
2018-07-15 13:51:05 +01:00
actionVoid - > setEnabled ( false ) ;
QAction * actionCreateInstance = new QAction ( tr ( " Create instance " ) , this ) ;
actionCreateInstance - > setToolTip ( ui - > actionAddInstance - > toolTip ( ) ) ;
if ( ! group . isNull ( ) )
{
QVariantMap data ;
data [ " group " ] = group ;
actionCreateInstance - > setData ( data ) ;
}
connect ( actionCreateInstance , SIGNAL ( triggered ( bool ) ) , SLOT ( on_actionAddInstance_triggered ( ) ) ) ;
actions . prepend ( actionSep ) ;
actions . prepend ( actionVoid ) ;
actions . append ( actionCreateInstance ) ;
if ( ! group . isNull ( ) )
{
QAction * actionDeleteGroup = new QAction ( tr ( " Delete group '%1' " ) . arg ( group ) , this ) ;
QVariantMap data ;
data [ " group " ] = group ;
actionDeleteGroup - > setData ( data ) ;
connect ( actionDeleteGroup , SIGNAL ( triggered ( bool ) ) , SLOT ( deleteGroup ( ) ) ) ;
actions . append ( actionDeleteGroup ) ;
}
}
QMenu myMenu ;
myMenu . addActions ( actions ) ;
/*
if ( onInstance )
myMenu . setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
*/
myMenu . exec ( view - > mapToGlobal ( pos ) ) ;
2014-01-05 00:06:59 +00:00
}
2022-04-15 23:25:37 +01:00
void MainWindow : : updateMainToolBar ( )
{
ui - > menuBar - > setVisible ( APPLICATION - > settings ( ) - > get ( " MenuBarInsteadOfToolBar " ) . toBool ( ) ) ;
ui - > mainToolBar - > setVisible ( ui - > menuBar - > isNativeMenuBar ( ) | | ! APPLICATION - > settings ( ) - > get ( " MenuBarInsteadOfToolBar " ) . toBool ( ) ) ;
}
2014-02-16 10:49:55 +00:00
void MainWindow : : updateToolsMenu ( )
{
2022-06-19 19:33:34 +01:00
bool currentInstanceRunning = m_selectedInstance & & m_selectedInstance - > isRunning ( ) ;
ui - > actionLaunchInstance - > setDisabled ( ! m_selectedInstance | | currentInstanceRunning ) ;
ui - > actionLaunchInstanceOffline - > setDisabled ( ! m_selectedInstance | | currentInstanceRunning ) ;
2022-07-11 19:46:11 +01:00
ui - > actionLaunchInstanceDemo - > setDisabled ( ! m_selectedInstance | | currentInstanceRunning ) ;
2018-07-15 13:51:05 +01:00
QMenu * launchMenu = ui - > actionLaunchInstance - > menu ( ) ;
if ( launchMenu )
{
launchMenu - > clear ( ) ;
}
else
{
launchMenu = new QMenu ( this ) ;
}
QAction * normalLaunch = launchMenu - > addAction ( tr ( " Launch " ) ) ;
2022-04-16 08:32:08 +01:00
normalLaunch - > setShortcut ( QKeySequence : : Open ) ;
2022-10-10 22:20:21 +01:00
QAction * normalLaunchOffline = launchMenu - > addAction ( tr ( " Launch Offline " ) ) ;
2022-04-16 08:32:08 +01:00
normalLaunchOffline - > setShortcut ( QKeySequence ( tr ( " Ctrl+Shift+O " ) ) ) ;
2022-10-10 22:20:21 +01:00
QAction * normalLaunchDemo = launchMenu - > addAction ( tr ( " Launch Demo " ) ) ;
2022-07-13 21:53:36 +01:00
normalLaunchDemo - > setShortcut ( QKeySequence ( tr ( " Ctrl+Alt+O " ) ) ) ;
2022-04-17 17:44:24 +01:00
if ( m_selectedInstance )
{
2022-06-19 19:33:34 +01:00
normalLaunch - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
normalLaunchOffline - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2022-07-11 19:46:11 +01:00
normalLaunchDemo - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2022-06-19 19:33:34 +01:00
2022-04-17 17:44:24 +01:00
connect ( normalLaunch , & QAction : : triggered , [ this ] ( ) {
2022-07-11 19:46:11 +01:00
APPLICATION - > launch ( m_selectedInstance , true , false ) ;
2022-04-17 17:44:24 +01:00
} ) ;
connect ( normalLaunchOffline , & QAction : : triggered , [ this ] ( ) {
2022-07-11 19:46:11 +01:00
APPLICATION - > launch ( m_selectedInstance , false , false ) ;
} ) ;
connect ( normalLaunchDemo , & QAction : : triggered , [ this ] ( ) {
APPLICATION - > launch ( m_selectedInstance , false , true ) ;
2022-04-17 17:44:24 +01:00
} ) ;
}
else
{
normalLaunch - > setDisabled ( true ) ;
normalLaunchOffline - > setDisabled ( true ) ;
2022-07-11 19:46:11 +01:00
normalLaunchDemo - > setDisabled ( true ) ;
2022-04-17 17:44:24 +01:00
}
2022-09-15 23:23:58 +01:00
// Disable demo-mode if not available.
auto instance = dynamic_cast < MinecraftInstance * > ( m_selectedInstance . get ( ) ) ;
if ( instance ) {
normalLaunchDemo - > setEnabled ( instance - > supportsDemo ( ) ) ;
}
2019-04-14 22:02:01 +01:00
QString profilersTitle = tr ( " Profilers " ) ;
launchMenu - > addSeparator ( ) - > setText ( profilersTitle ) ;
2021-11-20 15:22:22 +00:00
for ( auto profiler : APPLICATION - > profilers ( ) . values ( ) )
2018-07-15 13:51:05 +01:00
{
QAction * profilerAction = launchMenu - > addAction ( profiler - > name ( ) ) ;
2022-10-11 13:58:34 +01:00
QAction * profilerOfflineAction = launchMenu - > addAction ( tr ( " %1 Offline " ) . arg ( profiler - > name ( ) ) ) ;
2018-07-15 13:51:05 +01:00
QString error ;
if ( ! profiler - > check ( & error ) )
{
profilerAction - > setDisabled ( true ) ;
2019-04-14 23:42:06 +01:00
profilerOfflineAction - > setDisabled ( true ) ;
2019-04-14 22:02:01 +01:00
QString profilerToolTip = tr ( " Profiler not setup correctly. Go into settings, \" External Tools \" . " ) ;
profilerAction - > setToolTip ( profilerToolTip ) ;
profilerOfflineAction - > setToolTip ( profilerToolTip ) ;
2018-07-15 13:51:05 +01:00
}
2022-04-17 17:44:24 +01:00
else if ( m_selectedInstance )
2018-07-15 13:51:05 +01:00
{
2022-06-19 19:33:34 +01:00
profilerAction - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
profilerOfflineAction - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2018-07-15 13:51:05 +01:00
connect ( profilerAction , & QAction : : triggered , [ this , profiler ] ( )
{
2022-07-11 19:46:11 +01:00
APPLICATION - > launch ( m_selectedInstance , true , false , profiler . get ( ) ) ;
2018-07-15 13:51:05 +01:00
} ) ;
2019-04-14 23:42:06 +01:00
connect ( profilerOfflineAction , & QAction : : triggered , [ this , profiler ] ( )
{
2022-07-11 19:46:11 +01:00
APPLICATION - > launch ( m_selectedInstance , false , false , profiler . get ( ) ) ;
} ) ;
2018-07-15 13:51:05 +01:00
}
2022-04-17 17:44:24 +01:00
else
{
profilerAction - > setDisabled ( true ) ;
profilerOfflineAction - > setDisabled ( true ) ;
}
2018-07-15 13:51:05 +01:00
}
ui - > actionLaunchInstance - > setMenu ( launchMenu ) ;
2014-02-16 10:49:55 +00:00
}
2022-11-14 19:33:25 +00:00
void MainWindow : : updateThemeMenu ( )
{
QMenu * themeMenu = ui - > actionChangeTheme - > menu ( ) ;
2022-11-15 08:38:31 +00:00
if ( themeMenu ) {
2022-11-14 19:33:25 +00:00
themeMenu - > clear ( ) ;
2022-11-15 08:38:31 +00:00
} else {
2022-11-14 19:33:25 +00:00
themeMenu = new QMenu ( this ) ;
}
2022-11-14 22:59:26 +00:00
auto themes = APPLICATION - > getValidApplicationThemes ( ) ;
2022-11-17 09:20:53 +00:00
QActionGroup * themesGroup = new QActionGroup ( this ) ;
2022-11-14 22:59:26 +00:00
2022-11-16 15:24:28 +00:00
for ( auto * theme : themes ) {
2022-11-14 22:59:26 +00:00
QAction * themeAction = themeMenu - > addAction ( theme - > name ( ) ) ;
themeAction - > setCheckable ( true ) ;
2022-11-15 08:38:31 +00:00
if ( APPLICATION - > settings ( ) - > get ( " ApplicationTheme " ) . toString ( ) = = theme - > id ( ) ) {
themeAction - > setChecked ( true ) ;
}
2022-11-17 09:39:05 +00:00
themeAction - > setActionGroup ( themesGroup ) ;
2022-11-14 22:59:26 +00:00
connect ( themeAction , & QAction : : triggered , [ theme ] ( ) {
2022-10-22 18:43:04 +01:00
APPLICATION - > setApplicationTheme ( theme - > id ( ) ) ;
2022-11-15 09:09:13 +00:00
APPLICATION - > settings ( ) - > set ( " ApplicationTheme " , theme - > id ( ) ) ;
2022-11-14 22:59:26 +00:00
} ) ;
}
2022-11-14 19:33:25 +00:00
ui - > actionChangeTheme - > setMenu ( themeMenu ) ;
}
2013-11-27 22:39:49 +00:00
void MainWindow : : repopulateAccountsMenu ( )
{
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > clear ( ) ;
2018-07-15 13:51:05 +01:00
2021-11-20 15:22:22 +00:00
auto accounts = APPLICATION - > accounts ( ) ;
MinecraftAccountPtr defaultAccount = accounts - > defaultAccount ( ) ;
2018-07-15 13:51:05 +01:00
2021-07-26 20:44:11 +01:00
QString active_profileId = " " ;
2021-11-20 15:22:22 +00:00
if ( defaultAccount )
2018-07-15 13:51:05 +01:00
{
// this can be called before accountMenuButton exists
2023-01-26 22:48:21 +00:00
if ( ui - > actionAccountsButton )
2018-07-15 13:51:05 +01:00
{
2021-11-20 15:22:22 +00:00
auto profileLabel = profileInUseFilter ( defaultAccount - > profileName ( ) , defaultAccount - > isInUse ( ) ) ;
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setText ( profileLabel ) ;
2018-07-15 13:51:05 +01:00
}
}
if ( accounts - > count ( ) < = 0 )
{
2022-05-09 04:19:23 +01:00
ui - > actionNoAccountsAdded - > setEnabled ( false ) ;
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > addAction ( ui - > actionNoAccountsAdded ) ;
2018-07-15 13:51:05 +01:00
}
else
{
// TODO: Nicer way to iterate?
for ( int i = 0 ; i < accounts - > count ( ) ; i + + )
{
2021-07-26 20:44:11 +01:00
MinecraftAccountPtr account = accounts - > at ( i ) ;
auto profileLabel = profileInUseFilter ( account - > profileName ( ) , account - > isInUse ( ) ) ;
QAction * action = new QAction ( profileLabel , this ) ;
2021-11-10 02:02:51 +00:00
action - > setData ( i ) ;
2021-07-26 20:44:11 +01:00
action - > setCheckable ( true ) ;
2021-11-20 15:22:22 +00:00
if ( defaultAccount = = account )
2018-07-15 13:51:05 +01:00
{
2021-07-26 20:44:11 +01:00
action - > setChecked ( true ) ;
2018-07-15 13:51:05 +01:00
}
2021-07-26 20:44:11 +01:00
2021-11-10 02:02:51 +00:00
auto face = account - > getFace ( ) ;
if ( ! face . isNull ( ) ) {
action - > setIcon ( face ) ;
}
else {
2021-11-20 15:22:22 +00:00
action - > setIcon ( APPLICATION - > getThemedIcon ( " noaccount " ) ) ;
2021-11-10 02:02:51 +00:00
}
2022-04-16 00:55:49 +01:00
const int highestNumberKey = 9 ;
if ( i < highestNumberKey )
{
action - > setShortcut ( QKeySequence ( tr ( " Ctrl+%1 " ) . arg ( i + 1 ) ) ) ;
}
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > addAction ( action ) ;
2021-07-26 20:44:11 +01:00
connect ( action , SIGNAL ( triggered ( bool ) ) , SLOT ( changeActiveAccount ( ) ) ) ;
2018-07-15 13:51:05 +01:00
}
}
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > addSeparator ( ) ;
2018-07-15 13:51:05 +01:00
2022-05-09 04:19:23 +01:00
ui - > actionNoDefaultAccount - > setData ( - 1 ) ;
2023-01-26 22:48:21 +00:00
ui - > actionNoDefaultAccount - > setChecked ( ! defaultAccount ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > addAction ( ui - > actionNoDefaultAccount ) ;
2023-01-26 22:48:21 +00:00
2022-05-09 04:19:23 +01:00
connect ( ui - > actionNoDefaultAccount , SIGNAL ( triggered ( bool ) ) , SLOT ( changeActiveAccount ( ) ) ) ;
2018-07-15 13:51:05 +01:00
2022-12-31 00:08:10 +00:00
ui - > accountsMenu - > addSeparator ( ) ;
ui - > accountsMenu - > addAction ( ui - > actionManageAccounts ) ;
2013-11-27 22:39:49 +00:00
}
2017-05-02 00:43:18 +01:00
void MainWindow : : updatesAllowedChanged ( bool allowed )
{
2018-07-15 13:51:05 +01:00
if ( ! BuildConfig . UPDATER_ENABLED )
{
return ;
}
ui - > actionCheckUpdate - > setEnabled ( allowed ) ;
2017-05-02 00:43:18 +01:00
}
2013-11-27 22:39:49 +00:00
/*
* Assumes the sender is a QAction
*/
void MainWindow : : changeActiveAccount ( )
{
2018-07-15 13:51:05 +01:00
QAction * sAction = ( QAction * ) sender ( ) ;
2021-11-10 02:02:51 +00:00
2018-07-15 13:51:05 +01:00
// Profile's associated Mojang username
2021-11-10 02:02:51 +00:00
if ( sAction - > data ( ) . type ( ) ! = QVariant : : Type : : Int )
2018-07-15 13:51:05 +01:00
return ;
2013-11-27 22:39:49 +00:00
2018-07-15 13:51:05 +01:00
QVariant data = sAction - > data ( ) ;
2021-11-10 02:02:51 +00:00
bool valid = false ;
int index = data . toInt ( & valid ) ;
if ( ! valid ) {
index = - 1 ;
2018-07-15 13:51:05 +01:00
}
2021-11-20 15:22:22 +00:00
auto accounts = APPLICATION - > accounts ( ) ;
accounts - > setDefaultAccount ( index = = - 1 ? nullptr : accounts - > at ( index ) ) ;
defaultAccountChanged ( ) ;
2013-11-27 22:39:49 +00:00
}
2021-11-20 15:22:22 +00:00
void MainWindow : : defaultAccountChanged ( )
2013-11-27 16:56:15 +00:00
{
2018-07-15 13:51:05 +01:00
repopulateAccountsMenu ( ) ;
2013-11-27 22:39:49 +00:00
2021-11-20 15:22:22 +00:00
MinecraftAccountPtr account = APPLICATION - > accounts ( ) - > defaultAccount ( ) ;
2013-11-27 16:56:15 +00:00
2021-07-26 20:44:11 +01:00
// FIXME: this needs adjustment for MSA
2021-11-20 15:22:22 +00:00
if ( account & & account - > profileName ( ) ! = " " )
2018-07-15 13:51:05 +01:00
{
2021-07-26 20:44:11 +01:00
auto profileLabel = profileInUseFilter ( account - > profileName ( ) , account - > isInUse ( ) ) ;
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setText ( profileLabel ) ;
2021-11-10 02:02:51 +00:00
auto face = account - > getFace ( ) ;
if ( face . isNull ( ) ) {
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setIcon ( APPLICATION - > getThemedIcon ( " noaccount " ) ) ;
2021-11-10 02:02:51 +00:00
}
else {
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setIcon ( face ) ;
2021-11-10 02:02:51 +00:00
}
2021-07-26 20:44:11 +01:00
return ;
2018-07-15 13:51:05 +01:00
}
2013-11-27 22:39:49 +00:00
2018-07-15 13:51:05 +01:00
// Set the icon to the "no account" icon.
2023-01-26 22:48:21 +00:00
ui - > actionAccountsButton - > setIcon ( APPLICATION - > getThemedIcon ( " noaccount " ) ) ;
ui - > actionAccountsButton - > setText ( tr ( " Accounts " ) ) ;
2013-11-27 16:56:15 +00:00
}
2013-10-06 00:13:40 +01:00
bool MainWindow : : eventFilter ( QObject * obj , QEvent * ev )
2013-08-11 23:39:19 +01:00
{
2018-07-15 13:51:05 +01:00
if ( obj = = view )
{
if ( ev - > type ( ) = = QEvent : : KeyPress )
{
secretEventFilter - > input ( ev ) ;
QKeyEvent * keyEvent = static_cast < QKeyEvent * > ( ev ) ;
switch ( keyEvent - > key ( ) )
{
2018-11-22 00:50:32 +00:00
/*
2018-07-15 13:51:05 +01:00
case Qt : : Key_Enter :
case Qt : : Key_Return :
activateInstance ( m_selectedInstance ) ;
return true ;
2018-11-22 00:50:32 +00:00
*/
2018-07-15 13:51:05 +01:00
case Qt : : Key_Delete :
on_actionDeleteInstance_triggered ( ) ;
return true ;
case Qt : : Key_F5 :
refreshInstances ( ) ;
return true ;
case Qt : : Key_F2 :
on_actionRenameInstance_triggered ( ) ;
return true ;
default :
break ;
}
}
}
return QMainWindow : : eventFilter ( obj , ev ) ;
2013-08-11 23:39:19 +01:00
}
2022-02-10 11:55:07 +00:00
void MainWindow : : updateNewsLabel ( )
{
if ( m_newsChecker - > isLoadingNews ( ) )
{
newsLabel - > setText ( tr ( " Loading news... " ) ) ;
newsLabel - > setEnabled ( false ) ;
2022-08-12 21:33:10 +01:00
ui - > actionMoreNews - > setVisible ( false ) ;
2022-02-10 11:55:07 +00:00
}
else
{
QList < NewsEntryPtr > entries = m_newsChecker - > getNewsEntries ( ) ;
if ( entries . length ( ) > 0 )
{
newsLabel - > setText ( entries [ 0 ] - > title ) ;
newsLabel - > setEnabled ( true ) ;
2022-08-12 21:33:10 +01:00
ui - > actionMoreNews - > setVisible ( true ) ;
2022-02-10 11:55:07 +00:00
}
else
{
newsLabel - > setText ( tr ( " No news available. " ) ) ;
newsLabel - > setEnabled ( false ) ;
2022-08-12 21:33:10 +01:00
ui - > actionMoreNews - > setVisible ( false ) ;
2022-02-10 11:55:07 +00:00
}
}
}
2015-02-08 16:56:14 +00:00
void MainWindow : : updateAvailable ( GoUpdate : : Status status )
2013-12-01 23:55:24 +00:00
{
2021-11-20 15:22:22 +00:00
if ( ! APPLICATION - > updatesAreAllowed ( ) )
2018-07-15 13:51:05 +01:00
{
updateNotAvailable ( ) ;
return ;
}
UpdateDialog dlg ( true , this ) ;
UpdateAction action = ( UpdateAction ) dlg . exec ( ) ;
switch ( action )
{
case UPDATE_LATER :
qDebug ( ) < < " Update will be installed later. " ;
break ;
case UPDATE_NOW :
downloadUpdates ( status ) ;
break ;
}
2013-12-01 23:55:24 +00:00
}
2014-07-13 23:57:54 +01:00
void MainWindow : : updateNotAvailable ( )
{
2018-07-15 13:51:05 +01:00
UpdateDialog dlg ( false , this ) ;
dlg . exec ( ) ;
2014-07-13 23:57:54 +01:00
}
2014-01-03 18:19:27 +00:00
QList < int > stringToIntList ( const QString & string )
{
2022-05-02 18:10:45 +01:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QStringList split = string . split ( ' , ' , Qt : : SkipEmptyParts ) ;
# else
2018-07-15 13:51:05 +01:00
QStringList split = string . split ( ' , ' , QString : : SkipEmptyParts ) ;
2022-05-02 18:10:45 +01:00
# endif
2018-07-15 13:51:05 +01:00
QList < int > out ;
for ( int i = 0 ; i < split . size ( ) ; + + i )
{
out . append ( split . at ( i ) . toInt ( ) ) ;
}
return out ;
2014-01-03 18:19:27 +00:00
}
QString intListToString ( const QList < int > & list )
{
2018-07-15 13:51:05 +01:00
QStringList slist ;
for ( int i = 0 ; i < list . size ( ) ; + + i )
{
slist . append ( QString : : number ( list . at ( i ) ) ) ;
}
return slist . join ( ' , ' ) ;
2014-01-03 18:19:27 +00:00
}
2015-06-07 22:42:22 +01:00
void MainWindow : : downloadUpdates ( GoUpdate : : Status status )
2013-12-06 18:59:58 +00:00
{
2021-11-20 15:22:22 +00:00
if ( ! APPLICATION - > updatesAreAllowed ( ) )
2018-07-15 13:51:05 +01:00
{
return ;
}
qDebug ( ) < < " Downloading updates. " ;
ProgressDialog updateDlg ( this ) ;
2021-11-20 15:22:22 +00:00
status . rootPath = APPLICATION - > root ( ) ;
2018-07-15 13:51:05 +01:00
2021-11-20 15:22:22 +00:00
auto dlPath = FS : : PathCombine ( APPLICATION - > root ( ) , " update " , " XXXXXX " ) ;
2018-07-15 13:51:05 +01:00
if ( ! FS : : ensureFilePathExists ( dlPath ) )
{
CustomMessageBox : : selectable ( this , tr ( " Error " ) , tr ( " Couldn't create folder for update downloads: \n %1 " ) . arg ( dlPath ) , QMessageBox : : Warning ) - > show ( ) ;
}
2021-11-21 22:21:12 +00:00
GoUpdate : : DownloadTask updateTask ( APPLICATION - > network ( ) , status , dlPath , & updateDlg ) ;
2018-07-15 13:51:05 +01:00
// If the task succeeds, install the updates.
if ( updateDlg . execWithTask ( & updateTask ) )
{
/**
* NOTE : This disables launching instances until the update either succeeds ( and this process exits )
* or the update fails ( and the control leaves this scope ) .
*/
2021-11-20 15:22:22 +00:00
APPLICATION - > updateIsRunning ( true ) ;
UpdateController update ( this , APPLICATION - > root ( ) , updateTask . updateFilesDir ( ) , updateTask . operations ( ) ) ;
2018-07-15 13:51:05 +01:00
update . installUpdates ( ) ;
2021-11-20 15:22:22 +00:00
APPLICATION - > updateIsRunning ( false ) ;
2018-07-15 13:51:05 +01:00
}
else
{
CustomMessageBox : : selectable ( this , tr ( " Error " ) , updateTask . failReason ( ) , QMessageBox : : Warning ) - > show ( ) ;
}
2013-12-06 18:59:58 +00:00
}
2013-10-06 00:13:40 +01:00
void MainWindow : : onCatToggled ( bool state )
2013-08-25 21:48:41 +01:00
{
2018-07-15 13:51:05 +01:00
setCatBackground ( state ) ;
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " TheCat " , state ) ;
2013-08-25 21:48:41 +01:00
}
2013-10-06 00:13:40 +01:00
void MainWindow : : setCatBackground ( bool enabled )
2013-08-25 21:48:41 +01:00
{
2023-01-09 15:58:27 +00:00
if ( enabled ) {
2018-12-24 02:26:14 +00:00
view - > setStyleSheet ( QString ( R " (
2021-10-25 22:51:42 +01:00
InstanceView
2018-07-23 23:42:18 +01:00
{
2018-12-24 02:26:14 +00:00
background - image : url ( : / backgrounds / % 1 ) ;
2018-07-23 23:42:18 +01:00
background - attachment : fixed ;
background - clip : padding ;
2022-12-14 07:36:35 +00:00
background - position : bottom right ;
2018-07-23 23:42:18 +01:00
background - repeat : none ;
background - color : palette ( base ) ;
2022-11-01 22:06:27 +00:00
} ) " )
2023-01-09 15:58:27 +00:00
. arg ( ThemeManager : : getCatImage ( ) ) ) ;
} else {
2018-07-15 13:51:05 +01:00
view - > setStyleSheet ( QString ( ) ) ;
}
2013-08-25 21:48:41 +01:00
}
2016-10-02 23:55:54 +01:00
void MainWindow : : runModalTask ( Task * task )
2015-01-27 21:31:07 +00:00
{
2018-07-15 13:51:05 +01:00
connect ( task , & Task : : failed , [ this ] ( QString reason )
{
CustomMessageBox : : selectable ( this , tr ( " Error " ) , reason , QMessageBox : : Critical ) - > show ( ) ;
} ) ;
connect ( task , & Task : : succeeded , [ this , task ] ( )
{
QStringList warnings = task - > warnings ( ) ;
if ( warnings . count ( ) )
{
CustomMessageBox : : selectable ( this , tr ( " Warnings " ) , warnings . join ( ' \n ' ) , QMessageBox : : Warning ) - > show ( ) ;
}
} ) ;
2022-07-28 19:58:04 +01:00
connect ( task , & Task : : aborted , [ this ]
{
CustomMessageBox : : selectable ( this , tr ( " Task aborted " ) , tr ( " The task has been aborted by the user. " ) , QMessageBox : : Information ) - > show ( ) ;
} ) ;
2018-07-15 13:51:05 +01:00
ProgressDialog loadDialog ( this ) ;
loadDialog . setSkipButton ( true , tr ( " Abort " ) ) ;
loadDialog . execWithTask ( task ) ;
2016-10-02 23:55:54 +01:00
}
2015-02-12 21:01:20 +00:00
2018-03-19 01:36:12 +00:00
void MainWindow : : instanceFromInstanceTask ( InstanceTask * rawTask )
2016-10-02 23:55:54 +01:00
{
2021-11-20 15:22:22 +00:00
unique_qobject_ptr < Task > task ( APPLICATION - > instances ( ) - > wrapInstanceTask ( rawTask ) ) ;
2018-07-15 13:51:05 +01:00
runModalTask ( task . get ( ) ) ;
2018-02-28 18:42:30 +00:00
}
2016-10-02 23:55:54 +01:00
void MainWindow : : on_actionCopyInstance_triggered ( )
2015-01-27 21:31:07 +00:00
{
2018-07-15 13:51:05 +01:00
if ( ! m_selectedInstance )
return ;
2015-02-01 02:08:25 +00:00
2018-07-15 13:51:05 +01:00
CopyInstanceDialog copyInstDlg ( m_selectedInstance , this ) ;
if ( ! copyInstDlg . exec ( ) )
return ;
2015-01-27 21:31:07 +00:00
2022-10-23 04:04:36 +01:00
auto copyTask = new InstanceCopyTask ( m_selectedInstance , copyInstDlg . getChosenOptions ( ) ) ;
2018-07-15 13:51:05 +01:00
copyTask - > setName ( copyInstDlg . instName ( ) ) ;
copyTask - > setGroup ( copyInstDlg . instGroup ( ) ) ;
copyTask - > setIcon ( copyInstDlg . iconKey ( ) ) ;
2021-11-20 15:22:22 +00:00
unique_qobject_ptr < Task > task ( APPLICATION - > instances ( ) - > wrapInstanceTask ( copyTask ) ) ;
2018-07-15 13:51:05 +01:00
runModalTask ( task . get ( ) ) ;
2015-01-27 21:31:07 +00:00
}
2015-02-12 21:01:20 +00:00
2015-01-27 21:31:07 +00:00
void MainWindow : : finalizeInstance ( InstancePtr inst )
{
2018-07-15 13:51:05 +01:00
view - > updateGeometries ( ) ;
setSelectedInstanceById ( inst - > id ( ) ) ;
2021-11-20 15:22:22 +00:00
if ( APPLICATION - > accounts ( ) - > anyAccountIsValid ( ) )
2018-07-15 13:51:05 +01:00
{
ProgressDialog loadDialog ( this ) ;
auto update = inst - > createUpdateTask ( Net : : Mode : : Online ) ;
connect ( update . get ( ) , & Task : : failed , [ this ] ( QString reason )
{
QString error = QString ( " Instance load failed: %1 " ) . arg ( reason ) ;
CustomMessageBox : : selectable ( this , tr ( " Error " ) , error , QMessageBox : : Warning ) - > show ( ) ;
} ) ;
if ( update )
{
loadDialog . setSkipButton ( true , tr ( " Abort " ) ) ;
loadDialog . execWithTask ( update . get ( ) ) ;
}
}
else
{
2021-10-17 23:47:02 +01:00
CustomMessageBox : : selectable (
this ,
tr ( " Error " ) ,
tr ( " The launcher cannot download Minecraft or update instances unless you have at least "
" one account added. \n Please add your Mojang or Minecraft account. " ) ,
QMessageBox : : Warning
) - > show ( ) ;
2018-07-15 13:51:05 +01:00
}
2013-01-09 18:22:22 +00:00
}
2017-04-22 05:11:26 +01:00
void MainWindow : : addInstance ( QString url )
2015-01-27 21:31:07 +00:00
{
2018-07-15 13:51:05 +01:00
QString groupName ;
do
{
QObject * obj = sender ( ) ;
if ( ! obj )
break ;
QAction * action = qobject_cast < QAction * > ( obj ) ;
if ( ! action )
break ;
auto map = action - > data ( ) . toMap ( ) ;
if ( ! map . contains ( " group " ) )
break ;
groupName = map [ " group " ] . toString ( ) ;
} while ( 0 ) ;
if ( groupName . isEmpty ( ) )
{
2021-11-20 15:22:22 +00:00
groupName = APPLICATION - > settings ( ) - > get ( " LastUsedGroupForNewInstance " ) . toString ( ) ;
2018-07-15 13:51:05 +01:00
}
NewInstanceDialog newInstDlg ( groupName , url , this ) ;
if ( ! newInstDlg . exec ( ) )
return ;
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " LastUsedGroupForNewInstance " , newInstDlg . instGroup ( ) ) ;
2018-07-15 13:51:05 +01:00
InstanceTask * creationTask = newInstDlg . extractTask ( ) ;
if ( creationTask )
{
instanceFromInstanceTask ( creationTask ) ;
}
2015-01-27 21:31:07 +00:00
}
2017-04-22 05:11:26 +01:00
void MainWindow : : on_actionAddInstance_triggered ( )
{
2018-07-15 13:51:05 +01:00
addInstance ( ) ;
2017-04-22 05:11:26 +01:00
}
2022-12-31 01:06:17 +00:00
void MainWindow : : processURLs ( QList < QUrl > urls )
2017-04-22 05:11:26 +01:00
{
2022-11-27 17:38:56 +00:00
// NOTE: This loop only processes one dropped file!
2022-11-19 16:28:35 +00:00
for ( auto & url : urls ) {
2023-01-13 20:11:20 +00:00
qDebug ( ) < < " Processing " < < url ;
2022-12-31 01:06:17 +00:00
2022-12-02 01:54:03 +00:00
// The isLocalFile() check below doesn't work as intended without an explicit scheme.
if ( url . scheme ( ) . isEmpty ( ) )
url . setScheme ( " file " ) ;
2022-11-27 17:38:56 +00:00
if ( ! url . isLocalFile ( ) ) { // probably instance/modpack
2018-07-15 13:51:05 +01:00
addInstance ( url . toString ( ) ) ;
2022-11-27 17:38:56 +00:00
break ;
2018-07-15 13:51:05 +01:00
}
2022-11-19 16:28:35 +00:00
2023-01-02 15:55:32 +00:00
auto localFileName = QDir : : toNativeSeparators ( url . toLocalFile ( ) ) ;
2022-11-27 17:38:56 +00:00
QFileInfo localFileInfo ( localFileName ) ;
2022-12-31 01:06:17 +00:00
auto type = ResourceUtils : : identify ( localFileInfo ) ;
2022-11-27 17:38:56 +00:00
2023-01-13 20:11:20 +00:00
if ( ResourceUtils : : ValidResourceTypes . count ( type ) = = 0 ) { // probably instance/modpack
2022-11-27 17:38:56 +00:00
addInstance ( localFileName ) ;
2022-12-31 01:06:17 +00:00
continue ;
2022-11-27 17:38:56 +00:00
}
2022-12-31 01:06:17 +00:00
ImportResourceDialog dlg ( localFileName , type , this ) ;
2022-11-27 17:38:56 +00:00
if ( dlg . exec ( ) ! = QDialog : : Accepted )
2022-12-31 01:06:17 +00:00
continue ;
2022-11-27 17:38:56 +00:00
2022-12-31 01:06:17 +00:00
qDebug ( ) < < " Adding resource " < < localFileName < < " to " < < dlg . selectedInstanceKey ;
2022-11-27 17:38:56 +00:00
auto inst = APPLICATION - > instances ( ) - > getInstanceById ( dlg . selectedInstanceKey ) ;
auto minecraftInst = std : : dynamic_pointer_cast < MinecraftInstance > ( inst ) ;
2022-12-31 01:06:17 +00:00
switch ( type ) {
case PackedResourceType : : ResourcePack :
2022-12-31 02:27:26 +00:00
minecraftInst - > resourcePackList ( ) - > installResource ( localFileName ) ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : TexturePack :
2022-12-31 02:27:26 +00:00
minecraftInst - > texturePackList ( ) - > installResource ( localFileName ) ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : DataPack :
2022-12-31 02:27:26 +00:00
qWarning ( ) < < " Importing of Data Packs not supported at this time. Ignoring " < < localFileName ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : Mod :
2022-12-31 02:27:26 +00:00
minecraftInst - > loaderModList ( ) - > installMod ( localFileName ) ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : ShaderPack :
2022-12-31 02:27:26 +00:00
minecraftInst - > shaderPackList ( ) - > installResource ( localFileName ) ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : WorldSave :
2022-12-31 02:27:26 +00:00
minecraftInst - > worldList ( ) - > installWorld ( localFileInfo ) ;
break ;
2022-12-31 01:06:17 +00:00
case PackedResourceType : : UNKNOWN :
default :
2022-12-31 02:27:26 +00:00
qDebug ( ) < < " Can't Identify " < < localFileName < < " Ignoring it. " ;
break ;
2022-12-31 01:06:17 +00:00
}
2018-07-15 13:51:05 +01:00
}
2017-04-22 05:11:26 +01:00
}
2015-09-15 22:02:21 +01:00
void MainWindow : : on_actionREDDIT_triggered ( )
{
2021-06-18 12:24:20 +01:00
DesktopServices : : openUrl ( QUrl ( BuildConfig . SUBREDDIT_URL ) ) ;
2015-09-15 22:02:21 +01:00
}
2016-01-09 00:39:51 +00:00
void MainWindow : : on_actionDISCORD_triggered ( )
{
2021-06-18 12:24:20 +01:00
DesktopServices : : openUrl ( QUrl ( BuildConfig . DISCORD_URL ) ) ;
2016-01-09 00:39:51 +00:00
}
2022-03-08 17:41:23 +00:00
void MainWindow : : on_actionMATRIX_triggered ( )
{
DesktopServices : : openUrl ( QUrl ( BuildConfig . MATRIX_URL ) ) ;
}
2013-08-10 17:34:08 +01:00
void MainWindow : : on_actionChangeInstIcon_triggered ( )
2013-03-19 05:24:34 +00:00
{
2018-07-15 13:51:05 +01:00
if ( ! m_selectedInstance )
return ;
2013-10-06 00:13:40 +01:00
2018-07-15 13:51:05 +01:00
IconPickerDialog dlg ( this ) ;
dlg . execWithSelection ( m_selectedInstance - > iconKey ( ) ) ;
if ( dlg . result ( ) = = QDialog : : Accepted )
{
m_selectedInstance - > setIconKey ( dlg . selectedIconKey ) ;
2021-11-20 15:22:22 +00:00
auto icon = APPLICATION - > icons ( ) - > getIcon ( dlg . selectedIconKey ) ;
2018-07-15 13:51:05 +01:00
ui - > actionChangeInstIcon - > setIcon ( icon ) ;
2022-12-31 00:08:10 +00:00
changeIconButton - > setIcon ( icon ) ;
2018-07-15 13:51:05 +01:00
}
2013-03-19 05:24:34 +00:00
}
2013-12-31 00:24:28 +00:00
void MainWindow : : iconUpdated ( QString icon )
{
2018-07-15 13:51:05 +01:00
if ( icon = = m_currentInstIcon )
{
2021-11-20 15:22:22 +00:00
auto icon = APPLICATION - > icons ( ) - > getIcon ( m_currentInstIcon ) ;
2018-07-15 13:51:05 +01:00
ui - > actionChangeInstIcon - > setIcon ( icon ) ;
2022-12-31 00:08:10 +00:00
changeIconButton - > setIcon ( icon ) ;
2018-07-15 13:51:05 +01:00
}
2013-03-19 05:24:34 +00:00
}
2013-12-31 00:24:28 +00:00
void MainWindow : : updateInstanceToolIcon ( QString new_icon )
{
2018-07-15 13:51:05 +01:00
m_currentInstIcon = new_icon ;
2021-11-20 15:22:22 +00:00
auto icon = APPLICATION - > icons ( ) - > getIcon ( m_currentInstIcon ) ;
2018-07-15 13:51:05 +01:00
ui - > actionChangeInstIcon - > setIcon ( icon ) ;
2022-12-31 00:08:10 +00:00
changeIconButton - > setIcon ( icon ) ;
2013-12-31 00:24:28 +00:00
}
2014-01-06 09:01:40 +00:00
void MainWindow : : setSelectedInstanceById ( const QString & id )
{
2018-07-15 13:51:05 +01:00
if ( id . isNull ( ) )
return ;
2021-11-20 15:22:22 +00:00
const QModelIndex index = APPLICATION - > instances ( ) - > getInstanceIndexById ( id ) ;
2018-07-15 13:51:05 +01:00
if ( index . isValid ( ) )
{
QModelIndex selectionIndex = proxymodel - > mapFromSource ( index ) ;
view - > selectionModel ( ) - > setCurrentIndex ( selectionIndex , QItemSelectionModel : : ClearAndSelect ) ;
2019-07-10 03:23:24 +01:00
updateStatusCenter ( ) ;
2018-07-15 13:51:05 +01:00
}
2014-01-06 09:01:40 +00:00
}
2013-08-10 17:34:08 +01:00
void MainWindow : : on_actionChangeInstGroup_triggered ( )
{
2018-07-15 13:51:05 +01:00
if ( ! m_selectedInstance )
return ;
2013-10-06 00:13:40 +01:00
2018-07-15 13:51:05 +01:00
bool ok = false ;
2018-07-31 00:54:08 +01:00
InstanceId instId = m_selectedInstance - > id ( ) ;
2021-11-20 15:22:22 +00:00
QString name ( APPLICATION - > instances ( ) - > getInstanceGroup ( instId ) ) ;
auto groups = APPLICATION - > instances ( ) - > getGroups ( ) ;
2018-07-15 13:51:05 +01:00
groups . insert ( 0 , " " ) ;
groups . sort ( Qt : : CaseInsensitive ) ;
int foo = groups . indexOf ( name ) ;
2013-12-15 17:10:51 +00:00
2018-07-15 13:51:05 +01:00
name = QInputDialog : : getItem ( this , tr ( " Group name " ) , tr ( " Enter a new group name. " ) , groups , foo , true , & ok ) ;
name = name . simplified ( ) ;
if ( ok )
2018-07-31 00:54:08 +01:00
{
2021-11-20 15:22:22 +00:00
APPLICATION - > instances ( ) - > setInstanceGroup ( instId , name ) ;
2018-07-31 00:54:08 +01:00
}
2013-08-10 17:34:08 +01:00
}
2017-12-13 23:29:00 +00:00
void MainWindow : : deleteGroup ( )
2016-04-11 00:30:50 +01:00
{
2018-07-15 13:51:05 +01:00
QObject * obj = sender ( ) ;
if ( ! obj )
return ;
QAction * action = qobject_cast < QAction * > ( obj ) ;
if ( ! action )
return ;
auto map = action - > data ( ) . toMap ( ) ;
if ( ! map . contains ( " group " ) )
return ;
QString groupName = map [ " group " ] . toString ( ) ;
if ( ! groupName . isEmpty ( ) )
{
2022-03-18 12:19:09 +00:00
auto reply = QMessageBox : : question ( this , tr ( " Delete group " ) , tr ( " Are you sure you want to delete the group %1? " )
2018-11-08 16:30:30 +00:00
. arg ( groupName ) , QMessageBox : : Yes | QMessageBox : : No ) ;
if ( reply = = QMessageBox : : Yes )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > instances ( ) - > deleteGroup ( groupName ) ;
2018-11-08 16:30:30 +00:00
}
2018-07-15 13:51:05 +01:00
}
2016-04-11 00:30:50 +01:00
}
2022-07-30 18:42:33 +01:00
void MainWindow : : undoTrashInstance ( )
{
APPLICATION - > instances ( ) - > undoTrashInstance ( ) ;
2022-10-30 17:37:03 +00:00
ui - > actionUndoTrashInstance - > setEnabled ( APPLICATION - > instances ( ) - > trashedSomething ( ) ) ;
2022-07-30 18:42:33 +01:00
}
2013-01-09 18:22:22 +00:00
void MainWindow : : on_actionViewInstanceFolder_triggered ( )
{
2021-11-20 15:22:22 +00:00
QString str = APPLICATION - > settings ( ) - > get ( " InstanceDir " ) . toString ( ) ;
2018-07-15 13:51:05 +01:00
DesktopServices : : openDirectory ( str ) ;
2013-01-09 18:22:22 +00:00
}
2017-12-13 23:29:00 +00:00
void MainWindow : : refreshInstances ( )
2013-01-09 18:22:22 +00:00
{
2021-11-20 15:22:22 +00:00
APPLICATION - > instances ( ) - > loadList ( ) ;
2013-01-09 18:22:22 +00:00
}
void MainWindow : : on_actionViewCentralModsFolder_triggered ( )
{
2021-11-20 15:22:22 +00:00
DesktopServices : : openDirectory ( APPLICATION - > settings ( ) - > get ( " CentralModsDir " ) . toString ( ) , true ) ;
2013-01-09 18:22:22 +00:00
}
2017-12-13 23:29:00 +00:00
void MainWindow : : checkForUpdates ( )
2013-01-09 18:22:22 +00:00
{
2018-07-15 13:51:05 +01:00
if ( BuildConfig . UPDATER_ENABLED )
{
2021-11-20 15:22:22 +00:00
auto updater = APPLICATION - > updateChecker ( ) ;
updater - > checkForUpdate ( APPLICATION - > settings ( ) - > get ( " UpdateChannel " ) . toString ( ) , true ) ;
2018-07-15 13:51:05 +01:00
}
else
{
qWarning ( ) < < " Updater not set up. Cannot check for updates. " ;
}
2013-01-09 18:22:22 +00:00
}
2014-07-15 23:13:40 +01:00
void MainWindow : : on_actionSettings_triggered ( )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > ShowGlobalSettings ( this , " global-settings " ) ;
2019-06-01 11:28:53 +01:00
}
void MainWindow : : globalSettingsClosed ( )
{
2018-07-15 13:51:05 +01:00
// FIXME: quick HACK to make this work. improve, optimize.
2021-11-20 15:22:22 +00:00
APPLICATION - > instances ( ) - > loadList ( ) ;
2018-07-15 13:51:05 +01:00
proxymodel - > invalidate ( ) ;
proxymodel - > sort ( 0 ) ;
2022-04-15 23:25:37 +01:00
updateMainToolBar ( ) ;
2018-07-15 13:51:05 +01:00
updateToolsMenu ( ) ;
2022-11-15 08:46:24 +00:00
updateThemeMenu ( ) ;
2021-10-13 22:14:02 +01:00
updateStatusCenter ( ) ;
2022-05-17 00:21:57 +01:00
// This needs to be done to prevent UI elements disappearing in the event the config is changed
2022-10-18 15:37:04 +01:00
// but Prism Launcher exits abnormally, causing the window state to never be saved:
2022-05-17 00:21:57 +01:00
APPLICATION - > settings ( ) - > set ( " MainWindowState " , saveState ( ) . toBase64 ( ) ) ;
2018-07-15 13:51:05 +01:00
update ( ) ;
2014-07-15 23:13:40 +01:00
}
2014-06-18 00:15:01 +01:00
void MainWindow : : on_actionEditInstance_triggered ( )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > showInstanceWindow ( m_selectedInstance ) ;
2014-06-18 00:15:01 +01:00
}
2013-11-20 18:20:35 +00:00
void MainWindow : : on_actionManageAccounts_triggered ( )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > ShowGlobalSettings ( this , " accounts " ) ;
2013-11-20 18:20:35 +00:00
}
2013-01-09 18:22:22 +00:00
void MainWindow : : on_actionReportBug_triggered ( )
{
2021-06-18 12:24:20 +01:00
DesktopServices : : openUrl ( QUrl ( BuildConfig . BUG_TRACKER_URL ) ) ;
2013-01-09 18:22:22 +00:00
}
2022-10-10 11:45:44 +01:00
void MainWindow : : on_actionClearMetadata_triggered ( )
{
APPLICATION - > metacache ( ) - > evictAll ( ) ;
2022-11-06 00:05:10 +00:00
APPLICATION - > metacache ( ) - > SaveNow ( ) ;
2022-10-10 11:45:44 +01:00
}
2022-11-05 14:31:07 +00:00
# ifdef Q_OS_MAC
2022-11-14 17:37:24 +00:00
void MainWindow : : on_actionAddToPATH_triggered ( )
{
2022-11-05 14:15:31 +00:00
auto binaryPath = APPLICATION - > applicationFilePath ( ) ;
2022-11-14 17:37:24 +00:00
auto targetPath = QString ( " /usr/local/bin/%1 " ) . arg ( BuildConfig . LAUNCHER_APP_BINARY_NAME ) ;
qDebug ( ) < < " Symlinking " < < binaryPath < < " to " < < targetPath ;
QStringList args ;
args < < " -e " ;
args < < QString ( " do shell script \" mkdir -p /usr/local/bin && ln -sf '%1' '%2' \" with administrator privileges " )
. arg ( binaryPath , targetPath ) ;
auto outcome = QProcess : : execute ( " /usr/bin/osascript " , args ) ;
2022-10-19 14:53:57 +01:00
if ( ! outcome ) {
2022-11-14 17:37:24 +00:00
QMessageBox : : information ( this , tr ( " Successfully added %1 to PATH " ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ,
tr ( " %1 was successfully added to your PATH. You can now start it by running `%2`. " )
. arg ( BuildConfig . LAUNCHER_DISPLAYNAME , BuildConfig . LAUNCHER_APP_BINARY_NAME ) ) ;
2022-10-19 14:53:57 +01:00
} else {
2022-11-14 17:37:24 +00:00
QMessageBox : : critical ( this , tr ( " Failed to add %1 to PATH " ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ,
tr ( " An error occurred while trying to add %1 to PATH " ) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME ) ) ;
2022-10-19 14:53:57 +01:00
}
}
2022-11-05 14:31:07 +00:00
# endif
2022-10-19 14:53:57 +01:00
2022-04-08 20:37:18 +01:00
void MainWindow : : on_actionOpenWiki_triggered ( )
{
2022-04-15 21:44:27 +01:00
DesktopServices : : openUrl ( QUrl ( BuildConfig . HELP_URL . arg ( " " ) ) ) ;
2022-04-08 20:37:18 +01:00
}
2022-02-10 11:55:07 +00:00
void MainWindow : : on_actionMoreNews_triggered ( )
{
2022-06-26 00:15:16 +01:00
auto entries = m_newsChecker - > getNewsEntries ( ) ;
NewsDialog news_dialog ( entries , this ) ;
news_dialog . exec ( ) ;
2022-02-10 11:55:07 +00:00
}
void MainWindow : : newsButtonClicked ( )
{
2022-06-26 00:15:16 +01:00
auto entries = m_newsChecker - > getNewsEntries ( ) ;
NewsDialog news_dialog ( entries , this ) ;
news_dialog . toggleArticleList ( ) ;
news_dialog . exec ( ) ;
2022-02-10 11:55:07 +00:00
}
2023-01-20 14:13:25 +00:00
void MainWindow : : onCatChanged ( int ) {
setCatBackground ( APPLICATION - > settings ( ) - > get ( " TheCat " ) . toBool ( ) ) ;
}
2013-01-09 18:22:22 +00:00
void MainWindow : : on_actionAbout_triggered ( )
{
2018-07-15 13:51:05 +01:00
AboutDialog dialog ( this ) ;
dialog . exec ( ) ;
2013-01-09 18:22:22 +00:00
}
2013-01-30 05:52:37 +00:00
2013-06-23 21:10:32 +01:00
void MainWindow : : on_actionDeleteInstance_triggered ( )
{
2022-12-03 13:54:41 +00:00
if ( ! m_selectedInstance ) {
2018-07-15 13:51:05 +01:00
return ;
}
2022-07-30 18:42:33 +01:00
2019-06-17 15:45:32 +01:00
auto id = m_selectedInstance - > id ( ) ;
2022-12-03 13:54:41 +00:00
2022-12-17 09:26:06 +00:00
auto response = CustomMessageBox : : selectable ( this , tr ( " Confirm Deletion " ) ,
2022-12-26 14:33:50 +00:00
tr ( " You are about to delete \" %1 \" . \n "
2022-12-14 15:02:04 +00:00
" This may be permanent and will completely delete the instance. \n \n "
" Are you sure? " )
. arg ( m_selectedInstance - > name ( ) ) ,
QMessageBox : : Warning , QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : No )
- > exec ( ) ;
2022-12-03 13:54:41 +00:00
2022-12-14 15:02:04 +00:00
if ( response ! = QMessageBox : : Yes )
return ;
2022-12-03 13:54:41 +00:00
2022-12-14 15:02:04 +00:00
if ( APPLICATION - > instances ( ) - > trashInstance ( id ) ) {
ui - > actionUndoTrashInstance - > setEnabled ( APPLICATION - > instances ( ) - > trashedSomething ( ) ) ;
return ;
2018-07-15 13:51:05 +01:00
}
2022-12-14 15:02:04 +00:00
APPLICATION - > instances ( ) - > deleteInstance ( id ) ;
2013-06-23 21:10:32 +01:00
}
2015-02-12 21:01:20 +00:00
void MainWindow : : on_actionExportInstance_triggered ( )
{
2018-07-15 13:51:05 +01:00
if ( m_selectedInstance )
{
ExportInstanceDialog dlg ( m_selectedInstance , this ) ;
dlg . exec ( ) ;
}
2015-02-12 21:01:20 +00:00
}
2013-06-23 21:10:32 +01:00
void MainWindow : : on_actionRenameInstance_triggered ( )
{
2018-07-15 13:51:05 +01:00
if ( m_selectedInstance )
{
2018-11-22 00:50:32 +00:00
view - > edit ( view - > currentIndex ( ) ) ;
2018-07-15 13:51:05 +01:00
}
2013-06-23 21:10:32 +01:00
}
void MainWindow : : on_actionViewSelectedInstFolder_triggered ( )
{
2018-07-15 13:51:05 +01:00
if ( m_selectedInstance )
{
QString str = m_selectedInstance - > instanceRoot ( ) ;
DesktopServices : : openDirectory ( QDir ( str ) . absolutePath ( ) ) ;
}
2013-06-23 21:10:32 +01:00
}
2013-10-06 00:13:40 +01:00
void MainWindow : : closeEvent ( QCloseEvent * event )
2013-01-30 05:52:37 +00:00
{
2018-07-15 13:51:05 +01:00
// Save the window state and geometry.
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " MainWindowState " , saveState ( ) . toBase64 ( ) ) ;
APPLICATION - > settings ( ) - > set ( " MainWindowGeometry " , saveGeometry ( ) . toBase64 ( ) ) ;
2022-12-31 00:08:10 +00:00
instanceToolbarSetting - > set ( ui - > instanceToolBar - > getVisibilityState ( ) ) ;
2018-07-15 13:51:05 +01:00
event - > accept ( ) ;
emit isClosing ( ) ;
2013-01-30 05:52:37 +00:00
}
2013-03-11 21:19:17 +00:00
2016-12-05 01:29:08 +00:00
void MainWindow : : changeEvent ( QEvent * event )
{
2018-07-15 13:51:05 +01:00
if ( event - > type ( ) = = QEvent : : LanguageChange )
{
2021-06-19 00:12:54 +01:00
retranslateUi ( ) ;
2018-07-15 13:51:05 +01:00
}
QMainWindow : : changeEvent ( event ) ;
2016-12-05 01:29:08 +00:00
}
2013-10-21 21:25:50 +01:00
void MainWindow : : instanceActivated ( QModelIndex index )
{
2018-07-15 13:51:05 +01:00
if ( ! index . isValid ( ) )
return ;
QString id = index . data ( InstanceList : : InstanceIDRole ) . toString ( ) ;
2021-11-20 15:22:22 +00:00
InstancePtr inst = APPLICATION - > instances ( ) - > getInstanceById ( id ) ;
2018-07-15 13:51:05 +01:00
if ( ! inst )
return ;
2013-10-21 21:25:50 +01:00
2018-07-15 13:51:05 +01:00
activateInstance ( inst ) ;
2013-10-21 21:25:50 +01:00
}
2013-02-05 22:34:20 +00:00
void MainWindow : : on_actionLaunchInstance_triggered ( )
{
2022-06-19 19:33:34 +01:00
if ( m_selectedInstance & & ! m_selectedInstance - > isRunning ( ) )
2018-07-15 13:51:05 +01:00
{
2021-11-20 15:22:22 +00:00
APPLICATION - > launch ( m_selectedInstance ) ;
2018-07-15 13:51:05 +01:00
}
2013-02-05 22:34:20 +00:00
}
2016-11-26 17:06:08 +00:00
void MainWindow : : activateInstance ( InstancePtr instance )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > launch ( instance ) ;
2016-11-26 17:06:08 +00:00
}
2014-01-27 02:00:49 +00:00
void MainWindow : : on_actionLaunchInstanceOffline_triggered ( )
{
2018-07-15 13:51:05 +01:00
if ( m_selectedInstance )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > launch ( m_selectedInstance , false ) ;
2018-07-15 13:51:05 +01:00
}
2015-07-04 19:02:43 +01:00
}
2022-07-11 19:46:11 +01:00
void MainWindow : : on_actionLaunchInstanceDemo_triggered ( )
{
if ( m_selectedInstance )
{
APPLICATION - > launch ( m_selectedInstance , false , true ) ;
}
}
2022-06-19 19:33:34 +01:00
void MainWindow : : on_actionKillInstance_triggered ( )
{
if ( m_selectedInstance & & m_selectedInstance - > isRunning ( ) )
{
APPLICATION - > kill ( m_selectedInstance ) ;
}
}
2022-10-22 13:39:53 +01:00
void MainWindow : : on_actionCreateInstanceShortcut_triggered ( )
{
if ( m_selectedInstance )
{
2022-10-22 15:56:27 +01:00
auto desktopPath = FS : : getDesktopDir ( ) ;
if ( desktopPath . isEmpty ( ) ) {
2022-10-22 13:39:53 +01:00
// TODO come up with an alternative solution (open "save file" dialog)
2022-10-22 15:56:27 +01:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Couldn't find desktop?! " ) ) ;
2022-10-22 13:39:53 +01:00
return ;
}
2022-11-12 18:41:52 +00:00
# if defined(Q_OS_MACOS)
2022-11-13 13:47:37 +00:00
QString appPath = QApplication : : applicationFilePath ( ) ;
2022-11-13 15:51:29 +00:00
if ( appPath . startsWith ( " /private/var/ " ) ) {
2022-11-13 13:47:37 +00:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " The launcher is in the folder it was extracted from, therefore it cannot create shortcuts. " ) ) ;
return ;
2022-11-13 13:49:28 +00:00
}
2022-11-12 18:36:49 +00:00
2022-11-12 18:41:52 +00:00
if ( FS : : createShortcut ( FS : : PathCombine ( desktopPath , m_selectedInstance - > name ( ) ) ,
2022-11-13 15:51:29 +00:00
appPath , { " --launch " , m_selectedInstance - > id ( ) } ,
m_selectedInstance - > name ( ) , " " ) ) {
2022-11-12 18:36:49 +00:00
QMessageBox : : information ( this , tr ( " Create instance shortcut " ) , tr ( " Created a shortcut to this instance on your desktop! " ) ) ;
}
else
{
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create instance shortcut! " ) ) ;
}
2022-11-12 18:41:52 +00:00
# elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
2022-11-13 15:51:29 +00:00
QString appPath = QApplication : : applicationFilePath ( ) ;
if ( appPath . startsWith ( " /tmp/.mount_ " ) ) {
// AppImage!
appPath = QProcessEnvironment : : systemEnvironment ( ) . value ( QStringLiteral ( " APPIMAGE " ) ) ;
if ( appPath . isEmpty ( ) )
{
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing) " ) ) ;
}
else if ( appPath . endsWith ( " / " ) )
{
appPath . chop ( 1 ) ;
}
}
2022-10-25 15:37:30 +01:00
auto icon = APPLICATION - > icons ( ) - > icon ( m_selectedInstance - > iconKey ( ) ) ;
2022-11-13 18:18:51 +00:00
if ( icon = = nullptr )
{
icon = APPLICATION - > icons ( ) - > icon ( " grass " ) ;
}
2022-11-13 15:51:29 +00:00
QString iconPath = FS : : PathCombine ( m_selectedInstance - > instanceRoot ( ) , " icon.png " ) ;
2022-12-14 15:02:04 +00:00
2022-11-13 15:51:29 +00:00
QFile iconFile ( iconPath ) ;
if ( ! iconFile . open ( QFile : : WriteOnly ) )
{
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create icon for shortcut. " ) ) ;
return ;
}
bool success = icon - > icon ( ) . pixmap ( 64 , 64 ) . save ( & iconFile , " PNG " ) ;
iconFile . close ( ) ;
2022-12-14 15:02:04 +00:00
2022-11-13 15:51:29 +00:00
if ( ! success )
{
iconFile . remove ( ) ;
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create icon for shortcut. " ) ) ;
return ;
}
2022-12-08 13:46:58 +00:00
QString desktopFilePath = FS : : PathCombine ( desktopPath , m_selectedInstance - > name ( ) + " .desktop " ) ;
QStringList args ;
if ( DesktopServices : : isFlatpak ( ) ) {
QFileDialog fileDialog ;
// workaround to make sure the portal file dialog opens in the desktop directory
fileDialog . setDirectoryUrl ( desktopPath ) ;
desktopFilePath = fileDialog . getSaveFileName (
this , tr ( " Create Shortcut " ) , desktopFilePath ,
tr ( " Desktop Entries (*.desktop) " ) ) ;
if ( desktopFilePath . isEmpty ( ) )
return ; // file dialog canceled by user
appPath = " flatpak " ;
QString flatpakAppId = BuildConfig . LAUNCHER_DESKTOPFILENAME ;
flatpakAppId . remove ( " .desktop " ) ;
args . append ( { " run " , flatpakAppId } ) ;
}
args . append ( { " --launch " , m_selectedInstance - > id ( ) } ) ;
if ( FS : : createShortcut ( desktopFilePath , appPath , args , m_selectedInstance - > name ( ) , iconPath ) ) {
2022-11-12 18:41:52 +00:00
QMessageBox : : information ( this , tr ( " Create instance shortcut " ) , tr ( " Created a shortcut to this instance on your desktop! " ) ) ;
}
else
{
2022-11-13 15:51:29 +00:00
iconFile . remove ( ) ;
2022-11-12 18:41:52 +00:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create instance shortcut! " ) ) ;
}
# elif defined(Q_OS_WIN)
auto icon = APPLICATION - > icons ( ) - > icon ( m_selectedInstance - > iconKey ( ) ) ;
2022-11-13 18:18:51 +00:00
if ( icon = = nullptr )
{
icon = APPLICATION - > icons ( ) - > icon ( " grass " ) ;
}
2022-11-12 18:41:52 +00:00
QString iconPath = FS : : PathCombine ( m_selectedInstance - > instanceRoot ( ) , " icon.ico " ) ;
2022-12-14 15:02:04 +00:00
2022-10-28 19:11:51 +01:00
// part of fix for weird bug involving the window icon being replaced
// dunno why it happens, but this 2-line fix seems to be enough, so w/e
2022-11-09 19:55:13 +00:00
auto appIcon = APPLICATION - > getThemedIcon ( " logo " ) ;
2022-10-28 19:11:51 +01:00
2022-10-28 15:42:29 +01:00
QFile iconFile ( iconPath ) ;
if ( ! iconFile . open ( QFile : : WriteOnly ) )
{
2022-11-13 15:51:29 +00:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create icon for shortcut. " ) ) ;
2022-10-28 15:42:29 +01:00
return ;
}
2022-11-09 19:55:13 +00:00
bool success = icon - > icon ( ) . pixmap ( 64 , 64 ) . save ( & iconFile , " ICO " ) ;
iconFile . close ( ) ;
// restore original window icon
QGuiApplication : : setWindowIcon ( appIcon ) ;
2022-10-28 15:42:29 +01:00
2022-11-12 18:41:52 +00:00
if ( ! success )
2022-10-28 15:42:29 +01:00
{
iconFile . remove ( ) ;
2022-11-13 15:51:29 +00:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create icon for shortcut. " ) ) ;
2022-10-28 15:42:29 +01:00
return ;
}
2022-12-14 15:02:04 +00:00
2022-10-22 15:56:27 +01:00
if ( FS : : createShortcut ( FS : : PathCombine ( desktopPath , m_selectedInstance - > name ( ) ) ,
2022-11-13 15:51:29 +00:00
QApplication : : applicationFilePath ( ) , { " --launch " , m_selectedInstance - > id ( ) } ,
m_selectedInstance - > name ( ) , iconPath ) ) {
2022-10-22 15:56:27 +01:00
QMessageBox : : information ( this , tr ( " Create instance shortcut " ) , tr ( " Created a shortcut to this instance on your desktop! " ) ) ;
}
else
{
2022-11-12 18:43:58 +00:00
iconFile . remove ( ) ;
2022-10-22 15:56:27 +01:00
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Failed to create instance shortcut! " ) ) ;
}
2022-11-12 18:41:52 +00:00
# else
QMessageBox : : critical ( this , tr ( " Create instance shortcut " ) , tr ( " Not supported on your platform! " ) ) ;
# endif
2022-10-22 13:39:53 +01:00
}
}
2013-08-08 23:26:35 +01:00
void MainWindow : : taskEnd ( )
2013-05-06 23:19:20 +01:00
{
2018-07-15 13:51:05 +01:00
QObject * sender = QObject : : sender ( ) ;
if ( sender = = m_versionLoadTask )
m_versionLoadTask = NULL ;
2013-10-06 00:13:40 +01:00
2018-07-15 13:51:05 +01:00
sender - > deleteLater ( ) ;
2013-05-06 23:19:20 +01:00
}
void MainWindow : : startTask ( Task * task )
{
2018-07-15 13:51:05 +01:00
connect ( task , SIGNAL ( succeeded ( ) ) , SLOT ( taskEnd ( ) ) ) ;
connect ( task , SIGNAL ( failed ( QString ) ) , SLOT ( taskEnd ( ) ) ) ;
task - > start ( ) ;
2013-05-06 23:19:20 +01:00
}
2013-10-06 00:13:40 +01:00
void MainWindow : : instanceChanged ( const QModelIndex & current , const QModelIndex & previous )
2013-08-25 00:32:42 +01:00
{
2018-07-15 13:51:05 +01:00
if ( ! current . isValid ( ) )
{
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " SelectedInstance " , QString ( ) ) ;
2018-07-15 13:51:05 +01:00
selectionBad ( ) ;
return ;
}
2022-06-10 03:25:13 +01:00
if ( m_selectedInstance ) {
2022-06-10 08:48:18 +01:00
disconnect ( m_selectedInstance . get ( ) , & BaseInstance : : runningStatusChanged , this , & MainWindow : : refreshCurrentInstance ) ;
2022-06-10 03:25:13 +01:00
}
2018-07-15 13:51:05 +01:00
QString id = current . data ( InstanceList : : InstanceIDRole ) . toString ( ) ;
2021-11-20 15:22:22 +00:00
m_selectedInstance = APPLICATION - > instances ( ) - > getInstanceById ( id ) ;
2018-07-15 13:51:05 +01:00
if ( m_selectedInstance )
{
ui - > instanceToolBar - > setEnabled ( true ) ;
2022-12-31 00:08:10 +00:00
setInstanceActionsEnabled ( true ) ;
2022-06-19 19:33:34 +01:00
ui - > actionLaunchInstance - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2018-07-15 13:51:05 +01:00
ui - > actionLaunchInstanceOffline - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2022-07-11 19:46:11 +01:00
ui - > actionLaunchInstanceDemo - > setEnabled ( m_selectedInstance - > canLaunch ( ) ) ;
2022-09-15 23:23:58 +01:00
// Disable demo-mode if not available.
auto instance = dynamic_cast < MinecraftInstance * > ( m_selectedInstance . get ( ) ) ;
if ( instance ) {
ui - > actionLaunchInstanceDemo - > setEnabled ( instance - > supportsDemo ( ) ) ;
}
2022-06-19 19:33:34 +01:00
ui - > actionKillInstance - > setEnabled ( m_selectedInstance - > isRunning ( ) ) ;
2018-07-15 13:51:05 +01:00
ui - > actionExportInstance - > setEnabled ( m_selectedInstance - > canExport ( ) ) ;
2022-12-31 00:08:10 +00:00
renameButton - > setText ( m_selectedInstance - > name ( ) ) ;
2018-07-15 13:51:05 +01:00
m_statusLeft - > setText ( m_selectedInstance - > getStatusbarDescription ( ) ) ;
2019-07-10 03:23:24 +01:00
updateStatusCenter ( ) ;
2018-07-15 13:51:05 +01:00
updateInstanceToolIcon ( m_selectedInstance - > iconKey ( ) ) ;
updateToolsMenu ( ) ;
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " SelectedInstance " , m_selectedInstance - > id ( ) ) ;
2022-06-10 03:25:13 +01:00
2022-06-10 08:48:18 +01:00
connect ( m_selectedInstance . get ( ) , & BaseInstance : : runningStatusChanged , this , & MainWindow : : refreshCurrentInstance ) ;
2018-07-15 13:51:05 +01:00
}
else
{
ui - > instanceToolBar - > setEnabled ( false ) ;
2022-12-31 00:08:10 +00:00
setInstanceActionsEnabled ( false ) ;
2022-06-19 19:33:34 +01:00
ui - > actionLaunchInstance - > setEnabled ( false ) ;
ui - > actionLaunchInstanceOffline - > setEnabled ( false ) ;
2022-07-11 19:46:11 +01:00
ui - > actionLaunchInstanceDemo - > setEnabled ( false ) ;
2022-06-19 19:33:34 +01:00
ui - > actionKillInstance - > setEnabled ( false ) ;
2021-11-20 15:22:22 +00:00
APPLICATION - > settings ( ) - > set ( " SelectedInstance " , QString ( ) ) ;
2018-07-15 13:51:05 +01:00
selectionBad ( ) ;
return ;
}
2013-08-26 05:30:11 +01:00
}
2019-06-23 13:54:17 +01:00
void MainWindow : : instanceSelectRequest ( QString id )
2019-06-17 15:13:52 +01:00
{
setSelectedInstanceById ( id ) ;
}
2015-10-20 16:22:13 +01:00
void MainWindow : : instanceDataChanged ( const QModelIndex & topLeft , const QModelIndex & bottomRight )
2015-04-07 00:21:03 +01:00
{
2018-07-15 13:51:05 +01:00
auto current = view - > selectionModel ( ) - > currentIndex ( ) ;
QItemSelection test ( topLeft , bottomRight ) ;
if ( test . contains ( current ) )
{
instanceChanged ( current , current ) ;
}
2015-04-07 00:21:03 +01:00
}
2013-08-26 05:30:11 +01:00
void MainWindow : : selectionBad ( )
{
2018-07-15 13:51:05 +01:00
// start by reseting everything...
m_selectedInstance = nullptr ;
2013-12-31 00:24:28 +00:00
2018-07-15 13:51:05 +01:00
statusBar ( ) - > clearMessage ( ) ;
ui - > instanceToolBar - > setEnabled ( false ) ;
2022-12-31 00:08:10 +00:00
setInstanceActionsEnabled ( false ) ;
2022-06-19 20:00:51 +01:00
updateToolsMenu ( ) ;
2022-12-31 00:08:10 +00:00
renameButton - > setText ( tr ( " Rename Instance " ) ) ;
2021-10-15 23:42:01 +01:00
updateInstanceToolIcon ( " grass " ) ;
2014-01-06 09:01:40 +00:00
2018-07-15 13:51:05 +01:00
// ...and then see if we can enable the previously selected instance
2021-11-20 15:22:22 +00:00
setSelectedInstanceById ( APPLICATION - > settings ( ) - > get ( " SelectedInstance " ) . toString ( ) ) ;
2013-07-14 21:01:30 +01:00
}
2013-08-25 21:48:41 +01:00
2014-07-27 14:50:03 +01:00
void MainWindow : : checkInstancePathForProblems ( )
{
2021-11-20 15:22:22 +00:00
QString instanceFolder = APPLICATION - > settings ( ) - > get ( " InstanceDir " ) . toString ( ) ;
2018-07-15 13:51:05 +01:00
if ( FS : : checkProblemticPathJava ( QDir ( instanceFolder ) ) )
{
QMessageBox warning ( this ) ;
warning . setText ( tr ( " Your instance folder contains \' ! \' and this is known to cause Java problems! " ) ) ;
2021-10-17 23:47:02 +01:00
warning . setInformativeText (
tr (
" You have now two options: <br/> "
" - change the instance folder in the settings <br/> "
" - move this installation of %1 to a different folder "
2022-10-18 08:50:27 +01:00
) . arg ( BuildConfig . LAUNCHER_DISPLAYNAME )
2021-10-17 23:47:02 +01:00
) ;
2018-07-15 13:51:05 +01:00
warning . setDefaultButton ( QMessageBox : : Ok ) ;
warning . exec ( ) ;
}
auto tempFolderText = tr ( " This is a problem: <br/> "
2021-10-17 23:47:02 +01:00
" - The launcher will likely be deleted without warning by the operating system <br/> "
" - close the launcher now and extract it to a real location, not a temporary folder " ) ;
2018-07-15 13:51:05 +01:00
QString pathfoldername = QDir ( instanceFolder ) . absolutePath ( ) ;
if ( pathfoldername . contains ( " Rar$ " , Qt : : CaseInsensitive ) )
{
QMessageBox warning ( this ) ;
2021-10-17 23:47:02 +01:00
warning . setText ( tr ( " Your instance folder contains \' Rar$ \' - that means you haven't extracted the launcher archive! " ) ) ;
2018-07-15 13:51:05 +01:00
warning . setInformativeText ( tempFolderText ) ;
warning . setDefaultButton ( QMessageBox : : Ok ) ;
warning . exec ( ) ;
}
2019-08-04 20:14:59 +01:00
else if ( pathfoldername . startsWith ( QDir : : tempPath ( ) ) | | pathfoldername . contains ( " /TempState/ " ) )
2018-07-15 13:51:05 +01:00
{
QMessageBox warning ( this ) ;
warning . setText ( tr ( " Your instance folder is in a temporary folder: \' %1 \' ! " ) . arg ( QDir : : tempPath ( ) ) ) ;
warning . setInformativeText ( tempFolderText ) ;
warning . setDefaultButton ( QMessageBox : : Ok ) ;
warning . exec ( ) ;
}
2014-07-27 14:50:03 +01:00
}
2019-07-10 03:23:24 +01:00
void MainWindow : : updateStatusCenter ( )
{
2021-11-20 15:22:22 +00:00
m_statusCenter - > setVisible ( APPLICATION - > settings ( ) - > get ( " ShowGlobalGameTime " ) . toBool ( ) ) ;
2021-10-13 22:14:02 +01:00
2021-11-20 15:22:22 +00:00
int timePlayed = APPLICATION - > instances ( ) - > getTotalPlayTime ( ) ;
2021-09-28 23:20:34 +01:00
if ( timePlayed > 0 ) {
m_statusCenter - > setText ( tr ( " Total playtime: %1 " ) . arg ( Time : : prettifyDuration ( timePlayed ) ) ) ;
}
2019-07-10 03:23:24 +01:00
}
2022-12-31 00:08:10 +00:00
// "Instance actions" are actions that require an instance to be selected (i.e. "new instance" is not here)
// Actions that also require other conditions (e.g. a running instance) won't be changed.
void MainWindow : : setInstanceActionsEnabled ( bool enabled )
{
ui - > actionEditInstance - > setEnabled ( enabled ) ;
ui - > actionChangeInstGroup - > setEnabled ( enabled ) ;
ui - > actionViewSelectedInstFolder - > setEnabled ( enabled ) ;
ui - > actionExportInstance - > setEnabled ( enabled ) ;
ui - > actionDeleteInstance - > setEnabled ( enabled ) ;
ui - > actionCopyInstance - > setEnabled ( enabled ) ;
ui - > actionCreateInstanceShortcut - > setEnabled ( enabled ) ;
}
2022-06-10 03:25:13 +01:00
2022-06-10 08:48:18 +01:00
void MainWindow : : refreshCurrentInstance ( bool running )
2022-06-10 03:25:13 +01:00
{
auto current = view - > selectionModel ( ) - > currentIndex ( ) ;
instanceChanged ( current , current ) ;
}