def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) load_ui('world_list.ui', baseinstance=self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent( self.worldListView ) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect( self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() self.savesFolderComboBox.currentIndexChanged.connect(self.reloadList) self.minecraftInstallBox.currentIndexChanged.connect( minecraftinstall.currentInstallOption.setValue) self.minecraftVersionBox.currentIndexChanged[str].connect( minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect( self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds()
def showProgress(text, iter, cancel=False): """ Show a progress dialog for the given task. The task should be an iterable, yielding progress info as (current, max) or (current, max, statusString) tuples. Return the last value yielded by the task. :param text: :type text: :param iter: :type iter: :param cancel: :type cancel: :return: :rtype: """ from mcedit2 import editorapp dialog = QtGui.QProgressDialog(editorapp.MCEditApp.app.mainWindow) dialog.setWindowTitle(text) dialog.setWindowModality(Qt.WindowModal) dialog.show() progress = None LoaderTimer.stopAll() for progress in iter: if isinstance(progress, basestring): max = current = 0 status = progress elif isinstance(progress, (tuple, list)): if len(progress) > 2: current, max, status = progress[:3] else: current, max = progress status = "" else: current = max = 1 status = "" dialog.setValue(current) dialog.setMaximum(max) dialog.setLabelText(status) QtGui.QApplication.processEvents() if dialog.wasCanceled(): return False LoaderTimer.startAll() dialog.close() return progress
def __init__(self, parent=None, f=0): super(WorldListWidget, self).__init__(parent, f) self.setWindowTitle("World List") self.saveFileDir = None self.worldView = None self.chunkLoader = None self.errorWidget = QtGui.QWidget() load_ui('world_list.ui', baseinstance=self) self.setLayout(Row(self)) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) screen = QtGui.QApplication.desktop().availableGeometry() w = screen.width() h = screen.height() margin = 0.125 r = QtCore.QRect(screen.x() + margin * w, screen.y() + margin * h, w - w * 2 * margin, h - h * 2 * margin) self.setGeometry(r) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() for install in minecraftinstall.listInstalls(): self.minecraftInstallBox.addItem(install.name) self.minecraftInstallBox.setCurrentIndex( minecraftinstall.selectedInstallIndex()) self._updateVersionsAndResourcePacks() self.reloadList()
def __init__(self, parent=None, f=0): super(WorldListWidget, self).__init__(parent, f) self.setWindowTitle("World List") self.saveFileDir = None self.worldView = None self.chunkLoader = None self.errorWidget = QtGui.QWidget() load_ui('world_list.ui', baseinstance=self) self.setLayout(Row(self)) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) centerWidgetInScreen(self, 0.75) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() for install in minecraftinstall.listInstalls(): self.minecraftInstallBox.addItem(install.name) self.minecraftInstallBox.setCurrentIndex( minecraftinstall.selectedInstallIndex()) self._updateVersionsAndResourcePacks() self.reloadList()
def showProgress(text, iter, cancel=False): """ Show a progress dialog for the given task. The task should be an iterable, yielding progress info as (current, max) or (current, max, statusString) tuples. Return the last value yielded by the task. :param text: :type text: :param iter: :type iter: :param cancel: :type cancel: :return: :rtype: """ progress = None i = 0 start = time.time() with LoaderTimer.stopCtx(): for progress in iter: if time.time() - start > timeBeforeDialog: break else: return progress dialog = QtGui.QProgressDialog(QtGui.qApp.mainWindow) dialog.setWindowTitle(text) dialog.setWindowModality(Qt.WindowModal) dialog.show() for progress in iter: if isinstance(progress, basestring): max = current = 0 status = progress elif isinstance(progress, tuple): if len(progress) > 2: current, max, status = progress[:3] else: current, max = progress status = "" else: current = max = 1 status = "" dialog.setValue(current) dialog.setMaximum(max) dialog.setLabelText(status) QtGui.QApplication.processEvents() if dialog.wasCanceled(): return False dialog.close() return progress
def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) self.setupUi(self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) self.chooseSavesFolderButton.clicked.connect(self.chooseSavesFolder) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent(self.worldListView) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect(self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() self.savesFolderComboBox.currentIndexChanged.connect(self.reloadList) self.minecraftInstallBox.currentIndexChanged.connect(minecraftinstall.currentInstallOption.setValue) self.minecraftVersionBox.currentIndexChanged[str].connect(minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect(self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds()
def __init__(self, parent=None, f=0): super(WorldListWidget, self).__init__(parent, f) self.setWindowTitle("World List") load_ui('world_list.ui', baseinstance=self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent(self.worldListView) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect(self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() self.savesFolderComboBox.currentIndexChanged.connect(self.reloadList) self.worldListModel = None self.reloadList() self.reloadRecentWorlds()
def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) self.setupUi(self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) self.chooseSavesFolderButton.clicked.connect(self.chooseSavesFolder) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent(self.worldListView) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect(self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() try: savesFolders = WorldListSettings.allSavesFolders.value() for filename in savesFolders: if not os.path.isdir(filename): continue dirname, basename = os.path.split(filename) displayName = os.sep.join(dirname.split(os.sep)[-2:] + [basename]) self.savesFolderComboBox.addItem(displayName, filename) except (ValueError, KeyError) as e: log.warn("Failed to load saves folder list.") currentFolder = WorldListSettings.currentSavesFolder.value() if os.path.isdir(currentFolder): index = self.savesFolderComboBox.findData(currentFolder) if index != -1: self.savesFolderComboBox.setCurrentIndex(index) self.savesFolderComboBox.currentIndexChanged.connect(self.savesFolderChanged) self.minecraftInstallBox.currentIndexChanged.connect(self.currentInstallChanged) self.minecraftVersionBox.currentIndexChanged[str].connect(minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect(self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds()
class WorldListWidget(QtGui.QDialog, Ui_worldList): def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) self.setupUi(self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) self.chooseSavesFolderButton.clicked.connect(self.chooseSavesFolder) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent(self.worldListView) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect(self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() try: savesFolders = WorldListSettings.allSavesFolders.value() for filename in savesFolders: if not os.path.isdir(filename): continue dirname, basename = os.path.split(filename) displayName = os.sep.join(dirname.split(os.sep)[-2:] + [basename]) self.savesFolderComboBox.addItem(displayName, filename) except (ValueError, KeyError) as e: log.warn("Failed to load saves folder list.") currentFolder = WorldListSettings.currentSavesFolder.value() if os.path.isdir(currentFolder): index = self.savesFolderComboBox.findData(currentFolder) if index != -1: self.savesFolderComboBox.setCurrentIndex(index) self.savesFolderComboBox.currentIndexChanged.connect(self.savesFolderChanged) self.minecraftInstallBox.currentIndexChanged.connect(self.currentInstallChanged) self.minecraftVersionBox.currentIndexChanged[str].connect(minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect(self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds() def currentInstallChanged(self, index): path = self.minecraftInstallBox.itemData(index) minecraftinstall.currentInstallOption.setValue(path) def resourcePackChanged(self, index): if index == 0: minecraftinstall.currentResourcePackOption.setValue("") else: minecraftinstall.currentResourcePackOption.setValue(self.resourcePackBox.currentText()) def _updateInstalls(self): self.minecraftInstallBox.clear() for install in minecraftinstall.GetInstalls().installs: self.minecraftInstallBox.addItem(install.name, install.path) for saveDir in install.getSaveDirs(): self.savesFolderComboBox.addItem(install.name + os.sep + os.path.basename(saveDir), saveDir) for instance in minecraftinstall.GetInstalls().instances: saveDir = instance.saveFileDir self.savesFolderComboBox.addItem(instance.name + os.sep + os.path.basename(saveDir), saveDir) path = minecraftinstall.GetInstalls().selectedInstallPath() index = self.minecraftInstallBox.findData(path) self.minecraftInstallBox.setCurrentIndex(index) self._updateVersionsAndResourcePacks() def _updateVersionsAndResourcePacks(self): self.minecraftVersionBox.clear() self.resourcePackBox.clear() self.resourcePackBox.addItem(self.tr("(No resource pack)")) path = minecraftinstall.currentInstallOption.value() install = minecraftinstall.GetInstalls().getInstall(path) if install: for version in sorted(install.versions, reverse=True): self.minecraftVersionBox.addItem(version) for resourcePack in sorted(install.resourcePacks): self.resourcePackBox.addItem(resourcePack) def chooseSavesFolder(self): startingDir = WorldListSettings.lastChosenSavesFolder.value() if startingDir == '' or not os.path.isdir(startingDir): startingDir = os.path.expanduser(b"~") filename = QtGui.QFileDialog.getExistingDirectory( self, self.tr("Choose Saves Folder"), startingDir ) if filename: log.info("Adding saves folder %s", filename) savesFolders = WorldListSettings.allSavesFolders.value() savesFolders.append(filename) WorldListSettings.allSavesFolders.setValue(savesFolders) dirname, basename = os.path.split(filename) displayName = os.sep.join(dirname.split(os.sep)[-2:] + [basename]) WorldListSettings.lastChosenSavesFolder.setValue(filename) self.savesFolderComboBox.addItem(displayName, filename) self.savesFolderComboBox.setCurrentIndex(self.savesFolderComboBox.count()-1) def reloadRecentWorlds(self): recentWorlds = RecentFilesSetting.value() self.recentWorldsMenu = QtGui.QMenu() def _triggered(f): def triggered(): self.accept() self.editWorldClicked.emit(f) return triggered dead = [] for filename in recentWorlds: if not os.path.exists(filename): dead.append(filename) continue try: displayName, lastPlayed, versionInfo = WorldEditor.getWorldInfo(filename) action = self.recentWorldsMenu.addAction(displayName) action._editWorld = _triggered(filename) action.triggered.connect(action._editWorld) except EnvironmentError as e: log.exception("Failed to load world info") if len(dead): for f in dead: recentWorlds.remove(f) RecentFilesSetting.setValue(recentWorlds) self.recentWorldsButton.setMenu(self.recentWorldsMenu) def savesFolderChanged(self): currentFolder = self.savesFolderComboBox.itemData(self.savesFolderComboBox.currentIndex()) WorldListSettings.currentSavesFolder.setValue(currentFolder) self.reloadList() if len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex(self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) else: self.removeWorldView() def reloadList(self): try: saveFileDir = self.savesFolderComboBox.itemData(self.savesFolderComboBox.currentIndex()) if saveFileDir is None: log.error("No item selected in savesFolderComboBox!!(?)") return if not os.path.isdir(saveFileDir): raise IOError(u"Could not find the Minecraft saves directory!\n\n({0} was not found or is not a directory)".format(saveFileDir)) log.info("Scanning %s for worlds...", saveFileDir) potentialWorlds = os.listdir(saveFileDir) potentialWorlds = [os.path.join(saveFileDir, p) for p in potentialWorlds] worldFiles = [p for p in potentialWorlds if isLevel(AnvilWorldAdapter, p)] self.worldListModel = WorldListModel(worldFiles) self.worldListView.setModel(self.worldListModel) except Exception as e: setWidgetError(self, e, "An error occurred while scanning the saves folder.") def openWorldClicked(self): QtGui.qApp.chooseOpenWorld() _currentFilename = None def worldListItemClicked(self, index): filename = index.data() self.showWorld(filename) def worldListItemDoubleClicked(self, index): row = index.row() self.accept() self.editWorldClicked.emit(self.worldListModel.worlds[row][0]) def showWorld(self, filename): if filename == self._currentFilename: return self._currentFilename = filename self.removeWorldView() try: worldEditor = worldeditor.WorldEditor(filename, readonly=True) except (EnvironmentError, LevelFormatError, zipfile.BadZipfile) as e: self.errorWidget = QtGui.QWidget() setWidgetError(self.errorWidget, e, "An error occurred while reading the world %s." % filename) self.stackedWidget.addWidget(self.errorWidget) self.stackedWidget.setCurrentWidget(self.errorWidget) else: dim = worldEditor.getDimension() self.setWorldView(MinimapWorldView(dim)) self.chunkLoader = ChunkLoader(dim) self.chunkLoader.addClient(self.worldView) self.chunkLoader.chunkCompleted.connect(self.worldView.update) try: try: player = worldEditor.getPlayer() log.info("Centering on single-player player.") except PlayerNotFound: try: center = worldEditor.getWorldMetadata().Spawn log.info("Centering on spawn position.") except AttributeError: log.info("Centering on world center") center = dim.bounds.origin + (dim.bounds.size * 0.5) else: if player.dimName == dim.dimName: center = Vector(*player.Position) self.worldView.centerOnPoint(center) else: center = dim.bounds.origin + (dim.bounds.size * 0.5) self.worldView.centerOnPoint(center) except Exception as e: log.exception("Error while centering view in world list: %s", e) log.info("Switched world view") def setWorldView(self, worldView): if self.worldView: self.removeWorldView() self.worldView = worldView self.stackedWidget.addWidget(worldView) self.stackedWidget.setCurrentWidget(worldView) def removeWorldView(self): self.stackedWidget.setCurrentWidget(self.blankWidget) QtGui.qApp.processEvents() # force repaint of stackedWidget to hide old error widget if self.worldView: log.info("Removing view from WorldListWidget") self.worldView.dealloc() self.stackedWidget.removeWidget(self.worldView) self.worldView.setParent(None) self.worldView = None if self.errorWidget: self.stackedWidget.removeWidget(self.errorWidget) self.errorWidget = None self.chunkLoader = None # ensure WorldView gets freed now and not later # if it is freed later, it will call makeCurrent and ruin another view's render import gc; gc.collect() def hide(self): self.removeWorldView() super(WorldListWidget, self).hide() def close(self): self.removeWorldView() super(WorldListWidget, self).close() def reject(self): self.removeWorldView() super(WorldListWidget, self).reject() def showEvent(self, event): if self.worldListModel and len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex(self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) self.reloadRecentWorlds() @profiler.function("worldListLoadTimer") def loadTimerFired(self): if not self.isVisible(): self.loadTimer.setInterval(1000) return if self.chunkLoader: try: self.chunkLoader.next() self.loadTimer.setInterval(0) except StopIteration: self.loadTimer.setInterval(1000) else: self.loadTimer.setInterval(1000) @property def selectedWorldIndex(self): indexes = self.worldListView.selectedIndexes() if len(indexes): return indexes[0] editWorldClicked = QtCore.Signal(unicode) viewWorldClicked = QtCore.Signal(unicode) repairWorldClicked = QtCore.Signal(unicode) backupWorldClicked = QtCore.Signal(unicode) def editClicked(self): index = self.selectedWorldIndex if index is not None: self.editWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def viewClicked(self): index = self.selectedWorldIndex if index is not None: self.viewWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def repairClicked(self): index = self.selectedWorldIndex if index is not None: self.repairWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def backupClicked(self): index = self.selectedWorldIndex if index is not None: self.backupWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def configureClicked(self): installsWidget = MinecraftInstallsDialog() installsWidget.exec_() self._updateInstalls()
def __init__(self, argv, DEBUG=False): super(MCEditApp, self).__init__(argv) self.DEBUG = DEBUG MCEditApp.app = self minecraftinstall.GetInstalls().ensureValidInstall() self.ensureSingle() self.commandLineWorlds = [] self.parseArgs(argv) log.warn("UserFilesDirectory: %s", getUserFilesDirectory()) # --- Necessities --- translator = QtCore.QTranslator() translator.load(resourcePath('mcedit2/i18n/en_US.ts')) self.installTranslator(translator) self.setOrganizationName("MCEdit") self.setOrganizationDomain("mcedit.net") self.setApplicationName("MCEdit") self.setWindowIcon( QtGui.QIcon(resourcePath("mcedit2/assets/mcedit2/mcediticon.png"))) styleSheet = file(resourcePath("mcedit2/styles/mcedit2.qcss")).read() self.setStyleSheet(styleSheet) # --- Main Window --- self.mainWindow = mainWindow = MCEditMainWindow() self.undoGroup = QtGui.QUndoGroup() self.tabWidget = self.mainWindow.tabWidget self.tabWidget.tabCloseRequested.connect(self.tabCloseRequested) self.tabWidget.currentChanged.connect(self.tabChanged) # --- Sessions --- self._currentSession = None self.sessions = [] self.sessionDockWidgets = [] self.sessionChanged.connect(self.sessionDidChange) # --- Panel Widgets --- self.undoView = QtGui.QUndoView(self.undoGroup) self.undoDockWidget = QtGui.QDockWidget("History", mainWindow, objectName="HistoryWidget") self.undoDockWidget.setWidget(self.undoView) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.undoDockWidget) mainWindow.panelsToolBar.addAction( self.undoDockWidget.toggleViewAction()) self.undoDockWidget.close() self.logViewWidget = LogViewFrame(mainWindow) self.logViewDockWidget = QtGui.QDockWidget("Error Log", mainWindow, objectName="ErrorsWidget") self.logViewDockWidget.setWidget(self.logViewWidget) mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self.logViewDockWidget) mainWindow.panelsToolBar.addAction( self.logViewDockWidget.toggleViewAction()) self.logViewDockWidget.close() self.libraryView = LibraryWidget() self.libraryDockWidget = QtGui.QDockWidget("Library", mainWindow, objectName="LibraryWidget") self.libraryDockWidget.setWidget(self.libraryView) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.libraryDockWidget) mainWindow.panelsToolBar.addAction( self.libraryDockWidget.toggleViewAction()) self.libraryDockWidget.close() self.libraryView.doubleClicked.connect(self.libraryItemDoubleClicked) self.globalPanels = [ self.undoDockWidget, self.logViewDockWidget, self.libraryDockWidget ] # --- Debug Widgets --- if DEBUG: debugMenu = self.createDebugMenu() self.debugObjectInspector = ObjectInspector(mainWindow) self.inspectorDockWidget = QtGui.QDockWidget( "Inspector", mainWindow, objectName="InspectorWidget") self.inspectorDockWidget.setWidget(self.debugObjectInspector) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.inspectorDockWidget) debugMenu.addAction(self.inspectorDockWidget.toggleViewAction()) self.inspectorDockWidget.close() self.profileView = ProfilerWidget() profileDockWidget = QtGui.QDockWidget("Profiler", mainWindow, objectName="ProfilerWidget") profileDockWidget.setWidget(self.profileView) mainWindow.addDockWidget(Qt.RightDockWidgetArea, profileDockWidget) debugMenu.addAction(profileDockWidget.toggleViewAction()) profileDockWidget.close() self.textureAtlasView = QtGui.QLabel() self.textureAtlasView.setScaledContents(True) self.textureAtlasDockWidget = QtGui.QDockWidget( "Texture Atlas", mainWindow, objectName="TextureAtlasWidget") self.textureAtlasArea = QtGui.QScrollArea() self.textureAtlasArea.setWidget(self.textureAtlasView) self.textureAtlasDockWidget.setWidget(self.textureAtlasArea) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.textureAtlasDockWidget) debugMenu.addAction(self.textureAtlasDockWidget.toggleViewAction()) self.textureAtlasDockWidget.close() infoTabs = QtGui.QTabWidget() self.cursorInfo = WorldCursorInfo() infoTabs.addTab(self.cursorInfo, "Cursor") self.viewInfo = WorldViewInfo() infoTabs.addTab(self.viewInfo, "View") self.loaderInfo = ChunkLoaderInfo() infoTabs.addTab(self.loaderInfo, "Loader") infoDockWidget = QtGui.QDockWidget("Debug Info", mainWindow, objectName="DebugInfo") infoDockWidget.setWidget(infoTabs) mainWindow.addDockWidget(Qt.BottomDockWidgetArea, infoDockWidget) mainWindow.tabifyDockWidget(infoDockWidget, self.logViewDockWidget) self.globalPanels.append(infoDockWidget) mainWindow.panelsToolBar.addAction( infoDockWidget.toggleViewAction()) infoDockWidget.close() # --- Menu Actions --- # -- MCEdit menu -- mainWindow.actionNew_World.triggered.connect(self.createNewWorld) mainWindow.actionNew_World.setShortcut(QtGui.QKeySequence.New) mainWindow.actionOpen_World.triggered.connect(self.chooseOpenWorld) mainWindow.actionOpen_World.setShortcut(QtGui.QKeySequence.Open) mainWindow.actionShow_World_List.triggered.connect(self.showWorldList) mainWindow.actionShow_World_List.setShortcut( QtGui.QKeySequence("Ctrl+L")) mainWindow.actionSave_World.triggered.connect(self.saveCurrentWorld) mainWindow.actionSave_World.setShortcut(QtGui.QKeySequence.Save) mainWindow.actionSave_World_As.triggered.connect( self.saveCurrentWorldAs) mainWindow.actionSave_World_As.setShortcut(QtGui.QKeySequence.SaveAs) mainWindow.actionClose_World.triggered.connect(self.closeCurrentTab) mainWindow.actionClose_World.setShortcut(QtGui.QKeySequence.Close) mainWindow.actionExit_MCEdit.triggered.connect(self.exitEditor) mainWindow.actionExit_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Help menu -- mainWindow.actionAbout_MCEdit.triggered.connect(self.showAbout) mainWindow.actionAbout_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Window Menu -- mainWindow.menuWindow.addAction(self.undoDockWidget.toggleViewAction()) mainWindow.menuWindow.addAction( self.logViewDockWidget.toggleViewAction()) mainWindow.menuWindow.addAction( self.libraryDockWidget.toggleViewAction()) # --- World List --- self.worldList = WorldListWidget(mainWindow) self.worldList.editWorldClicked.connect(self.editWorldFromList) self.worldList.viewWorldClicked.connect(self.viewWorldFromList) self.worldList.backupWorldClicked.connect(self.backupWorldFromList) self.worldList.repairWorldClicked.connect(self.repairWorldFromList) # --- Status Bar --- self.positionLabel = QtGui.QLabel("xx, yy, zz", minimumWidth=100) self.blocktypeLabel = QtGui.QLabel("(-1:-1)minecraft:rocktonium", minimumWidth=250) self.blockNameLabel = QtGui.QLabel("rocktonium", minimumWidth=150) self.cpsLabel = QtGui.QLabel("-1 cps", minimumWidth=65) self.fpsLabel = QtGui.QLabel("-1 fps", minimumWidth=65) statusBar = mainWindow.statusBar() statusBar.addPermanentWidget(self.positionLabel) statusBar.addPermanentWidget(self.blocktypeLabel) statusBar.addPermanentWidget(self.blockNameLabel) statusBar.addPermanentWidget(self.cpsLabel) statusBar.addPermanentWidget(self.fpsLabel) # --- Load settings --- mainWindow.loadSettings() self.updateRecentFilesMenu() self.loadTimer = timer = LoaderTimer(self) timer.setInterval(0) timer.timeout.connect(self.loadTimerFired) timer.start() log.info("Loading timer started") mainWindow.showMaximized() QtCore.QTimer.singleShot(0, self.didFinishLaunching)
def showProgress(text, *tasks, **kwargs): """ Show a progress dialog for the given task(s). Each task should be an iterable, yielding progress info as (current, max) or (current, max, statusString) tuples. Return the last value yielded by the task. :param text: :type text: :param iter: :type iter: :param cancel: :type cancel: :return: :rtype: """ progress = None cancel = kwargs.pop('cancel', None) start = time.time() shown = False with LoaderTimer.stopCtx(): dialog = MCEProgressDialog(QtGui.qApp.mainWindow) if not cancel: dialog.setCancelButtonText(None) dialog.setWindowTitle(text) dialog.setWindowModality(Qt.WindowModal) log.info("Starting progress: %d tasks." % len(tasks)) totalMaximum = len(tasks) * 100 for i, task in enumerate(tasks): log.info("Task #%d", i) task = rescaleProgress(task, i * 100, i * 100 + 100) for progress in task: if isinstance(progress, basestring): current = 0 maximum = 0 status = progress elif isinstance(progress, tuple): if len(progress) > 2: current, maximum, status = progress[:3] else: current, maximum = progress status = "" else: current = 0 maximum = 0 status = "" dialog.setValue(current) if maximum == 0: # Task progress is indeterminate dialog.setMaximum(0) else: dialog.setMaximum(totalMaximum) dialog.setLabelText(status) if time.time() > start + timeBeforeDialog: if not shown: dialog.show() shown = True QtGui.QApplication.processEvents() if dialog.wasCanceled(): return False dialog.reset() return progress
class WorldListWidget(QtGui.QDialog): def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) load_ui('world_list.ui', baseinstance=self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent( self.worldListView ) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect( self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() self.savesFolderComboBox.currentIndexChanged.connect(self.reloadList) self.minecraftInstallBox.currentIndexChanged.connect( minecraftinstall.currentInstallOption.setValue) self.minecraftVersionBox.currentIndexChanged[str].connect( minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect( self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds() def resourcePackChanged(self, index): if index == 0: minecraftinstall.currentResourcePackOption.setValue("") else: minecraftinstall.currentResourcePackOption.setValue( self.resourcePackBox.currentText()) def _updateInstalls(self): for install in minecraftinstall.GetInstalls().installs: self.minecraftInstallBox.addItem(install.name) self.minecraftInstallBox.setCurrentIndex( minecraftinstall.GetInstalls().selectedInstallIndex()) self._updateVersionsAndResourcePacks() def _updateVersionsAndResourcePacks(self): self.minecraftVersionBox.clear() self.resourcePackBox.clear() self.resourcePackBox.addItem(self.tr("(No resource pack)")) self.savesFolderComboBox.clear() if self.minecraftInstallBox.count(): install = minecraftinstall.GetInstalls().getInstall( self.minecraftInstallBox.currentIndex()) for version in sorted(install.versions, reverse=True): self.minecraftVersionBox.addItem(version) for resourcePack in sorted(install.resourcePacks): self.resourcePackBox.addItem(resourcePack) for filename in install.getSaveDirs(): self.savesFolderComboBox.addItem( os.path.basename(os.path.dirname(filename)), (filename, None)) for index, instance in enumerate( minecraftinstall.GetInstalls().instances): # xxx instanceID? self.savesFolderComboBox.addItem(instance.name, (instance.saveFileDir, index)) def reloadRecentWorlds(self): recentWorlds = RecentFilesSetting.value() self.recentWorldsMenu = QtGui.QMenu() def _triggered(f): def triggered(): self.accept() self.editWorldClicked.emit(f) return triggered dead = [] for filename in recentWorlds: if not os.path.exists(filename): dead.append(filename) continue try: displayName, lastPlayed, versionInfo = getWorldInfo(filename) action = self.recentWorldsMenu.addAction(displayName) action._editWorld = _triggered(filename) action.triggered.connect(action._editWorld) except EnvironmentError as e: log.exception("Failed to load world info") if len(dead): for f in dead: recentWorlds.remove(f) RecentFilesSetting.setValue(recentWorlds) self.recentWorldsButton.setMenu(self.recentWorldsMenu) def reloadList(self): try: itemData = self.savesFolderComboBox.itemData( self.savesFolderComboBox.currentIndex()) if itemData is None: log.error("No item selected in savesFolderComboBox!!(?)") return saveFileDir, instanceIndex = itemData if instanceIndex is not None: # disable version selector, update resource packs(?) pass if not os.path.isdir(saveFileDir): raise IOError( u"Could not find the Minecraft saves directory!\n\n({0} was not found or is not a directory)" .format(saveFileDir)) log.info("Scanning %s for worlds...", saveFileDir) potentialWorlds = os.listdir(saveFileDir) potentialWorlds = [ os.path.join(saveFileDir, p) for p in potentialWorlds ] worldFiles = [ p for p in potentialWorlds if isLevel(AnvilWorldAdapter, p) ] self.worldListModel = WorldListModel(worldFiles) self.worldListView.setModel(self.worldListModel) if len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex( self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) except EnvironmentError as e: setWidgetError(self, e) def openWorldClicked(self): QtGui.qApp.chooseOpenWorld() _currentFilename = None def worldListItemClicked(self, index): filename = index.data() if filename != self._currentFilename: self._currentFilename = filename self.showWorld(filename) def worldListItemDoubleClicked(self, index): row = index.row() self.accept() self.editWorldClicked.emit(self.worldListModel.worlds[row][0]) def showWorld(self, filename): self.removeWorldView() try: worldEditor = worldeditor.WorldEditor(filename, readonly=True) resLoader = QtGui.qApp.getResourceLoaderForFilename(filename) blockModels = BlockModels(worldEditor.blocktypes, resLoader) textureAtlas = TextureAtlas(worldEditor, resLoader, blockModels) except (EnvironmentError, LevelFormatError, zipfile.BadZipfile) as e: self.errorWidget = QtGui.QWidget() setWidgetError(self.errorWidget, e) self.stackedWidget.addWidget(self.errorWidget) self.stackedWidget.setCurrentWidget(self.errorWidget) else: dim = worldEditor.getDimension() self.setWorldView(MinimapWorldView(dim, textureAtlas)) self.chunkLoader = ChunkLoader(dim) self.chunkLoader.addClient(self.worldView) self.chunkLoader.chunkCompleted.connect(self.worldView.update) try: player = worldEditor.getPlayer() log.info("Centering on single-player player.") except PlayerNotFound: try: center = worldEditor.worldSpawnPosition() log.info("Centering on spawn position.") except AttributeError: log.info("Centering on world center") center = dim.bounds.origin + (dim.bounds.size * 0.5) else: if player.dimName == dim.dimName: center = Vector(*player.Position) self.worldView.centerOnPoint(center) else: center = dim.bounds.origin + (dim.bounds.size * 0.5) self.worldView.centerOnPoint(center) log.info("Switched world view") def setWorldView(self, worldView): if self.worldView: self.removeWorldView() self.worldView = worldView self.stackedWidget.addWidget(worldView) self.stackedWidget.setCurrentWidget(worldView) def removeWorldView(self): self.stackedWidget.setCurrentWidget(self.blankWidget) QtGui.qApp.processEvents( ) # force repaint of stackedWidget to hide old error widget if self.worldView: log.info("Removing view from WorldListWidget") self.worldView.destroy() self.stackedWidget.removeWidget(self.worldView) self.worldView.setParent(None) self.worldView = None if self.errorWidget: self.stackedWidget.removeWidget(self.errorWidget) self.errorWidget = None self.chunkLoader = None def hide(self): self.removeWorldView() super(WorldListWidget, self).hide() def close(self): self.removeWorldView() super(WorldListWidget, self).close() def reject(self): self.removeWorldView() super(WorldListWidget, self).reject() def showEvent(self, event): if self.worldListModel and len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex( self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) self.reloadRecentWorlds() @profiler.function("worldListLoadTimer") def loadTimerFired(self): if not self.isVisible(): self.loadTimer.setInterval(1000) return if self.chunkLoader: try: self.chunkLoader.next() self.loadTimer.setInterval(0) except StopIteration: self.loadTimer.setInterval(1000) else: self.loadTimer.setInterval(1000) @property def selectedWorldIndex(self): indexes = self.worldListView.selectedIndexes() if len(indexes): return indexes[0] editWorldClicked = QtCore.Signal(unicode) viewWorldClicked = QtCore.Signal(unicode) repairWorldClicked = QtCore.Signal(unicode) backupWorldClicked = QtCore.Signal(unicode) def editClicked(self): index = self.selectedWorldIndex if index is not None: self.editWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def viewClicked(self): index = self.selectedWorldIndex if index is not None: self.viewWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def repairClicked(self): index = self.selectedWorldIndex if index is not None: self.repairWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def backupClicked(self): index = self.selectedWorldIndex if index is not None: self.backupWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def configureClicked(self): installsWidget = MinecraftInstallsDialog() installsWidget.exec_() self._updateVersionsAndResourcePacks()
def __init__(self, argv): super(MCEditApp, self).__init__(argv) MCEditApp.app = self self.ensureSingle() self.commandLineWorlds = [] self.parseArgs(argv) log.warn("UserFilesDirectory: %s", getUserFilesDirectory()) # --- Translations --- self.transDir = resourcePath('mcedit2/i18n') self.transLangs = [ f[:-3] for f in os.listdir(self.transDir) if f.endswith(".qm") ] lang = LangSetting.value() langFile = self.findLangFile(lang) if langFile is None: systemLocale = QtCore.QLocale.system() lang = systemLocale.name() # "en_US" langFile = self.findLangFile(lang) if langFile is None: lang = "en" langFile = os.path.join(self.transDir, "en.qm") chosenLang = lang self.translator = QtCore.QTranslator() self.translator.load(langFile) self.installTranslator(self.translator) log.info("Loaded translator. Selected language: %s", lang) self.translationsMenu = QtGui.QMenu() self.translationsMenu.setTitle(self.tr("Language")) self.langActions = [] for lang in self.transLangs: locale = QtCore.QLocale(lang) language = locale.nativeLanguageName().title() or lang if lang == "pr": language = "Pirate" langAction = self.translationsMenu.addAction(language) langAction.setData(lang) langAction.setCheckable(True) if lang == chosenLang: langAction.setChecked(True) self.langActions.append(langAction) self.translationsMenu.triggered.connect(self.changeLanguage) # --- Necessities --- self.setOrganizationName("MCEdit") self.setOrganizationDomain("mcedit.net") self.setApplicationName("MCEdit") self.setWindowIcon( QtGui.QIcon(resourcePath("mcedit2/assets/mcedit2/mcediticon.png"))) styleSheet = file(resourcePath("mcedit2/styles/mcedit2.qcss")).read() self.setStyleSheet(styleSheet) log.info("Loaded stylesheet.") # --- Main Window --- self.mainWindow = mainWindow = MCEditMainWindow() self.undoGroup = QtGui.QUndoGroup() self.tabWidget = self.mainWindow.tabWidget self.tabWidget.tabCloseRequested.connect(self.tabCloseRequested) self.tabWidget.currentChanged.connect(self.tabChanged) log.info("Loaded main window.") tttIcon = QtGui.QIcon( resourcePath("mcedit2/assets/mcedit2/icons/toolbar_text.png")) self.toggleToolbarTextAction = QtGui.QAction(tttIcon, "Toolbar Text", self) self.toggleToolbarTextAction.setCheckable(True) self.toggleToolbarTextAction.setChecked(True) self.toggleToolbarTextAction.toggled.connect(self.toggleToolbarText) # --- OpenGL --- setDefaultFormat() # --- Sessions --- self._currentSession = None self.sessions = [] self.sessionDockWidgets = [] self.sessionChanged.connect(self.sessionDidChange) # --- Panel Widgets --- historyIcon = QtGui.QIcon( resourcePath("mcedit2/assets/mcedit2/icons/history.png")) self.undoView = QtGui.QUndoView(self.undoGroup) self.undoDockWidget = MCEDockWidget("History", mainWindow, objectName="HistoryWidget") self.undoDockWidget.setWidget(self.undoView) self.undoDockWidget.setWindowIcon(historyIcon) self.undoDockWidget.setUnfocusedOpacity(0.8) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.undoDockWidget) undoToggleAction = self.undoDockWidget.toggleViewAction() undoToggleAction.setIcon(historyIcon) mainWindow.panelsToolBar.addAction(undoToggleAction) self.undoDockWidget.close() libraryIcon = QtGui.QIcon( resourcePath("mcedit2/assets/mcedit2/icons/library.png")) self.libraryWidget = LibraryWidget() self.libraryDockWidget = MCEDockWidget("Library", mainWindow, objectName="LibraryWidget") self.libraryDockWidget.setWidget(self.libraryWidget) self.libraryDockWidget.setWindowIcon(libraryIcon) self.libraryDockWidget.setUnfocusedOpacity(0.8) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.libraryDockWidget) libraryToggleAction = self.libraryDockWidget.toggleViewAction() libraryToggleAction.setIcon(libraryIcon) mainWindow.panelsToolBar.addAction(libraryToggleAction) self.libraryDockWidget.close() self.sessionChanged.connect(self.libraryWidget.sessionDidChange) self.libraryWidget.doubleClicked.connect(self.libraryItemDoubleClicked) self.globalPanels = [self.undoDockWidget, self.libraryDockWidget] log.info("Loaded panels.") # --- Debug Widgets --- self.debugMenu = self.createDebugMenu() self.debugObjectInspector = ObjectInspector(mainWindow) self.inspectorDockWidget = MCEDockWidget("Object Inspector", mainWindow, objectName="InspectorWidget") self.inspectorDockWidget.setWidget(self.debugObjectInspector) self.debugMenu.addAction(self.inspectorDockWidget.toggleViewAction()) self.inspectorDockWidget.close() self.profileView = ProfilerWidget() self.profileDockWidget = MCEDockWidget("Profiler", mainWindow, objectName="ProfilerWidget") self.profileDockWidget.setWidget(self.profileView) self.debugMenu.addAction(self.profileDockWidget.toggleViewAction()) self.profileDockWidget.close() self.textureAtlasView = QtGui.QLabel() self.textureAtlasView.setScaledContents(True) self.textureAtlasDockWidget = MCEDockWidget( "Texture Atlas", mainWindow, objectName="TextureAtlasWidget") self.textureAtlasArea = QtGui.QScrollArea() self.textureAtlasArea.setWidget(self.textureAtlasView) self.textureAtlasDockWidget.setWidget(self.textureAtlasArea) self.debugMenu.addAction( self.textureAtlasDockWidget.toggleViewAction()) self.textureAtlasDockWidget.close() infoTabs = QtGui.QTabWidget() self.cursorInfo = WorldCursorInfo() infoTabs.addTab(self.cursorInfo, "Cursor") self.viewInfo = WorldViewInfo() infoTabs.addTab(self.viewInfo, "View") self.loaderInfo = ChunkLoaderInfo() infoTabs.addTab(self.loaderInfo, "Loader") self.infoDockWidget = MCEDockWidget("Debug Info", mainWindow, objectName="DebugInfo") self.infoDockWidget.setWidget(infoTabs) self.infoDockWidget.close() log.info("Loaded debug widgets.") # --- Menu Actions --- # -- MCEdit menu -- mainWindow.actionNew_World.triggered.connect(self.createNewWorld) mainWindow.actionNew_World.setShortcut(QtGui.QKeySequence.New) mainWindow.actionOpen_World.triggered.connect(self.chooseOpenWorld) mainWindow.actionOpen_World.setShortcut(QtGui.QKeySequence.Open) mainWindow.actionShow_World_List.triggered.connect(self.showWorldList) mainWindow.actionShow_World_List.setShortcut( QtGui.QKeySequence("Ctrl+L")) mainWindow.actionSave_World.triggered.connect(self.saveCurrentWorld) mainWindow.actionSave_World.setShortcut(QtGui.QKeySequence.Save) mainWindow.actionSave_World_As.triggered.connect( self.saveCurrentWorldAs) mainWindow.actionSave_World_As.setShortcut(QtGui.QKeySequence.SaveAs) mainWindow.actionClose_World.triggered.connect(self.closeCurrentTab) mainWindow.actionClose_World.setShortcut(QtGui.QKeySequence.Close) mainWindow.actionExit_MCEdit.triggered.connect(self.exitEditor) mainWindow.actionExit_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Help menu -- mainWindow.actionAbout_MCEdit.triggered.connect(self.showAbout) mainWindow.actionAbout_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Window Menu -- mainWindow.menuWindow.addAction(self.undoDockWidget.toggleViewAction()) mainWindow.menuWindow.addAction( self.libraryDockWidget.toggleViewAction()) # -- Options Menu -- mainWindow.actionEnable_Lighting_Updates.setChecked( EnableLightingSetting.value()) mainWindow.actionEnable_Lighting_Updates.toggled.connect( EnableLightingSetting.setValue) EnableLightingSetting.valueChanged.connect(self.enableLightingChanged) self.enableLightingChanged(EnableLightingSetting.value()) mainWindow.actionPreferences.triggered.connect(self.showPrefsDialog) mainWindow.actionConfigure_Blocks_Items.triggered.connect( self.showConfigureBlocksDialog) mainWindow.actionConfigure_Blocks_Items.setEnabled(False) mainWindow.actionPlugins.triggered.connect(self.showPluginsDialog) mainWindow.actionEnable_Developer_Mode.setChecked( DevModeSetting.value()) mainWindow.actionEnable_Developer_Mode.toggled.connect( DevModeSetting.setValue) DevModeSetting.valueChanged.connect(self.toggleDeveloperMode) self.toggleDeveloperMode(DevModeSetting.value()) mainWindow.menuOptions.addMenu(self.translationsMenu) log.info("Loaded menus.") # --- World List --- self.worldList = WorldListWidget(mainWindow) self.worldList.editWorldClicked.connect(self.editWorldFromList) self.worldList.viewWorldClicked.connect(self.viewWorldFromList) self.worldList.backupWorldClicked.connect(self.backupWorldFromList) self.worldList.repairWorldClicked.connect(self.repairWorldFromList) log.info("Loaded world list.") # --- Status Bar --- self.positionLabel = QtGui.QLabel("xx, yy, zz", minimumWidth=100) self.biomeLabel = QtGui.QLabel("Nowhere", minimumWidth=100) self.blocktypeLabel = QtGui.QLabel("(-1:-1)minecraft:rocktonium", minimumWidth=250) self.blockNameLabel = QtGui.QLabel("rocktonium", minimumWidth=150) self.cpsLabel = QtGui.QLabel("-1 cps", minimumWidth=65) self.fpsLabel = QtGui.QLabel("-1 fps", minimumWidth=65) statusBar = mainWindow.statusBar() statusBar.addPermanentWidget(self.positionLabel) statusBar.addPermanentWidget(self.biomeLabel) statusBar.addPermanentWidget(self.blocktypeLabel) statusBar.addPermanentWidget(self.blockNameLabel) statusBar.addPermanentWidget(self.cpsLabel) statusBar.addPermanentWidget(self.fpsLabel) log.info("Loaded status bar.") # --- Load settings --- mainWindow.loadSettings() self.updateRecentFilesMenu() log.info("Loaded settings.") # --- App Dialogs --- # Qt weirdness - initializing QDialog with parent puts the dialog at 0, # 0 instead of centering it on the parent. Have to set the parent explicitly # and put the Qt.Dialog flag back on since changing the parent resets the # window flags... self.prefsDialog = prefsdialog.PrefsDialog(None) self.prefsDialog.setParent(mainWindow) self.prefsDialog.setWindowFlags(Qt.Dialog) self.configureBlocksDialog = configure_blocks.ConfigureBlocksDialog( None) self.configureBlocksDialog.finished.connect( self.configureBlocksFinished) self.configureBlocksDialog.setParent(mainWindow) self.configureBlocksDialog.setWindowFlags(Qt.Dialog) self.pluginsDialog = PluginsDialog() self.pluginsDialog.setParent(mainWindow) self.pluginsDialog.setWindowFlags(Qt.Dialog) log.info("Loaded app dialogs.") # --- Loader timer --- self.loadTimer = timer = LoaderTimer(self) timer.setInterval(0) timer.timeout.connect(self.loadTimerFired) timer.start() log.info("Loading timer started") mainWindow.showMaximized()
def __init__(self, argv): super(MCEditApp, self).__init__(argv) MCEditApp.app = self minecraftinstall.GetInstalls().ensureValidInstall() self.ensureSingle() self.commandLineWorlds = [] self.parseArgs(argv) log.warn("UserFilesDirectory: %s", getUserFilesDirectory()) # --- Necessities --- translator = QtCore.QTranslator() translator.load(resourcePath('mcedit2/i18n/en_US.ts')) self.installTranslator(translator) log.info("Loaded translator.") self.setOrganizationName("MCEdit") self.setOrganizationDomain("mcedit.net") self.setApplicationName("MCEdit") self.setWindowIcon( QtGui.QIcon(resourcePath("mcedit2/assets/mcedit2/mcediticon.png"))) styleSheet = file(resourcePath("mcedit2/styles/mcedit2.qcss")).read() self.setStyleSheet(styleSheet) log.info("Loaded stylesheet.") # --- Main Window --- self.mainWindow = mainWindow = MCEditMainWindow() self.undoGroup = QtGui.QUndoGroup() self.tabWidget = self.mainWindow.tabWidget self.tabWidget.tabCloseRequested.connect(self.tabCloseRequested) self.tabWidget.currentChanged.connect(self.tabChanged) log.info("Loaded main window.") # --- OpenGL --- setDefaultFormat() # --- Sessions --- self._currentSession = None self.sessions = [] self.sessionDockWidgets = [] self.sessionChanged.connect(self.sessionDidChange) # --- Panel Widgets --- self.undoView = QtGui.QUndoView(self.undoGroup) self.undoDockWidget = QtGui.QDockWidget("History", mainWindow, objectName="HistoryWidget") self.undoDockWidget.setWidget(self.undoView) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.undoDockWidget) mainWindow.panelsToolBar.addAction( self.undoDockWidget.toggleViewAction()) self.undoDockWidget.close() self.logViewWidget = LogViewFrame(mainWindow) self.logViewDockWidget = QtGui.QDockWidget("Error Log", mainWindow, objectName="ErrorsWidget") self.logViewDockWidget.setWidget(self.logViewWidget) mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self.logViewDockWidget) mainWindow.panelsToolBar.addAction( self.logViewDockWidget.toggleViewAction()) self.logViewDockWidget.close() self.libraryView = LibraryWidget() self.libraryDockWidget = QtGui.QDockWidget("Library", mainWindow, objectName="LibraryWidget") self.libraryDockWidget.setWidget(self.libraryView) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self.libraryDockWidget) mainWindow.panelsToolBar.addAction( self.libraryDockWidget.toggleViewAction()) self.libraryDockWidget.close() self.libraryView.doubleClicked.connect(self.libraryItemDoubleClicked) self.globalPanels = [ self.undoDockWidget, self.logViewDockWidget, self.libraryDockWidget ] log.info("Loaded panels.") # --- Debug Widgets --- self.debugMenu = self.createDebugMenu() self.debugObjectInspector = ObjectInspector(mainWindow) self.inspectorDockWidget = QtGui.QDockWidget( "Inspector", mainWindow, objectName="InspectorWidget") self.inspectorDockWidget.setWidget(self.debugObjectInspector) self.debugMenu.addAction(self.inspectorDockWidget.toggleViewAction()) self.inspectorDockWidget.close() self.profileView = ProfilerWidget() self.profileDockWidget = QtGui.QDockWidget("Profiler", mainWindow, objectName="ProfilerWidget") self.profileDockWidget.setWidget(self.profileView) self.debugMenu.addAction(self.profileDockWidget.toggleViewAction()) self.profileDockWidget.close() self.textureAtlasView = QtGui.QLabel() self.textureAtlasView.setScaledContents(True) self.textureAtlasDockWidget = QtGui.QDockWidget( "Texture Atlas", mainWindow, objectName="TextureAtlasWidget") self.textureAtlasArea = QtGui.QScrollArea() self.textureAtlasArea.setWidget(self.textureAtlasView) self.textureAtlasDockWidget.setWidget(self.textureAtlasArea) self.debugMenu.addAction( self.textureAtlasDockWidget.toggleViewAction()) self.textureAtlasDockWidget.close() infoTabs = QtGui.QTabWidget() self.cursorInfo = WorldCursorInfo() infoTabs.addTab(self.cursorInfo, "Cursor") self.viewInfo = WorldViewInfo() infoTabs.addTab(self.viewInfo, "View") self.loaderInfo = ChunkLoaderInfo() infoTabs.addTab(self.loaderInfo, "Loader") self.infoDockWidget = QtGui.QDockWidget("Debug Info", mainWindow, objectName="DebugInfo") self.infoDockWidget.setWidget(infoTabs) self.infoDockWidget.close() log.info("Loaded debug widgets.") # --- Menu Actions --- # -- MCEdit menu -- mainWindow.actionNew_World.triggered.connect(self.createNewWorld) mainWindow.actionNew_World.setShortcut(QtGui.QKeySequence.New) mainWindow.actionOpen_World.triggered.connect(self.chooseOpenWorld) mainWindow.actionOpen_World.setShortcut(QtGui.QKeySequence.Open) mainWindow.actionShow_World_List.triggered.connect(self.showWorldList) mainWindow.actionShow_World_List.setShortcut( QtGui.QKeySequence("Ctrl+L")) mainWindow.actionSave_World.triggered.connect(self.saveCurrentWorld) mainWindow.actionSave_World.setShortcut(QtGui.QKeySequence.Save) mainWindow.actionSave_World_As.triggered.connect( self.saveCurrentWorldAs) mainWindow.actionSave_World_As.setShortcut(QtGui.QKeySequence.SaveAs) mainWindow.actionClose_World.triggered.connect(self.closeCurrentTab) mainWindow.actionClose_World.setShortcut(QtGui.QKeySequence.Close) mainWindow.actionExit_MCEdit.triggered.connect(self.exitEditor) mainWindow.actionExit_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Help menu -- mainWindow.actionAbout_MCEdit.triggered.connect(self.showAbout) mainWindow.actionAbout_MCEdit.setShortcut(QtGui.QKeySequence.Quit) # -- Window Menu -- mainWindow.menuWindow.addAction(self.undoDockWidget.toggleViewAction()) mainWindow.menuWindow.addAction( self.logViewDockWidget.toggleViewAction()) mainWindow.menuWindow.addAction( self.libraryDockWidget.toggleViewAction()) # -- Options Menu -- mainWindow.actionEnable_Lighting_Updates.setChecked( EnableLightingSetting.value()) mainWindow.actionEnable_Lighting_Updates.toggled.connect( EnableLightingSetting.setValue) EnableLightingSetting.valueChanged.connect(self.enableLightingChanged) self.enableLightingChanged(EnableLightingSetting.value()) mainWindow.actionPreferences.triggered.connect(self.showPrefsDialog) mainWindow.actionConfigure_Blocks_Items.triggered.connect( self.showConfigureBlocksDialog) mainWindow.actionPlugins.triggered.connect(self.showPluginsDialog) mainWindow.actionEnable_Developer_Mode.setChecked( DevModeSetting.value()) mainWindow.actionEnable_Developer_Mode.toggled.connect( DevModeSetting.setValue) DevModeSetting.valueChanged.connect(self.toggleDeveloperMode) self.toggleDeveloperMode(DevModeSetting.value()) log.info("Loaded menus.") # --- World List --- self.worldList = WorldListWidget(mainWindow) self.worldList.editWorldClicked.connect(self.editWorldFromList) self.worldList.viewWorldClicked.connect(self.viewWorldFromList) self.worldList.backupWorldClicked.connect(self.backupWorldFromList) self.worldList.repairWorldClicked.connect(self.repairWorldFromList) log.info("Loaded world list.") # --- Status Bar --- self.positionLabel = QtGui.QLabel("xx, yy, zz", minimumWidth=100) self.biomeLabel = QtGui.QLabel("Nowhere", minimumWidth=100) self.blocktypeLabel = QtGui.QLabel("(-1:-1)minecraft:rocktonium", minimumWidth=250) self.blockNameLabel = QtGui.QLabel("rocktonium", minimumWidth=150) self.cpsLabel = QtGui.QLabel("-1 cps", minimumWidth=65) self.fpsLabel = QtGui.QLabel("-1 fps", minimumWidth=65) statusBar = mainWindow.statusBar() statusBar.addPermanentWidget(self.positionLabel) statusBar.addPermanentWidget(self.biomeLabel) statusBar.addPermanentWidget(self.blocktypeLabel) statusBar.addPermanentWidget(self.blockNameLabel) statusBar.addPermanentWidget(self.cpsLabel) statusBar.addPermanentWidget(self.fpsLabel) log.info("Loaded status bar.") # --- Load settings --- mainWindow.loadSettings() self.updateRecentFilesMenu() log.info("Loaded settings.") # --- App Dialogs --- self.prefsDialog = prefsdialog.PrefsDialog(None) self.configureBlocksDialog = configureblocksdialog.ConfigureBlocksDialog( None) self.configureBlocksDialog.finished.connect( self.configureBlocksFinished) # Qt weirdness - initializing QDialog with parent puts the dialog at 0,0 instead of # centering it on the parent. Have to set the parent explicitly and put the Qt.Dialog flag back on # since changing the parent resets the window flags... self.prefsDialog.setParent(mainWindow) self.prefsDialog.setWindowFlags(Qt.Dialog) self.configureBlocksDialog.setParent(mainWindow) self.configureBlocksDialog.setWindowFlags(Qt.Dialog) self.pluginsDialog = PluginsDialog() self.pluginsDialog.setParent(mainWindow) self.pluginsDialog.setWindowFlags(Qt.Dialog) log.info("Loaded app dialogs.") # --- Loader timer --- self.loadTimer = timer = LoaderTimer(self) timer.setInterval(0) timer.timeout.connect(self.loadTimerFired) timer.start() log.info("Loading timer started") mainWindow.showMaximized() QtCore.QTimer.singleShot(0, self.didFinishLaunching)
def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) self.setupUi(self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) self.chooseSavesFolderButton.clicked.connect(self.chooseSavesFolder) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent( self.worldListView ) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect( self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() try: savesFolders = WorldListSettings.allSavesFolders.value() for filename in savesFolders: if not os.path.isdir(filename): continue dirname, basename = os.path.split(filename) displayName = os.sep.join( dirname.split(os.sep)[-2:] + [basename]) self.savesFolderComboBox.addItem(displayName, filename) except (ValueError, KeyError) as e: log.warn("Failed to load saves folder list.") currentFolder = WorldListSettings.currentSavesFolder.value() if os.path.isdir(currentFolder): index = self.savesFolderComboBox.findData(currentFolder) if index != -1: self.savesFolderComboBox.setCurrentIndex(index) self.savesFolderComboBox.currentIndexChanged.connect( self.savesFolderChanged) self.minecraftInstallBox.currentIndexChanged.connect( self.currentInstallChanged) self.minecraftVersionBox.currentIndexChanged[str].connect( minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect( self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds()
class WorldListWidget(QtGui.QDialog, Ui_worldList): def __init__(self, parent=None): super(WorldListWidget, self).__init__(parent, f=Qt.Tool) self.setWindowTitle("World List") self.setWindowModality(Qt.NonModal) self.setupUi(self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) self.chooseSavesFolderButton.clicked.connect(self.chooseSavesFolder) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent( self.worldListView ) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect( self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() try: savesFolders = WorldListSettings.allSavesFolders.value() for filename in savesFolders: if not os.path.isdir(filename): continue dirname, basename = os.path.split(filename) displayName = os.sep.join( dirname.split(os.sep)[-2:] + [basename]) self.savesFolderComboBox.addItem(displayName, filename) except (ValueError, KeyError) as e: log.warn("Failed to load saves folder list.") currentFolder = WorldListSettings.currentSavesFolder.value() if os.path.isdir(currentFolder): index = self.savesFolderComboBox.findData(currentFolder) if index != -1: self.savesFolderComboBox.setCurrentIndex(index) self.savesFolderComboBox.currentIndexChanged.connect( self.savesFolderChanged) self.minecraftInstallBox.currentIndexChanged.connect( self.currentInstallChanged) self.minecraftVersionBox.currentIndexChanged[str].connect( minecraftinstall.currentVersionOption.setValue) self.resourcePackBox.currentIndexChanged.connect( self.resourcePackChanged) self.worldListModel = None self.reloadList() self.reloadRecentWorlds() def currentInstallChanged(self, index): path = self.minecraftInstallBox.itemData(index) minecraftinstall.currentInstallOption.setValue(path) def resourcePackChanged(self, index): if index == 0: minecraftinstall.currentResourcePackOption.setValue("") else: minecraftinstall.currentResourcePackOption.setValue( self.resourcePackBox.currentText()) def _updateInstalls(self): self.minecraftInstallBox.clear() for install in minecraftinstall.GetInstalls().installs: self.minecraftInstallBox.addItem(install.name, install.path) for saveDir in install.getSaveDirs(): self.savesFolderComboBox.addItem( install.name + os.sep + os.path.basename(saveDir), saveDir) for instance in minecraftinstall.GetInstalls().instances: saveDir = instance.saveFileDir self.savesFolderComboBox.addItem( instance.name + os.sep + os.path.basename(saveDir), saveDir) path = minecraftinstall.GetInstalls().selectedInstallPath() index = self.minecraftInstallBox.findData(path) self.minecraftInstallBox.setCurrentIndex(index) self._updateVersionsAndResourcePacks() def _updateVersionsAndResourcePacks(self): self.minecraftVersionBox.clear() self.resourcePackBox.clear() self.resourcePackBox.addItem(self.tr("(No resource pack)")) path = minecraftinstall.currentInstallOption.value() install = minecraftinstall.GetInstalls().getInstall(path) if install: for version in sorted(install.versions, reverse=True): self.minecraftVersionBox.addItem(version) for resourcePack in sorted(install.resourcePacks): self.resourcePackBox.addItem(resourcePack) def chooseSavesFolder(self): startingDir = WorldListSettings.lastChosenSavesFolder.value() if startingDir == '' or not os.path.isdir(startingDir): startingDir = os.path.expanduser(b"~") filename = QtGui.QFileDialog.getExistingDirectory( self, self.tr("Choose Saves Folder"), startingDir) if filename: log.info("Adding saves folder %s", filename) savesFolders = WorldListSettings.allSavesFolders.value() savesFolders.append(filename) WorldListSettings.allSavesFolders.setValue(savesFolders) dirname, basename = os.path.split(filename) displayName = os.sep.join(dirname.split(os.sep)[-2:] + [basename]) WorldListSettings.lastChosenSavesFolder.setValue(filename) self.savesFolderComboBox.addItem(displayName, filename) self.savesFolderComboBox.setCurrentIndex( self.savesFolderComboBox.count() - 1) def reloadRecentWorlds(self): recentWorlds = RecentFilesSetting.value() self.recentWorldsMenu = QtGui.QMenu() def _triggered(f): def triggered(): self.accept() self.editWorldClicked.emit(f) return triggered dead = [] for filename in recentWorlds: if not os.path.exists(filename): dead.append(filename) continue try: displayName, lastPlayed, versionInfo = WorldEditor.getWorldInfo( filename) action = self.recentWorldsMenu.addAction(displayName) action._editWorld = _triggered(filename) action.triggered.connect(action._editWorld) except EnvironmentError as e: log.exception("Failed to load world info") if len(dead): for f in dead: recentWorlds.remove(f) RecentFilesSetting.setValue(recentWorlds) self.recentWorldsButton.setMenu(self.recentWorldsMenu) def savesFolderChanged(self): currentFolder = self.savesFolderComboBox.itemData( self.savesFolderComboBox.currentIndex()) WorldListSettings.currentSavesFolder.setValue(currentFolder) self.reloadList() if len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex( self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) else: self.removeWorldView() def reloadList(self): try: saveFileDir = self.savesFolderComboBox.itemData( self.savesFolderComboBox.currentIndex()) if saveFileDir is None: log.error("No item selected in savesFolderComboBox!!(?)") return if not os.path.isdir(saveFileDir): raise IOError( u"Could not find the Minecraft saves directory!\n\n({0} was not found or is not a directory)" .format(saveFileDir)) log.info("Scanning %s for worlds...", saveFileDir) potentialWorlds = os.listdir(saveFileDir) potentialWorlds = [ os.path.join(saveFileDir, p) for p in potentialWorlds ] worldFiles = [ p for p in potentialWorlds if isLevel(AnvilWorldAdapter, p) ] self.worldListModel = WorldListModel(worldFiles) self.worldListView.setModel(self.worldListModel) except Exception as e: setWidgetError( self, e, "An error occurred while scanning the saves folder.") def openWorldClicked(self): QtGui.qApp.chooseOpenWorld() _currentFilename = None def worldListItemClicked(self, index): filename = index.data() self.showWorld(filename) def worldListItemDoubleClicked(self, index): row = index.row() self.accept() self.editWorldClicked.emit(self.worldListModel.worlds[row][0]) def showWorld(self, filename): if filename == self._currentFilename: return self._currentFilename = filename self.removeWorldView() try: worldEditor = worldeditor.WorldEditor(filename, readonly=True) except (EnvironmentError, LevelFormatError, zipfile.BadZipfile) as e: self.errorWidget = QtGui.QWidget() setWidgetError( self.errorWidget, e, "An error occurred while reading the world %s." % filename) self.stackedWidget.addWidget(self.errorWidget) self.stackedWidget.setCurrentWidget(self.errorWidget) else: dim = worldEditor.getDimension() self.setWorldView(MinimapWorldView(dim)) self.chunkLoader = ChunkLoader(dim) self.chunkLoader.addClient(self.worldView) self.chunkLoader.chunkCompleted.connect(self.worldView.update) try: try: player = worldEditor.getPlayer() log.info("Centering on single-player player.") except (PlayerNotFound, NBTFormatError): try: center = worldEditor.getWorldMetadata().Spawn log.info("Centering on spawn position.") except AttributeError: log.info("Centering on world center") center = dim.bounds.origin + (dim.bounds.size * 0.5) else: if player.dimName == dim.dimName: center = Vector(*player.Position) self.worldView.centerOnPoint(center) else: center = dim.bounds.origin + (dim.bounds.size * 0.5) self.worldView.centerOnPoint(center) except Exception as e: log.exception("Error while centering view in world list: %s", e) log.info("Switched world view") def setWorldView(self, worldView): if self.worldView: self.removeWorldView() self.worldView = worldView self.stackedWidget.addWidget(worldView) self.stackedWidget.setCurrentWidget(worldView) def removeWorldView(self): self.stackedWidget.setCurrentWidget(self.blankWidget) QtGui.qApp.processEvents( ) # force repaint of stackedWidget to hide old error widget if self.worldView: log.info("Removing view from WorldListWidget") self.worldView.dealloc() self.stackedWidget.removeWidget(self.worldView) self.worldView.setParent(None) self.worldView = None if self.errorWidget: self.stackedWidget.removeWidget(self.errorWidget) self.errorWidget = None self.chunkLoader = None # ensure WorldView gets freed now and not later # if it is freed later, it will call makeCurrent and ruin another view's render import gc gc.collect() def hide(self): self.removeWorldView() super(WorldListWidget, self).hide() def close(self): self.removeWorldView() super(WorldListWidget, self).close() def reject(self): self.removeWorldView() super(WorldListWidget, self).reject() def showEvent(self, event): if self.worldListModel and len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex( self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) self.reloadRecentWorlds() @profiler.function("worldListLoadTimer") def loadTimerFired(self): if not self.isVisible(): self.loadTimer.setInterval(1000) return if self.chunkLoader: try: self.chunkLoader.next() self.loadTimer.setInterval(0) except StopIteration: self.loadTimer.setInterval(1000) else: self.loadTimer.setInterval(1000) @property def selectedWorldIndex(self): indexes = self.worldListView.selectedIndexes() if len(indexes): return indexes[0] editWorldClicked = QtCore.Signal(unicode) viewWorldClicked = QtCore.Signal(unicode) repairWorldClicked = QtCore.Signal(unicode) backupWorldClicked = QtCore.Signal(unicode) def editClicked(self): index = self.selectedWorldIndex if index is not None: self.editWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def viewClicked(self): index = self.selectedWorldIndex if index is not None: self.viewWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def repairClicked(self): index = self.selectedWorldIndex if index is not None: self.repairWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def backupClicked(self): index = self.selectedWorldIndex if index is not None: self.backupWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def configureClicked(self): installsWidget = MinecraftInstallsDialog() installsWidget.exec_() self._updateInstalls()
class WorldListWidget(QtGui.QDialog): def __init__(self, parent=None, f=0): super(WorldListWidget, self).__init__(parent, f) self.setWindowTitle("World List") load_ui('world_list.ui', baseinstance=self) self.worldView = None self.chunkLoader = None self.errorWidget = None self.blankWidget = QtGui.QWidget() self.stackedWidget.addWidget(self.blankWidget) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.openWorldButton.clicked.connect(self.openWorldClicked) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) centerWidgetInScreen(self, 0.75) delegate = WorldListItemDelegate() self.worldListView.setItemDelegate(delegate) delegate.setParent(self.worldListView) # PYSIDE-152: get the view widget to the drawPrimitive call self.worldListView.clicked.connect(self.worldListItemClicked) self.worldListView.doubleClicked.connect(self.worldListItemDoubleClicked) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() self._updateInstalls() self.savesFolderComboBox.currentIndexChanged.connect(self.reloadList) self.worldListModel = None self.reloadList() self.reloadRecentWorlds() def _updateInstalls(self): for install in minecraftinstall.GetInstalls().installs: self.minecraftInstallBox.addItem(install.name) self.minecraftInstallBox.setCurrentIndex(minecraftinstall.GetInstalls().selectedInstallIndex()) self._updateVersionsAndResourcePacks() def _updateVersionsAndResourcePacks(self): install = minecraftinstall.GetInstalls().getInstall(self.minecraftInstallBox.currentIndex()) self.minecraftVersionBox.clear() for version in sorted(install.versions, reverse=True): self.minecraftVersionBox.addItem(version) self.resourcePackBox.clear() self.resourcePackBox.addItem(self.tr("(No resource pack)")) for resourcePack in sorted(install.resourcePacks): self.resourcePackBox.addItem(resourcePack) self.saveDirs = install.getSaveDirs() self.savesFolderComboBox.clear() for filename in self.saveDirs: self.savesFolderComboBox.addItem(os.path.basename(os.path.dirname(filename)), (filename, None)) for index, instance in enumerate(minecraftinstall.GetInstalls().instances): # xxx instanceID? self.savesFolderComboBox.addItem(instance.name, (instance.saveFileDir, index)) def getSelectedIVP(self): i = self.minecraftInstallBox.currentIndex() install = minecraftinstall.GetInstalls().getInstall(i) v = self.minecraftVersionBox.currentText() if self.resourcePackBox.currentIndex() > 0: p = self.resourcePackBox.currentText() else: p = None return install, v, p def reloadRecentWorlds(self): recentWorlds = RecentFilesSetting.value() self.recentWorldsMenu = QtGui.QMenu() def _triggered(f): def triggered(): self.accept() self.editWorldClicked.emit(f) return triggered for filename in recentWorlds: try: displayName, lastPlayed = getWorldInfo(filename) action = self.recentWorldsMenu.addAction(displayName) action._editWorld = _triggered(filename) action.triggered.connect(action._editWorld) except EnvironmentError as e: log.exception("Failed to load world info") self.recentWorldsButton.setMenu(self.recentWorldsMenu) def reloadList(self): try: itemData = self.savesFolderComboBox.itemData(self.savesFolderComboBox.currentIndex()) if itemData is None: log.error("No item selected in savesFolderComboBox!!(?)") return saveFileDir, instanceIndex = itemData if instanceIndex is not None: # disable version selector, update resource packs(?) pass if not os.path.isdir(saveFileDir): raise IOError(u"Could not find the Minecraft saves directory!\n\n({0} was not found or is not a directory)".format(saveFileDir)) log.info("Scanning %s for worlds...", saveFileDir) potentialWorlds = os.listdir(saveFileDir) potentialWorlds = [os.path.join(saveFileDir, p) for p in potentialWorlds] worldFiles = [p for p in potentialWorlds if isLevel(AnvilWorldAdapter, p)] self.worldListModel = WorldListModel(worldFiles) self.worldListView.setModel(self.worldListModel) if len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex(self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) except EnvironmentError as e: setWidgetError(self, e) def openWorldClicked(self): QtGui.qApp.chooseOpenWorld() _currentFilename = None def worldListItemClicked(self, index): filename = index.data() if filename != self._currentFilename: self._currentFilename = filename self.showWorld(filename) def worldListItemDoubleClicked(self, index): row = index.row() self.accept() self.editWorldClicked.emit(self.worldListModel.worlds[row][0]) def showWorld(self, filename): self.removeWorldView() try: worldEditor = worldeditor.WorldEditor(filename, readonly=True) i, v, p = self.getSelectedIVP() resLoader = i.getResourceLoader(v, p) blockModels = BlockModels(worldEditor.blocktypes, resLoader) textureAtlas = TextureAtlas(worldEditor, resLoader, blockModels) except (EnvironmentError, LevelFormatError, zipfile.BadZipfile) as e: self.errorWidget = QtGui.QWidget() setWidgetError(self.errorWidget, e) self.stackedWidget.addWidget(self.errorWidget) self.stackedWidget.setCurrentWidget(self.errorWidget) else: dim = worldEditor.getDimension() self.setWorldView(MinimapWorldView(dim, textureAtlas)) self.chunkLoader = ChunkLoader(dim) self.chunkLoader.addClient(self.worldView) self.chunkLoader.chunkCompleted.connect(self.worldView.update) try: player = worldEditor.getPlayer() log.info("Centering on single-player player.") except PlayerNotFound: try: center = worldEditor.worldSpawnPosition() log.info("Centering on spawn position.") except AttributeError: log.info("Centering on world center") center = dim.bounds.origin + (dim.bounds.size * 0.5) else: if player.dimName == dim.dimName: center = Vector(*player.Position) self.worldView.centerOnPoint(center) else: center = dim.bounds.origin + (dim.bounds.size * 0.5) self.worldView.centerOnPoint(center) log.info("Switched world view") def setWorldView(self, worldView): if self.worldView: self.removeWorldView() self.worldView = worldView self.stackedWidget.addWidget(worldView) self.stackedWidget.setCurrentWidget(worldView) def removeWorldView(self): self.stackedWidget.setCurrentWidget(self.blankWidget) QtGui.qApp.processEvents() # force repaint of stackedWidget to hide old error widget if self.worldView: log.info("Removing view from WorldListWidget") self.worldView.textureAtlas.dispose() self.worldView.destroy() self.stackedWidget.removeWidget(self.worldView) self.worldView.setParent(None) self.worldView = None if self.errorWidget: self.stackedWidget.removeWidget(self.errorWidget) self.errorWidget = None self.chunkLoader = None def hide(self): self.removeWorldView() super(WorldListWidget, self).hide() def close(self): self.removeWorldView() super(WorldListWidget, self).close() def reject(self): self.removeWorldView() super(WorldListWidget, self).reject() def showEvent(self, event): if self.worldListModel and len(self.worldListModel.worlds): self.worldListView.setFocus() self.worldListView.setCurrentIndex(self.worldListModel.createIndex(0, 0)) self.showWorld(self.worldListModel.worlds[0][0]) self.reloadRecentWorlds() @profiler.function("worldListLoadTimer") def loadTimerFired(self): if not self.isVisible(): self.loadTimer.setInterval(1000) return if self.chunkLoader: try: self.chunkLoader.next() self.loadTimer.setInterval(0) except StopIteration: self.loadTimer.setInterval(1000) else: self.loadTimer.setInterval(1000) @property def selectedWorldIndex(self): indexes = self.worldListView.selectedIndexes() if len(indexes): return indexes[0] editWorldClicked = QtCore.Signal(unicode) viewWorldClicked = QtCore.Signal(unicode) repairWorldClicked = QtCore.Signal(unicode) backupWorldClicked = QtCore.Signal(unicode) def editClicked(self): index = self.selectedWorldIndex if index is not None: self.editWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def viewClicked(self): index = self.selectedWorldIndex if index is not None: self.viewWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def repairClicked(self): index = self.selectedWorldIndex if index is not None: self.repairWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def backupClicked(self): index = self.selectedWorldIndex if index is not None: self.backupWorldClicked.emit(index.data(Qt.DisplayRole)) self.accept() def configureClicked(self): installsWidget = MinecraftInstallsDialog() installsWidget.exec_() self._updateVersionsAndResourcePacks()
def showProgress(text, *tasks, **kwargs): """ Show a progress dialog for the given task(s). Each task should be an iterable, yielding progress info as (current, max) or (current, max, statusString) tuples. Return the last value yielded by the task. :param text: :type text: :param iter: :type iter: :param cancel: :type cancel: :return: :rtype: """ progress = None cancel = kwargs.pop('cancel', None) start = time.time() shown = False with LoaderTimer.stopCtx(): dialog = MCEProgressDialog(QtGui.qApp.mainWindow) if not cancel: dialog.setCancelButtonText(None) dialog.setWindowTitle(text) dialog.setWindowModality(Qt.WindowModal) log.info("Starting progress: %d tasks." % len(tasks)) totalMaximum = len(tasks) * 100 for i, task in enumerate(tasks): log.info("Task #%d", i) task = rescaleProgress(task, i*100, i*100+100) for progress in task: if isinstance(progress, basestring): current = 0 maximum = 0 status = progress elif isinstance(progress, tuple): if len(progress) > 2: current, maximum, status = progress[:3] else: current, maximum = progress status = "" else: current = 0 maximum = 0 status = "" dialog.setValue(current) if maximum == 0: # Task progress is indeterminate dialog.setMaximum(0) else: dialog.setMaximum(totalMaximum) dialog.setLabelText(status) if time.time() > start + timeBeforeDialog: if not shown: dialog.show() shown = True QtGui.QApplication.processEvents() if dialog.wasCanceled(): return False dialog.reset() return progress
class WorldListWidget(QtGui.QDialog): def __init__(self, parent=None, f=0): super(WorldListWidget, self).__init__(parent, f) self.setWindowTitle("World List") self.saveFileDir = None self.worldView = None self.chunkLoader = None self.errorWidget = QtGui.QWidget() load_ui('world_list.ui', baseinstance=self) self.setLayout(Row(self)) self.editButton.clicked.connect(self.editClicked) self.cancelButton.clicked.connect(self.reject) self.showListAgainInput.setEnabled(False) self.viewButton.clicked.connect(self.viewClicked) self.viewButton.setEnabled(False) self.repairButton.clicked.connect(self.repairClicked) self.repairButton.setEnabled(False) self.backupButton.clicked.connect(self.backupClicked) self.backupButton.setEnabled(False) self.configureButton.clicked.connect(self.configureClicked) screen = QtGui.QApplication.desktop().availableGeometry() w = screen.width() h = screen.height() margin = 0.125 r = QtCore.QRect(screen.x() + margin * w, screen.y() + margin * h, w - w * 2 * margin, h - h * 2 * margin) self.setGeometry(r) self.loadTimer = LoaderTimer(interval=0, timeout=self.loadTimerFired) self.loadTimer.start() for install in minecraftinstall.listInstalls(): self.minecraftInstallBox.addItem(install.name) self.minecraftInstallBox.setCurrentIndex( minecraftinstall.selectedInstallIndex()) self._updateVersionsAndResourcePacks() self.reloadList() def _updateVersionsAndResourcePacks(self): install = minecraftinstall.getInstall( self.minecraftInstallBox.currentIndex()) for version in sorted(install.versions, reverse=True): self.minecraftVersionBox.addItem(version) self.resourcePackBox.addItem(self.tr("(No resource pack)")) for resourcePack in sorted(install.resourcePacks): self.resourcePackBox.addItem(resourcePack) self.saveFileDir = install.getSaveFileDir() def getSelectedIVP(self): i = self.minecraftInstallBox.currentIndex() install = minecraftinstall.getInstall(i) v = self.minecraftVersionBox.currentText() if self.resourcePackBox.currentIndex() > 0: p = self.resourcePackBox.currentText() else: p = None return install, v, p def reloadList(self): self.selectedWorldIndex = -1 self.itemWidgets = [] try: if not os.path.isdir(self.saveFileDir): raise IOError( u"Could not find the Minecraft saves directory!\n\n({0} was not found or is not a directory)" .format(self.saveFileDir)) log.info("Scanning %s for worlds...", self.saveFileDir) potentialWorlds = os.listdir(self.saveFileDir) potentialWorlds = [ os.path.join(self.saveFileDir, p) for p in potentialWorlds ] worldFiles = [ p for p in potentialWorlds if isLevel(AnvilWorldAdapter, p) ] worldAdapters = [] for f in worldFiles: try: adapter = findAdapter(f, readonly=True) except Exception as e: log.exception("Could not find adapter for %s: %r", f, e) continue else: worldAdapters.append(adapter) if len(worldAdapters) == 0: raise IOError( "No worlds found! You should probably play Minecraft to create your first world." ) column = QtGui.QVBoxLayout() column.setContentsMargins(0, 0, 0, 0) column.setSpacing(0) worldGroup = QtGui.QButtonGroup(self) #worldGroup.setExclusive(True) for adapter in worldAdapters: item = WorldListItemWidget(adapter) self.itemWidgets.append(item) self.itemWidgets.sort(key=lambda i: i.lastPlayed, reverse=True) for i, item in enumerate(self.itemWidgets): worldGroup.addButton(item, i) column.addWidget(item) item.doubleClicked.connect(self.worldListItemDoubleClicked) worldGroup.buttonClicked[int].connect(self.worldListItemClicked) self.scrollAreaWidgetContents.setLayout(column) except EnvironmentError as e: setWidgetError(self, e) def worldListItemClicked(self, i): if self.selectedWorldIndex == i: return self.selectedWorldIndex = i import gc gc.collect() models = {} try: worldEditor = worldeditor.WorldEditor(self.itemWidgets[i].filename, readonly=True) except (EnvironmentError, LevelFormatError) as e: setWidgetError(self.errorWidget, e) while self.stackedWidget.count(): self.stackedWidget.removeWidget(self.stackedWidget.widget(0)) self.worldViewBox.addWidget(self.errorWidget) else: i, v, p = self.getSelectedIVP() blockModels = models.get(worldEditor.blocktypes) resLoader = i.getResourceLoader(v, p) if blockModels is None: models[worldEditor.blocktypes] = blockModels = BlockModels( worldEditor.blocktypes, resLoader) textureAtlas = TextureAtlas(worldEditor, resLoader, blockModels) dim = worldEditor.getDimension() self.setWorldView(MinimapWorldView(dim, textureAtlas)) self.chunkLoader = ChunkLoader(dim) self.chunkLoader.addClient(self.worldView) self.chunkLoader.chunkCompleted.connect(self.worldView.update) try: player = worldEditor.getPlayer() log.info("Centering on single-player player.") except PlayerNotFound: try: center = worldEditor.worldSpawnPosition() log.info("Centering on spawn position.") except AttributeError: log.info("Centering on world center") center = dim.bounds.origin + (dim.bounds.size * 0.5) else: if player.dimName == dim.dimName: center = Vector(*player.Position) self.worldView.centerOnPoint(center) else: center = dim.bounds.origin + (dim.bounds.size * 0.5) self.worldView.centerOnPoint(center) log.info("Switched world view") def setWorldView(self, worldView): if self.worldView: self.removeWorldView() self.worldView = worldView self.stackedWidget.addWidget(worldView) def removeWorldView(self): if self.worldView: self.worldView.textureAtlas.dispose() self.worldView.destroy() self.worldView.setParent(None) self.stackedWidget.removeWidget(self.worldView) self.worldView = None self.chunkLoader = None def closeEvent(self, event): self.removeWorldView() self.selectedWorldIndex = -1 #import gc; gc.collect() def showEvent(self, event): if len(self.itemWidgets): self.itemWidgets[0].click() def worldListItemDoubleClicked(self): self.editClicked() @profiler.function("worldListLoadTimer") def loadTimerFired(self): if not self.isVisible(): self.loadTimer.setInterval(1000) return if self.chunkLoader: try: self.chunkLoader.next() self.loadTimer.setInterval(0) except StopIteration: self.loadTimer.setInterval(1000) else: self.loadTimer.setInterval(1000) editWorldClicked = QtCore.Signal(unicode) viewWorldClicked = QtCore.Signal(unicode) repairWorldClicked = QtCore.Signal(unicode) backupWorldClicked = QtCore.Signal(unicode) def editClicked(self): self.editWorldClicked.emit( self.itemWidgets[self.selectedWorldIndex].filename) self.accept() def viewClicked(self): self.viewWorldClicked.emit( self.itemWidgets[self.selectedWorldIndex].filename) self.accept() def repairClicked(self): self.repairWorldClicked.emit( self.itemWidgets[self.selectedWorldIndex].filename) self.accept() def backupClicked(self): self.backupWorldClicked.emit( self.itemWidgets[self.selectedWorldIndex].filename) self.accept() def configureClicked(self): installsWidget = MinecraftInstallsDialog() installsWidget.exec_() self._updateVersionsAndResourcePacks()