2018-02-10 23:40:01 +00:00
/* Copyright 2015-2018 MultiMC Contributors
2015-08-30 20:33:53 +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
*
* 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 .
*/
2015-08-19 00:10:17 +01:00
# include "WorldListPage.h"
# include "ui_WorldListPage.h"
# include "minecraft/WorldList.h"
2016-01-05 06:32:52 +00:00
# include <DesktopServices.h>
2015-08-19 00:10:17 +01:00
# include "dialogs/ModEditDialogCommon.h"
# include <QEvent>
# include <QKeyEvent>
2015-09-06 22:35:58 +01:00
# include <QClipboard>
2015-08-31 20:34:15 +01:00
# include <QMessageBox>
2015-09-06 22:35:58 +01:00
# include <QTreeView>
2015-09-14 22:49:32 +01:00
# include <QInputDialog>
2016-11-02 01:33:55 +00:00
# include <tools/MCEditTool.h>
2015-09-06 22:35:58 +01:00
# include "MultiMC.h"
2015-09-09 22:53:33 +01:00
# include <GuiUtil.h>
2016-11-02 01:33:55 +00:00
# include <QProcess>
2016-11-03 00:10:16 +00:00
# include <FileSystem.h>
2015-08-19 00:10:17 +01:00
WorldListPage : : WorldListPage ( BaseInstance * inst , std : : shared_ptr < WorldList > worlds , QString id ,
QString iconName , QString displayName , QString helpPage ,
QWidget * parent )
2015-09-26 03:04:09 +01:00
: QWidget ( parent ) , m_inst ( inst ) , ui ( new Ui : : WorldListPage ) , m_worlds ( worlds ) , m_iconName ( iconName ) , m_id ( id ) , m_displayName ( displayName ) , m_helpName ( helpPage )
2015-08-19 00:10:17 +01:00
{
ui - > setupUi ( this ) ;
ui - > tabWidget - > tabBar ( ) - > hide ( ) ;
2015-09-06 22:35:58 +01:00
QSortFilterProxyModel * proxy = new QSortFilterProxyModel ( this ) ;
2015-09-14 22:49:32 +01:00
proxy - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
2015-09-06 22:35:58 +01:00
proxy - > setSourceModel ( m_worlds . get ( ) ) ;
ui - > worldTreeView - > setSortingEnabled ( true ) ;
ui - > worldTreeView - > setModel ( proxy ) ;
2015-08-19 00:10:17 +01:00
ui - > worldTreeView - > installEventFilter ( this ) ;
2015-09-06 22:35:58 +01:00
auto head = ui - > worldTreeView - > header ( ) ;
head - > setSectionResizeMode ( 0 , QHeaderView : : Stretch ) ;
head - > setSectionResizeMode ( 1 , QHeaderView : : ResizeToContents ) ;
connect ( ui - > worldTreeView - > selectionModel ( ) ,
SIGNAL ( currentChanged ( const QModelIndex & , const QModelIndex & ) ) , this ,
SLOT ( worldChanged ( const QModelIndex & , const QModelIndex & ) ) ) ;
worldChanged ( QModelIndex ( ) , QModelIndex ( ) ) ;
2015-08-19 00:10:17 +01:00
}
void WorldListPage : : opened ( )
{
m_worlds - > startWatching ( ) ;
}
void WorldListPage : : closed ( )
{
m_worlds - > stopWatching ( ) ;
}
WorldListPage : : ~ WorldListPage ( )
{
m_worlds - > stopWatching ( ) ;
delete ui ;
}
bool WorldListPage : : shouldDisplay ( ) const
{
return true ;
}
bool WorldListPage : : worldListFilter ( QKeyEvent * keyEvent )
{
switch ( keyEvent - > key ( ) )
{
case Qt : : Key_Delete :
on_rmWorldBtn_clicked ( ) ;
return true ;
default :
break ;
}
return QWidget : : eventFilter ( ui - > worldTreeView , keyEvent ) ;
}
bool WorldListPage : : eventFilter ( QObject * obj , QEvent * ev )
{
if ( ev - > type ( ) ! = QEvent : : KeyPress )
{
return QWidget : : eventFilter ( obj , ev ) ;
}
QKeyEvent * keyEvent = static_cast < QKeyEvent * > ( ev ) ;
if ( obj = = ui - > worldTreeView )
return worldListFilter ( keyEvent ) ;
return QWidget : : eventFilter ( obj , ev ) ;
}
2015-09-06 22:35:58 +01:00
2015-08-19 00:10:17 +01:00
void WorldListPage : : on_rmWorldBtn_clicked ( )
{
2015-09-06 22:35:58 +01:00
auto proxiedIndex = getSelectedWorld ( ) ;
2015-08-19 00:10:17 +01:00
2015-09-06 22:35:58 +01:00
if ( ! proxiedIndex . isValid ( ) )
2015-08-19 00:10:17 +01:00
return ;
2015-09-01 01:23:18 +01:00
2015-08-31 20:34:15 +01:00
auto result = QMessageBox : : question ( this ,
tr ( " Are you sure? " ) ,
tr ( " This will remove the selected world permenantly. \n "
" The world will be gone forever (A LONG TIME). \n "
" \n "
2015-09-01 01:23:18 +01:00
" Do you want to continue? " ) ) ;
if ( result ! = QMessageBox : : Yes )
{
2015-08-31 20:34:15 +01:00
return ;
2015-09-01 01:23:18 +01:00
}
2015-08-19 00:10:17 +01:00
m_worlds - > stopWatching ( ) ;
2015-09-06 22:35:58 +01:00
m_worlds - > deleteWorld ( proxiedIndex . row ( ) ) ;
2015-08-19 00:10:17 +01:00
m_worlds - > startWatching ( ) ;
}
void WorldListPage : : on_viewFolderBtn_clicked ( )
{
2016-01-05 06:32:52 +00:00
DesktopServices : : openDirectory ( m_worlds - > dir ( ) . absolutePath ( ) , true ) ;
2015-08-19 00:10:17 +01:00
}
2015-09-06 22:35:58 +01:00
QModelIndex WorldListPage : : getSelectedWorld ( )
{
auto index = ui - > worldTreeView - > selectionModel ( ) - > currentIndex ( ) ;
auto proxy = ( QSortFilterProxyModel * ) ui - > worldTreeView - > model ( ) ;
return proxy - > mapToSource ( index ) ;
}
void WorldListPage : : on_copySeedBtn_clicked ( )
{
QModelIndex index = getSelectedWorld ( ) ;
if ( ! index . isValid ( ) )
{
return ;
}
int64_t seed = m_worlds - > data ( index , WorldList : : SeedRole ) . toLongLong ( ) ;
MMC - > clipboard ( ) - > setText ( QString : : number ( seed ) ) ;
}
void WorldListPage : : on_mcEditBtn_clicked ( )
{
2016-11-03 00:10:16 +00:00
if ( m_mceditStarting )
return ;
2016-11-02 01:33:55 +00:00
auto mcedit = MMC - > mcedit ( ) ;
2016-11-03 00:10:16 +00:00
2016-11-02 01:33:55 +00:00
const QString mceditPath = mcedit - > path ( ) ;
2015-09-06 22:35:58 +01:00
QModelIndex index = getSelectedWorld ( ) ;
if ( ! index . isValid ( ) )
{
return ;
}
2015-09-15 21:51:10 +01:00
if ( ! worldSafetyNagQuestion ( ) )
return ;
2015-09-06 22:35:58 +01:00
auto fullPath = m_worlds - > data ( index , WorldList : : FolderRole ) . toString ( ) ;
2016-11-02 01:33:55 +00:00
auto program = mcedit - > getProgramPath ( ) ;
2015-09-06 22:35:58 +01:00
if ( program . size ( ) )
{
2016-11-03 01:41:01 +00:00
# ifdef Q_OS_WIN32
if ( ! QProcess : : startDetached ( program , { fullPath } , mceditPath ) )
{
mceditError ( ) ;
}
# else
2016-11-03 00:10:16 +00:00
m_mceditProcess . reset ( new LoggedProcess ( ) ) ;
m_mceditProcess - > setDetachable ( true ) ;
connect ( m_mceditProcess . get ( ) , & LoggedProcess : : stateChanged , this , & WorldListPage : : mceditState ) ;
m_mceditProcess - > start ( program , { fullPath } ) ;
2016-11-03 01:21:50 +00:00
m_mceditProcess - > setWorkingDirectory ( mceditPath ) ;
2016-11-03 00:10:16 +00:00
m_mceditStarting = true ;
2016-11-03 01:41:01 +00:00
# endif
2015-09-14 01:23:40 +01:00
}
else
{
2016-11-02 01:33:55 +00:00
QMessageBox : : warning (
this - > parentWidget ( ) ,
tr ( " No MCEdit found or set up! " ) ,
tr ( " You do not have MCEdit set up or it was moved. \n You can set it up in the global settings. " )
) ;
2015-09-06 22:35:58 +01:00
}
}
2016-11-03 01:41:01 +00:00
void WorldListPage : : mceditError ( )
{
QMessageBox : : warning (
this - > parentWidget ( ) ,
tr ( " MCEdit failed to start! " ) ,
tr ( " MCEdit failed to start. \n It may be necessary to reinstall it. " )
) ;
}
2016-11-03 00:10:16 +00:00
void WorldListPage : : mceditState ( LoggedProcess : : State state )
{
bool failed = false ;
switch ( state )
{
case LoggedProcess : : NotRunning :
case LoggedProcess : : Starting :
return ;
case LoggedProcess : : FailedToStart :
case LoggedProcess : : Crashed :
case LoggedProcess : : Aborted :
{
failed = true ;
}
case LoggedProcess : : Running :
case LoggedProcess : : Finished :
{
m_mceditStarting = false ;
break ;
}
}
if ( failed )
{
2016-11-03 01:41:01 +00:00
mceditError ( ) ;
2016-11-03 00:10:16 +00:00
}
}
2015-09-06 22:35:58 +01:00
void WorldListPage : : worldChanged ( const QModelIndex & current , const QModelIndex & previous )
{
QModelIndex index = getSelectedWorld ( ) ;
bool enable = index . isValid ( ) ;
ui - > copySeedBtn - > setEnabled ( enable ) ;
ui - > mcEditBtn - > setEnabled ( enable ) ;
ui - > rmWorldBtn - > setEnabled ( enable ) ;
2015-09-14 22:49:32 +01:00
ui - > copyBtn - > setEnabled ( enable ) ;
ui - > renameBtn - > setEnabled ( enable ) ;
2015-09-06 22:35:58 +01:00
}
2015-09-09 22:53:33 +01:00
void WorldListPage : : on_addBtn_clicked ( )
{
auto list = GuiUtil : : BrowseForFiles (
m_helpName ,
tr ( " Select a Minecraft world zip " ) ,
tr ( " Minecraft World Zip File (*.zip) " ) , QString ( ) , this - > parentWidget ( ) ) ;
if ( ! list . empty ( ) )
{
m_worlds - > stopWatching ( ) ;
for ( auto filename : list )
{
m_worlds - > installWorld ( QFileInfo ( filename ) ) ;
}
m_worlds - > startWatching ( ) ;
}
2015-09-14 22:49:32 +01:00
}
2015-09-15 21:51:10 +01:00
bool WorldListPage : : isWorldSafe ( QModelIndex )
{
return ! m_inst - > isRunning ( ) ;
}
bool WorldListPage : : worldSafetyNagQuestion ( )
{
if ( ! isWorldSafe ( getSelectedWorld ( ) ) )
{
auto result = QMessageBox : : question ( this , tr ( " Copy World " ) , tr ( " Changing a world while Minecraft is running is potentially unsafe. \n Do you wish to proceed? " ) ) ;
if ( result = = QMessageBox : : No )
{
return false ;
}
}
return true ;
}
2015-09-14 22:49:32 +01:00
void WorldListPage : : on_copyBtn_clicked ( )
{
QModelIndex index = getSelectedWorld ( ) ;
if ( ! index . isValid ( ) )
{
return ;
}
2015-09-15 21:51:10 +01:00
if ( ! worldSafetyNagQuestion ( ) )
return ;
2015-09-14 22:49:32 +01:00
auto worldVariant = m_worlds - > data ( index , WorldList : : ObjectRole ) ;
auto world = ( World * ) worldVariant . value < void * > ( ) ;
bool ok = false ;
QString name = QInputDialog : : getText ( this , tr ( " World name " ) , tr ( " Enter a new name for the copy. " ) , QLineEdit : : Normal , world - > name ( ) , & ok ) ;
if ( ok & & name . length ( ) > 0 )
{
world - > install ( m_worlds - > dir ( ) . absolutePath ( ) , name ) ;
}
}
void WorldListPage : : on_renameBtn_clicked ( )
{
QModelIndex index = getSelectedWorld ( ) ;
if ( ! index . isValid ( ) )
{
return ;
}
2015-09-15 21:51:10 +01:00
if ( ! worldSafetyNagQuestion ( ) )
return ;
2015-09-14 22:49:32 +01:00
auto worldVariant = m_worlds - > data ( index , WorldList : : ObjectRole ) ;
auto world = ( World * ) worldVariant . value < void * > ( ) ;
bool ok = false ;
QString name = QInputDialog : : getText ( this , tr ( " World name " ) , tr ( " Enter a new world name. " ) , QLineEdit : : Normal , world - > name ( ) , & ok ) ;
if ( ok & & name . length ( ) > 0 )
{
world - > rename ( name ) ;
}
}
2015-09-15 21:51:10 +01:00
void WorldListPage : : on_refreshBtn_clicked ( )
{
m_worlds - > update ( ) ;
}