def __init__(self, mainWindow): """Initializes the user list.""" super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle(self.tr("Scratch Pad")) self.widget = QWidget(mainWindow) self.textArea = QTextEdit(mainWindow) self.currentEditingLabel = QLabel("No one is editing.") self.getLockButton = QPushButton("Edit") self.releaseLockButton = QPushButton("Confirm") #self.saveToFileButton = QPushButton("Save...") #self.loadButton = QPushButton("Load") self.layout = QGridLayout() self.layout.addWidget(self.currentEditingLabel, 0, 0, 1, 2) self.layout.addWidget(self.textArea, 1, 0, 1, 2) self.layout.addWidget(self.getLockButton, 2, 0) self.layout.addWidget(self.releaseLockButton, 2, 1) self.releaseLockButton.pressed.connect(self._releaseLock) self.getLockButton.pressed.connect(self._getLock) self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("Scratch Pad Widget") self.hasLock = False self.updateButtonStatus() try: with open(ospath.join(SAVE_DIR, "scratchpad.txt"), 'r') as autosave: self.textArea.setText(autosave.read()) except: pass mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self)
def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) #self.__eat = True self.painting = True self.dragging = False self.rectStart = None self.setWindowTitle(self.tr("Map Editor")) self.widget = QWidget(mainWindow) self.layout = QGridLayout() self.currentTileLayout = QBoxLayout(1) self.scrollarea = QScrollArea(mainWindow) self.noPaintingButton = QRadioButton(self.tr("Stop Painting"), mainWindow) self.singlePaintingButton = QRadioButton(self.tr("Single Tile Brush"), mainWindow) self.noPaintingButton.setChecked(True) self.rectPaintingButton = QRadioButton( self.tr("Area (Rectangle) Brush"), mainWindow) self.hollowRectPaintingButton = QRadioButton( self.tr("Hollow Rectangle Brush"), mainWindow) self.currentTileLabel = QLabel() self.currentTileLabelLabel = QLabel(self.tr("Current tile: ")) self.undoButton = QPushButton("Undo", mainWindow) self.redoButton = QPushButton("Redo", mainWindow) #self.moveMapButton = QPushButton("Move Map", mainWindow) self.layout.addWidget(self.scrollarea, 0, 0, 1, 2) self.layout.addWidget(self.noPaintingButton, 1, 0) self.layout.addWidget(self.singlePaintingButton, 2, 0) self.layout.addWidget(self.rectPaintingButton, 3, 0) self.layout.addWidget(self.hollowRectPaintingButton, 4, 0) self.layout.addWidget(self.undoButton, 1, 1) self.layout.addWidget(self.redoButton, 2, 1) #self.layout.addWidget(self.moveMapButton, 3, 1) self.layout.addWidget(self.currentTileLabel, 5, 1) self.layout.addWidget(self.currentTileLabelLabel, 5, 0) self.tilelabel = None self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("Map Editor") mainWindow.addDockWidget(Qt.RightDockWidgetArea, self) self.currentMap = None self.copyData = None self.undo = [] self.undoButton.clicked.connect(self._undo) self.undoButton.setEnabled(False) self.redo = [] self.redoButton.clicked.connect(self._redo) self.redoButton.setEnabled(False) addMapChangedListener(self.mapChangedResponse, NORMAL_RESPONSE_LEVEL) addMousePressListener(self.mousePressResponse, NORMAL_RESPONSE_LEVEL) addMouseMoveListener(self.mouseMoveResponse, NORMAL_RESPONSE_LEVEL) addMouseReleaseListener(self.mouseReleaseResponse, NORMAL_RESPONSE_LEVEL)
def addUser(self, name, host=False): self.internalList.append((name, host)) nametmp = name if host: if name == self.localname: self.kickbutton = QPushButton(self.tr("Kick")) self.kickbutton.setToolTip( self.tr("Disconnect the selected user.")) self.layout.addWidget(self.kickbutton, 1, 0) self.kickbutton.clicked.connect(self.requestKick) self.banbutton = QPushButton(self.tr("Manage Banlist")) self.banbutton.setToolTip( self.tr("View and edit a list of banned IPs.")) self.layout.addWidget(self.banbutton, 1, 1) self.banbutton.clicked.connect(self.openBanDialog) nametmp = "[Host] " + nametmp if self.gmname == name: nametmp = "[GM] " + nametmp self.listOfUsers.addItem(nametmp)
def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle("Pog Editor") self.setObjectName("Pog Editor") self.currentImage = None self.editedImage = None self.validBorderSizes = [(64, 64), (128, 128), (256, 256)] self.scrollarea = pogEditScrollArea(mainWindow, self) self.openButton = QPushButton("Open File", mainWindow) self.openButton.clicked.connect(self.promptOpenFile) self.saveButton = QPushButton("Save Pog", mainWindow) self.saveButton.clicked.connect(self.promptSaveFile) self.savePortraitButton = QPushButton("Save Portrait", mainWindow) self.savePortraitButton.clicked.connect(self.promptSavePortrait) self.resetButton = QPushButton("Reset Changes", mainWindow) self.resetButton.clicked.connect(self.resetImage) self.borderButton = QPushButton("Add Pog Border", mainWindow) self.borderButton.clicked.connect(self.addPogBorder) self.resizeButton = QPushButton("Resize...", mainWindow) self.resizeButton.clicked.connect(self.promptResize) self.layout = QGridLayout() self.layout.addWidget(self.scrollarea, 0, 0, 1, 3) self.layout.addWidget(self.openButton, 1, 0) self.layout.addWidget(self.borderButton, 1, 1) self.layout.addWidget(self.resizeButton, 1, 2) self.layout.addWidget(self.resetButton, 2, 0) self.layout.addWidget(self.saveButton, 2, 1) self.layout.addWidget(self.savePortraitButton, 2, 2) self.widget = QWidget() self.widget.setLayout(self.layout) self.setAcceptDrops(True) self.setWidget(self.widget) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self)
def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setToolTip( self.tr("Allows for drawing from a virtual deck of cards.")) self.setWindowTitle(self.tr("Deck")) #self.pristineCards = [] self.cards = [] self.deckDisplay = QListWidget() self.deckDisplay.itemActivated.connect(self.removeCard) self.cardNameField = QLineEdit() self.addCardButton = QPushButton("Add") self.addCardButton.clicked.connect(self.addCard) self.peekAmountField = QSpinBox() self.drawCardButton = QPushButton("Draw") self.drawCardButton.clicked.connect(self.drawCard) self.drawPlaceField = QSpinBox() self.peekCardButton = QPushButton("Peek") self.peekCardButton.clicked.connect(self.peekCard) self.refreshDeckButton = QPushButton("Initialize Deck") self.refreshDeckButton.clicked.connect(self.refreshDeck) self.shuffleDeckButton = QPushButton("Shuffle Deck") self.shuffleDeckButton.clicked.connect(self.shuffleDeck) self.loadButton = QPushButton("Load from file") self.loadButton.clicked.connect(self.loadFromFile) self.widget = QWidget(mainWindow) self.layout = QGridLayout() self.layout.addWidget(self.deckDisplay, 1, 0, 1, 2) self.layout.addWidget(self.cardNameField, 0, 0) self.layout.addWidget(self.addCardButton, 0, 1) self.layout.addWidget(self.drawCardButton, 2, 0) self.layout.addWidget(self.drawPlaceField, 2, 1) self.layout.addWidget(self.peekAmountField, 3, 0) self.layout.addWidget(self.peekCardButton, 3, 1) self.layout.addWidget(self.shuffleDeckButton, 4, 0) self.layout.addWidget(self.refreshDeckButton, 4, 1) self.layout.addWidget(self.loadButton, 5, 0, 1, 2) self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("Deck") mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self) self.hide()
def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle(self.tr("Dice")) self.realwidget = QWidget( mainWindow ) #I messed up on the initial setup and was too lazy to rename everything. self.widget = QGridLayout() self.diceArea = QListWidget(mainWindow) try: self.load(jsonload(ospath.join(SAVE_DIR, "dice.rgd"))) except: self.macros = [ QListWidgetItem(QIcon('data/dice.png'), "Sample: 2d6"), QListWidgetItem(QIcon('data/dice.png'), "Sample: 4k2"), QListWidgetItem(QIcon('data/dice.png'), "Sample: 1dn3") ] for m in self.macros: self.diceArea.addItem(m) self.diceArea.currentRowChanged.connect(self.changeCurrentMacro) self.rollbutton = QPushButton(self.tr("Roll"), mainWindow) self.rollbutton.setToolTip( self.tr("Roll dice according to the selected macro.")) self.addmacrobutton = QPushButton(self.tr("Add Macro"), mainWindow) self.addmacrobutton.setToolTip( self.tr("Add a new macro via a dialog box.")) self.removemacrobutton = QPushButton(self.tr("Delete Macro"), mainWindow) self.removemacrobutton.setToolTip( self.tr("Remove the currently selected macro.")) self.rollbutton.clicked.connect(self.rollDice) self.addmacrobutton.clicked.connect(self.summonMacro) self.removemacrobutton.clicked.connect(self.removeCurrentMacro) self.widget.addWidget(self.diceArea, 0, 0) self.widget.addWidget(self.rollbutton, 1, 0) self.widget.addWidget(self.addmacrobutton, 2, 0) self.widget.addWidget(self.removemacrobutton, 3, 0) self.realwidget.setLayout(self.widget) self.setWidget(self.realwidget) self.setObjectName("Dice Widget") mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self) self.close() self.currentMacro = -1
class mapEditor(QDockWidget): def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) #self.__eat = True self.painting = True self.dragging = False self.rectStart = None self.setWindowTitle(self.tr("Map Editor")) self.widget = QWidget(mainWindow) self.layout = QGridLayout() self.currentTileLayout = QBoxLayout(1) self.scrollarea = QScrollArea(mainWindow) self.noPaintingButton = QRadioButton(self.tr("Stop Painting"), mainWindow) self.singlePaintingButton = QRadioButton(self.tr("Single Tile Brush"), mainWindow) self.noPaintingButton.setChecked(True) self.rectPaintingButton = QRadioButton( self.tr("Area (Rectangle) Brush"), mainWindow) self.hollowRectPaintingButton = QRadioButton( self.tr("Hollow Rectangle Brush"), mainWindow) self.currentTileLabel = QLabel() self.currentTileLabelLabel = QLabel(self.tr("Current tile: ")) self.undoButton = QPushButton("Undo", mainWindow) self.redoButton = QPushButton("Redo", mainWindow) #self.moveMapButton = QPushButton("Move Map", mainWindow) self.layout.addWidget(self.scrollarea, 0, 0, 1, 2) self.layout.addWidget(self.noPaintingButton, 1, 0) self.layout.addWidget(self.singlePaintingButton, 2, 0) self.layout.addWidget(self.rectPaintingButton, 3, 0) self.layout.addWidget(self.hollowRectPaintingButton, 4, 0) self.layout.addWidget(self.undoButton, 1, 1) self.layout.addWidget(self.redoButton, 2, 1) #self.layout.addWidget(self.moveMapButton, 3, 1) self.layout.addWidget(self.currentTileLabel, 5, 1) self.layout.addWidget(self.currentTileLabelLabel, 5, 0) self.tilelabel = None self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("Map Editor") mainWindow.addDockWidget(Qt.RightDockWidgetArea, self) self.currentMap = None self.copyData = None self.undo = [] self.undoButton.clicked.connect(self._undo) self.undoButton.setEnabled(False) self.redo = [] self.redoButton.clicked.connect(self._redo) self.redoButton.setEnabled(False) addMapChangedListener(self.mapChangedResponse, NORMAL_RESPONSE_LEVEL) addMousePressListener(self.mousePressResponse, NORMAL_RESPONSE_LEVEL) addMouseMoveListener(self.mouseMoveResponse, NORMAL_RESPONSE_LEVEL) addMouseReleaseListener(self.mouseReleaseResponse, NORMAL_RESPONSE_LEVEL) def _undo(self): try: from libraries.rggViews import _sendTileUpdate except ImportError: from rggViews import _sendTileUpdate redoTiles = [] for data in self.undo.pop(): redoTiles.append( (data[0], data[1], _sendTileUpdate(data[0], data[1], data[2]))) self.redo.append(redoTiles) self.redoButton.setEnabled(True) if len(self.undo) == 0: self.undoButton.setEnabled(False) def _redo(self): try: from libraries.rggViews import _sendTileUpdate except ImportError: from rggViews import _sendTileUpdate undoTiles = [] for data in self.redo.pop(): undoTiles.append( (data[0], data[1], _sendTileUpdate(data[0], data[1], data[2]))) self.undo.append(undoTiles) self.undoButton.setEnabled(True) if len(self.redo) == 0: self.redoButton.setEnabled(False) def updateCurrentTile(self): self.tilepix = QPixmap() self.tilepix.load(self.currentMap.tileset) self.tilepix = self.tilepix.copy( QRect(*self.tilelabel.currentTileDimensions)) self.currentTileLabel.setPixmap(self.tilepix) def mousePressResponse(self, x, y, t): mapPosition = getMapPosition((x, y)) #This and similar things were a regrettable necessity in the plugin -> nonplugin conversion process. try: from libraries.rggViews import topmap, _sendTileUpdate except ImportError: from rggViews import topmap, _sendTileUpdate map = topmap(mapPosition) if map == None: return if map != self.currentMap: self.mapChangedResponse(map) if t == 0: self.dragging = True if self.isVisible() and self.singlePaintingButton.isChecked(): clickedtile = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(clickedtile): return True oldtile = _sendTileUpdate(map.ID, clickedtile, self.tilelabel.currentTile) self.undo.append([ (map.ID, clickedtile, oldtile), ]) self.redo = [] self.redoButton.setEnabled(False) self.undoButton.setEnabled(True) return True elif self.isVisible() and ( self.rectPaintingButton.isChecked() or self.hollowRectPaintingButton.isChecked()): self.rectStart = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(self.rectStart): self.rectStart = None return True elif t == 5: if self.isVisible() and not self.noPaintingButton.isChecked(): clickedtile = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) self.tilelabel.currentTile = map.getTile(clickedtile) self.tilelabel.updateTile() return True elif t == 6: if self.isVisible( ) and not self.noPaintingButton.isChecked() and self.copyData: if self.singlePaintingButton.isChecked(): clickedtile = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) for row, columns in enumerate(self.copyData): for column, tile in enumerate(columns): _sendTileUpdate(map.ID, (clickedtile[0] + row, clickedtile[1] + column), tile) elif self.rectPaintingButton.isChecked(): self.rectStart = ( int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(self.rectStart): self.rectStart = None return True elif t == 8: if self.isVisible() and not self.noPaintingButton.isChecked(): self.rectStart = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(self.rectStart): self.rectStart = None return True def mouseMoveResponse(self, x, y): if self.dragging and self.isVisible( ) and self.singlePaintingButton.isChecked(): try: from libraries.rggViews import topmap except ImportError: from rggViews import topmap mapPosition = getMapPosition((x, y)) map = topmap(mapPosition) if map == None: self.dragging = False return clickedtile = (int( ((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if map.tilePosExists(clickedtile) and map.getTile( clickedtile) != self.tilelabel.currentTile: try: from libraries.rggViews import _sendTileUpdate except ImportError: from rggViews import _sendTileUpdate oldtile = _sendTileUpdate(map.ID, clickedtile, self.tilelabel.currentTile) self.undo[-1].append((map.ID, clickedtile, oldtile)) return True def mouseReleaseResponse(self, x, y, t): if t == 0: try: from libraries.rggViews import topmap, _sendTileUpdate, _sendMultipleTileUpdate except ImportError: from rggViews import topmap, _sendTileUpdate, _sendMultipleTileUpdate if self.currentMap == None: return mapPosition = getMapPosition((x, y)) map = topmap(mapPosition) self.dragging = False if map == None or map != self.currentMap: return if self.isVisible() and self.singlePaintingButton.isChecked(): return True elif self.isVisible() and self.rectPaintingButton.isChecked( ) and self.rectStart is not None: rectEnd = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(rectEnd): self.rectStart = None self.rectEnd = None return self.undo.append([]) self.undoButton.setEnabled(True) self.redo = [] self.redoButton.setEnabled(False) oldtiles = _sendMultipleTileUpdate( self.currentMap.ID, (min(rectEnd[0], self.rectStart[0]), min(rectEnd[1], self.rectStart[1])), (max(rectEnd[0], self.rectStart[0]), max(rectEnd[1], self.rectStart[1])), self.tilelabel.currentTile) for x in range(min(rectEnd[0], self.rectStart[0]), max(rectEnd[0], self.rectStart[0]) + 1): for y in range(min(rectEnd[1], self.rectStart[1]), max(rectEnd[1], self.rectStart[1]) + 1): self.undo[-1].append((map.ID, (x, y), oldtiles.pop(0))) return True elif self.isVisible() and self.hollowRectPaintingButton.isChecked( ) and self.rectStart is not None: rectEnd = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(rectEnd): self.rectStart = None self.rectEnd = None return self.undo.append([]) self.undoButton.setEnabled(True) self.redo = [] self.redoButton.setEnabled(False) if rectEnd[0] != self.rectStart[0]: for x in range( self.rectStart[0], rectEnd[0] + (1 * (rectEnd[0] - self.rectStart[0])), 1 * (rectEnd[0] - self.rectStart[0])): if rectEnd[1] != self.rectStart[1]: #TODO: Less lazy and inefficient implementation for this case. for y in range( self.rectStart[1], rectEnd[1] + 1 * (rectEnd[1] - self.rectStart[1]), 1 * (rectEnd[1] - self.rectStart[1])): if x == self.rectStart[0] or x == rectEnd[ 0] or y == self.rectStart[ 1] or y == rectEnd[1]: if self.currentMap.tilePosExists((x, y)): oldtile = _sendTileUpdate( self.currentMap.ID, (x, y), self.tilelabel.currentTile) self.undo[-1].append( (map.ID, (x, y), oldtile)) else: if self.currentMap.tilePosExists( (x, self.rectStart[1])): oldtile = _sendTileUpdate( self.currentMap.ID, (x, self.rectStart[1]), self.tilelabel.currentTile) self.undo[-1].append( (map.ID, (x, self.rectStart[1]), oldtile)) else: if rectEnd[1] != self.rectStart[1]: for y in range( self.rectStart[1], rectEnd[1] + 1 * (rectEnd[1] - self.rectStart[1]), 1 * (rectEnd[1], self.rectStart[1])): if self.currentMap.tilePosExists( (self.rectStart[0], y)): oldtile = _sendTileUpdate( self.currentMap.ID, (self.rectStart[0], y), self.tilelabel.currentTile) self.undo[-1].append( (map.ID, (self.rectStart[0], y), oldtile)) else: if self.currentMap.tilePosExists( (self.rectStart[0], self.rectStart[1])): oldtile = _sendTileUpdate( self.currentMap.ID, (self.rectStart[0], self.rectStart[1]), self.tilelabel.currentTile) self.undo[-1].append( (map.ID, (self.rectStart[0], self.rectStart[1]), oldtile)) return True elif t == 6: if self.isVisible() and self.rectPaintingButton.isChecked( ) and self.copyData: try: from libraries.rggViews import topmap, _sendTileUpdate except ImportError: from rggViews import topmap, _sendTileUpdate if self.currentMap == None: return mapPosition = getMapPosition((x, y)) map = topmap(mapPosition) self.dragging = False if map == None or map != self.currentMap: return rectEnd = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(rectEnd): self.rectStart = None self.rectEnd = None return topleft = (min(self.rectStart[0], rectEnd[0]), min(self.rectStart[1], rectEnd[1])) bottomright = (max(self.rectStart[0], rectEnd[0]), max(self.rectStart[1], rectEnd[1])) for row in range(1 + (bottomright[0] - topleft[0])): for column in range(1 + (bottomright[1] - topleft[1])): _sendTileUpdate( self.currentMap.ID, (topleft[0] + row, topleft[1] + column), self.copyData[row % len(self.copyData)][ column % len(self.copyData[row % len(self.copyData)])]) return True elif t == 8: if self.isVisible() and not self.noPaintingButton.isChecked(): try: from libraries.rggViews import topmap except ImportError: from rggViews import topmap if self.currentMap == None: return mapPosition = getMapPosition((x, y)) map = topmap(mapPosition) self.dragging = False if map == None or map != self.currentMap: return rectEnd = (int(((mapPosition[0] - map.drawOffset[0]) / self.tilelabel.tilex)), int(((mapPosition[1] - map.drawOffset[1]) / self.tilelabel.tiley))) if not map.tilePosExists(rectEnd): self.rectStart = None self.rectEnd = None return topleft = (min(self.rectStart[0], rectEnd[0]), min(self.rectStart[1], rectEnd[1])) bottomright = (max(self.rectStart[0], rectEnd[0]), max(self.rectStart[1], rectEnd[1])) copypaste = [] for row in range(1 + (bottomright[0] - topleft[0])): copypaste.append([]) for column in range(1 + (bottomright[1] - topleft[1])): copypaste[row].append( map.getTile( (topleft[0] + row, topleft[1] + column))) self.copyData = copypaste return True def mapChangedResponse(self, newMap): if newMap != None: self.currentMap = newMap self.tilepixmap = QPixmap() self.tilepixmap.load(newMap.tileset) if self.tilelabel is None: self.tilelabel = mapEditorLabel(newMap.tilesize, self.tilepixmap.width(), self.tilepixmap.height(), self) else: self.tilelabel = mapEditorLabel(newMap.tilesize, self.tilepixmap.width(), self.tilepixmap.height(), self, self.tilelabel.currentTile) self.tilelabel.setPixmap(self.tilepixmap) self.scrollarea.setWidget(self.tilelabel)
class userListWidget(QDockWidget): """The list of connected users.""" def __init__(self, mainWindow): """Initializes the user list.""" super(QDockWidget, self).__init__(mainWindow) self.setToolTip(self.tr("People presently playing.")) self.setWindowTitle(self.tr("Connected Users")) self.widget = QWidget(mainWindow) self.listOfUsers = userListList(mainWindow, self) self.internalList = [] self.layout = QGridLayout() self.layout.addWidget(self.listOfUsers, 0, 0, 1, 2) self.widget.setLayout(self.layout) self.widget.setMaximumWidth( 200) #Arbitrary; keeps it from taking over 1/3 of the screen self.setWidget(self.widget) self.setObjectName("User List Widget") self.gmname = None self.localname = None mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self) def addUser(self, name, host=False): self.internalList.append((name, host)) nametmp = name if host: if name == self.localname: self.kickbutton = QPushButton(self.tr("Kick")) self.kickbutton.setToolTip( self.tr("Disconnect the selected user.")) self.layout.addWidget(self.kickbutton, 1, 0) self.kickbutton.clicked.connect(self.requestKick) self.banbutton = QPushButton(self.tr("Manage Banlist")) self.banbutton.setToolTip( self.tr("View and edit a list of banned IPs.")) self.layout.addWidget(self.banbutton, 1, 1) self.banbutton.clicked.connect(self.openBanDialog) nametmp = "[Host] " + nametmp if self.gmname == name: nametmp = "[GM] " + nametmp self.listOfUsers.addItem(nametmp) def removeUser(self, name): for i, item in enumerate(self.internalList): if item[0] == name: self.internalList.pop(i) self.listOfUsers.takeItem(i) def getUsers(self): return self.internalList def clearUserList(self): self.internalList = [] self.listOfUsers.clear() def refreshDisplay(self): self.listOfUsers.clear() for item in self.internalList: nametmp = item[0] if item[1]: nametmp = "[Host] " + nametmp if self.gmname == item[0]: nametmp = "[GM] " + nametmp self.listOfUsers.addItem(nametmp) def setGM(self, new): self.gmname = new self.refreshDisplay() def provideOptions(self, ID): if self.gmname != self.localname: return name = self.internalList[ID][0] #self.setGM(name) self.selectGM.emit(name) def requestKick(self): name = self.internalList[self.listOfUsers.currentRow()][0] if name == self.localname: return self.kickPlayer.emit(name) def openBanDialog(self): banDialog().exec_() self.requestBanlistUpdate.emit() selectGM = signal( BASE_STRING, doc= """Called to request a menu be summoned containing actions targeting the selected player. Sorry for the misleading legacy name.""") kickPlayer = signal(BASE_STRING, doc="""Called to request player kicking.""") requestBanlistUpdate = signal( doc="""Called to request that the banlist be updated.""")
def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setToolTip(self.tr("A widget for in-character chat.")) self.setWindowTitle(self.tr("IC Chat")) self.widgetEditor = QTextBrowser(mainWindow) self.widgetLineInput = chatLineEdit(mainWindow) self.widgetLineInput.setToolTip( self.tr( "Type text here and press Enter or Return to transmit it.")) self.widget = QWidget(mainWindow) self.widgetEditor.setReadOnly(True) self.widgetEditor.setOpenLinks(False) self.characterPreview = QLabel(mainWindow) self.characterSelector = QComboBox(mainWindow) self.characterSelector.setToolTip( self. tr("Select the character to be displayed as the speaker of entered text." )) self.characterAddButton = QPushButton(self.tr("Add New"), mainWindow) self.characterAddButton.setToolTip( self.tr("Add a new in-character chat character via a dialog box.")) self.characterDeleteButton = QPushButton(self.tr("Delete"), mainWindow) self.characterDeleteButton.setToolTip( self.tr( "Delete the currently selected in-character chat character.")) self.characterClearButton = QPushButton(self.tr("Clear"), mainWindow) self.characterClearButton.setToolTip( self.tr("Deletes all in-character chat characters.")) self.layout = QGridLayout() self.layout.addWidget(self.widgetEditor, 0, 0, 1, 4) self.layout.addWidget(self.widgetLineInput, 1, 1, 1, 3) self.layout.addWidget(self.characterPreview, 1, 0, 2, 1) self.layout.addWidget(self.characterDeleteButton, 2, 3, 1, 1) self.layout.addWidget(self.characterClearButton, 3, 3, 1, 1) self.layout.addWidget(self.characterAddButton, 2, 2, 1, 1) self.layout.addWidget(self.characterSelector, 2, 1, 1, 1) self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("IC Chat Widget") self.messageCache = [] self.setAcceptDrops(True) mainWindow.addDockWidget(Qt.LeftDockWidgetArea, self) #TODO: Store and access characters in a better fashion. try: self.load(jsonload(ospath.join(CHAR_DIR, "autosave.rgc"))) except: self.characters = [] self.widgetLineInput.returnPressed.connect(self.processInput) self.characterAddButton.clicked.connect(self.newCharacter) self.characterDeleteButton.clicked.connect(self.deleteCharacter) self.characterClearButton.clicked.connect(self.clearCharacters) self.characterSelector.currentIndexChanged.connect( self.setCharacterPreview) self.updateDeleteButton() self.setCharacterPreview()
class ICChatWidget(QDockWidget): def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setToolTip(self.tr("A widget for in-character chat.")) self.setWindowTitle(self.tr("IC Chat")) self.widgetEditor = QTextBrowser(mainWindow) self.widgetLineInput = chatLineEdit(mainWindow) self.widgetLineInput.setToolTip( self.tr( "Type text here and press Enter or Return to transmit it.")) self.widget = QWidget(mainWindow) self.widgetEditor.setReadOnly(True) self.widgetEditor.setOpenLinks(False) self.characterPreview = QLabel(mainWindow) self.characterSelector = QComboBox(mainWindow) self.characterSelector.setToolTip( self. tr("Select the character to be displayed as the speaker of entered text." )) self.characterAddButton = QPushButton(self.tr("Add New"), mainWindow) self.characterAddButton.setToolTip( self.tr("Add a new in-character chat character via a dialog box.")) self.characterDeleteButton = QPushButton(self.tr("Delete"), mainWindow) self.characterDeleteButton.setToolTip( self.tr( "Delete the currently selected in-character chat character.")) self.characterClearButton = QPushButton(self.tr("Clear"), mainWindow) self.characterClearButton.setToolTip( self.tr("Deletes all in-character chat characters.")) self.layout = QGridLayout() self.layout.addWidget(self.widgetEditor, 0, 0, 1, 4) self.layout.addWidget(self.widgetLineInput, 1, 1, 1, 3) self.layout.addWidget(self.characterPreview, 1, 0, 2, 1) self.layout.addWidget(self.characterDeleteButton, 2, 3, 1, 1) self.layout.addWidget(self.characterClearButton, 3, 3, 1, 1) self.layout.addWidget(self.characterAddButton, 2, 2, 1, 1) self.layout.addWidget(self.characterSelector, 2, 1, 1, 1) self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("IC Chat Widget") self.messageCache = [] self.setAcceptDrops(True) mainWindow.addDockWidget(Qt.LeftDockWidgetArea, self) #TODO: Store and access characters in a better fashion. try: self.load(jsonload(ospath.join(CHAR_DIR, "autosave.rgc"))) except: self.characters = [] self.widgetLineInput.returnPressed.connect(self.processInput) self.characterAddButton.clicked.connect(self.newCharacter) self.characterDeleteButton.clicked.connect(self.deleteCharacter) self.characterClearButton.clicked.connect(self.clearCharacters) self.characterSelector.currentIndexChanged.connect( self.setCharacterPreview) self.updateDeleteButton() self.setCharacterPreview() def toggleDarkBackgroundSupport(self, dark): if dark: self.widgetEditor.document().setDefaultStyleSheet( "a {color: cyan; }") else: self.widgetEditor.document().setDefaultStyleSheet( "a {color: blue; }") self.refreshMessages() def refreshMessages(self): '''Clear the text display and re-add all messages with current style settings etc.''' self.widgetEditor.clear() for message in self.messageCache: self.widgetEditor.append(message) def updateDeleteButton(self): self.characterDeleteButton.setEnabled(self.hasCharacters()) self.characterClearButton.setEnabled(self.hasCharacters()) self.characterSelector.setEnabled(self.hasCharacters()) self.widgetLineInput.setEnabled(self.hasCharacters()) def setCharacterPreview(self, newIndex=-1): try: preview = QPixmap( ospath.join( UNICODE_STRING(PORTRAIT_DIR), UNICODE_STRING(self.characters[ self.characterSelector.currentIndex()].portrait))) if preview.isNull( ): #Sadly, we have to check ahead, because Qt is dumb and prints an error about the scaling instead of raising one we can catch. raise TypeError preview = preview.scaled(min(preview.width(), 64), min(preview.height(), 64)) self.characterPreview.setPixmap(preview) except: self.characterPreview.clear() def insertMessage(self, mes): self.scroll = (self.widgetEditor.verticalScrollBar().value() == self.widgetEditor.verticalScrollBar().maximum()) self.messageCache.append(mes) self.widgetEditor.append(mes) if self.scroll: self.widgetEditor.verticalScrollBar().setValue( self.widgetEditor.verticalScrollBar().maximum()) try: try: self.logfile = open( ospath.join(LOG_DIR, strftime("%b_%d_%Y.log", localtime())), 'a') self.logfile.write(mes + "\n") finally: self.logfile.close() except: pass def dragEnterEvent(self, event): if event.mimeData().hasImage(): event.acceptProposedAction() def dropEvent(self, event): if event.mimeData().hasImage(): dat = event.mimeData().imageData() img = QImage(dat) filename = promptSaveFile('Save Portrait', 'Portrait files (*.png)', PORTRAIT_DIR) if filename is not None: img.save(filename, "PNG") event.acceptProposedAction() def newCharacter(self): dialog = newCharacterDialog() def accept(): valid = dialog.is_valid() if not valid: showErrorMessage(dialog.error) return valid if dialog.exec_(self.parentWidget(), accept): newchardat = dialog.save() newchar = ICChar(*newchardat) self.characterSelector.addItem(newchar.id) self.characters.append(newchar) jsondump(self.dump(), ospath.join(CHAR_DIR, "autosave.rgc")) self.characterSelector.setCurrentIndex( self.characterSelector.count() - 1) self.updateDeleteButton() self.setCharacterPreview() def _newChar(self, char): self.characterSelector.addItem(char.id) self.characters.append(char) jsondump(self.dump(), ospath.join(CHAR_DIR, "autosave.rgc")) def deleteCharacter(self): if self.hasCharacters(): self.characters.pop(self.characterSelector.currentIndex()) self.characterSelector.removeItem( self.characterSelector.currentIndex()) jsondump(self.dump(), ospath.join(CHAR_DIR, "autosave.rgc")) self.updateDeleteButton() def clearCharacters(self): if promptYesNo('Really clear all characters?') == 16384: self.characters = [] self.characterSelector.clear() jsondump(self.dump(), ospath.join(CHAR_DIR, "autosave.rgc")) self.updateDeleteButton() self.setCharacterPreview() def processTags(self, message): message = message.replace("<", "<").replace(">", ">") for validTag in ("i", "b", "u", "s"): message = message.replace("".join(("[", validTag, "]")), "".join( ("<", validTag, ">"))) message = message.replace("".join(("[", "/", validTag, "]")), "".join(("<", "/", validTag, ">"))) return message def processInput(self): self.newmes = UNICODE_STRING(self.widgetLineInput.text()) self.newmes = self.processTags(self.newmes) self.widgetLineInput.clear() self.widgetLineInput.addMessage(self.newmes) self.ICChatInput.emit( self.newmes, UNICODE_STRING( self.characters[self.characterSelector.currentIndex()].name), UNICODE_STRING(self.characters[ self.characterSelector.currentIndex()].portrait)) def hasCharacters(self): return len(self.characters) > 0 def dump(self): """Serialize to an object valid for JSON dumping.""" return dict(chars=dict([(i, char.dump()) for i, char in enumerate(self.characters)])) def load(self, obj): """Deserialize set of IC characters from a dictionary.""" self.characters = [] self.characterSelector.clear() chars = loadObject('ICChatWidget.chars', obj.get('chars')) chartemp = [None] * len(list(chars.keys())) for ID, char in list(chars.items()): chartemp[int(ID)] = char for char in chartemp: loaded = ICChar.load(char) self._newChar(loaded) self.updateDeleteButton() self.setCharacterPreview() ICChatInput = signal( BASE_STRING, BASE_STRING, BASE_STRING, doc="""Called when in-character chat input is received. charname -- the character name currently selected text -- the message entered portrait -- the portrait path, relative to data/portraits """)
class diceRoller(QDockWidget): def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle(self.tr("Dice")) self.realwidget = QWidget( mainWindow ) #I messed up on the initial setup and was too lazy to rename everything. self.widget = QGridLayout() self.diceArea = QListWidget(mainWindow) try: self.load(jsonload(ospath.join(SAVE_DIR, "dice.rgd"))) except: self.macros = [ QListWidgetItem(QIcon('data/dice.png'), "Sample: 2d6"), QListWidgetItem(QIcon('data/dice.png'), "Sample: 4k2"), QListWidgetItem(QIcon('data/dice.png'), "Sample: 1dn3") ] for m in self.macros: self.diceArea.addItem(m) self.diceArea.currentRowChanged.connect(self.changeCurrentMacro) self.rollbutton = QPushButton(self.tr("Roll"), mainWindow) self.rollbutton.setToolTip( self.tr("Roll dice according to the selected macro.")) self.addmacrobutton = QPushButton(self.tr("Add Macro"), mainWindow) self.addmacrobutton.setToolTip( self.tr("Add a new macro via a dialog box.")) self.removemacrobutton = QPushButton(self.tr("Delete Macro"), mainWindow) self.removemacrobutton.setToolTip( self.tr("Remove the currently selected macro.")) self.rollbutton.clicked.connect(self.rollDice) self.addmacrobutton.clicked.connect(self.summonMacro) self.removemacrobutton.clicked.connect(self.removeCurrentMacro) self.widget.addWidget(self.diceArea, 0, 0) self.widget.addWidget(self.rollbutton, 1, 0) self.widget.addWidget(self.addmacrobutton, 2, 0) self.widget.addWidget(self.removemacrobutton, 3, 0) self.realwidget.setLayout(self.widget) self.setWidget(self.realwidget) self.setObjectName("Dice Widget") mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self) self.close() self.currentMacro = -1 def changeCurrentMacro(self, n): self.currentMacro = n def rollDice(self): current = self.diceArea.item(self.currentMacro) if current is not None: text = UNICODE_STRING(current.text()) self.rollRequested.emit(text[text.rfind(':') + 1:]) def _addMacro(self, macro): self.macros.append(QListWidgetItem(QIcon('data/dice.png'), macro)) self.diceArea.addItem(self.macros[len(self.macros) - 1]) def addMacro(self, mac, macname): self.macros.append( QListWidgetItem(QIcon('data/dice.png'), macname + ': ' + mac)) self.diceArea.addItem(self.macros[len(self.macros) - 1]) jsondump(self.dump(), ospath.join(SAVE_DIR, "dice.rgd")) def removeCurrentMacro(self): if self.diceArea.item(self.currentMacro) != self.diceArea.currentItem( ): #This SHOULD, probably, only occur if there are two items and the first is deleted. Probably. self.diceArea.takeItem(0) return self.diceArea.takeItem(self.currentMacro) jsondump(self.dump(), ospath.join(SAVE_DIR, "dice.rgd")) def summonMacro(self): self.macroRequested.emit() def load(self, obj): """Deserialize set of macros from a dictionary.""" self.macros = [] macroz = loadObject('diceRoller.macros', obj.get('macros')) for ID, macro in list(macroz.items()): self._addMacro(macro) def dump(self): """Serialize to an object valid for JSON dumping.""" macroz = [] for i in range(0, self.diceArea.count()): macroz.append(UNICODE_STRING(self.diceArea.item(i).text())) return dict(macros=dict([(i, macro) for i, macro in enumerate(macroz)])) rollRequested = signal(BASE_STRING, doc="""Called when the roll button is hit. roll -- the dice to be rolled """) macroRequested = signal( doc="""Called when the add macro button is pressed.""")
class pogEditorWidget(QDockWidget): def __init__(self, mainWindow): super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle("Pog Editor") self.setObjectName("Pog Editor") self.currentImage = None self.editedImage = None self.validBorderSizes = [(64, 64), (128, 128), (256, 256)] self.scrollarea = pogEditScrollArea(mainWindow, self) self.openButton = QPushButton("Open File", mainWindow) self.openButton.clicked.connect(self.promptOpenFile) self.saveButton = QPushButton("Save Pog", mainWindow) self.saveButton.clicked.connect(self.promptSaveFile) self.savePortraitButton = QPushButton("Save Portrait", mainWindow) self.savePortraitButton.clicked.connect(self.promptSavePortrait) self.resetButton = QPushButton("Reset Changes", mainWindow) self.resetButton.clicked.connect(self.resetImage) self.borderButton = QPushButton("Add Pog Border", mainWindow) self.borderButton.clicked.connect(self.addPogBorder) self.resizeButton = QPushButton("Resize...", mainWindow) self.resizeButton.clicked.connect(self.promptResize) self.layout = QGridLayout() self.layout.addWidget(self.scrollarea, 0, 0, 1, 3) self.layout.addWidget(self.openButton, 1, 0) self.layout.addWidget(self.borderButton, 1, 1) self.layout.addWidget(self.resizeButton, 1, 2) self.layout.addWidget(self.resetButton, 2, 0) self.layout.addWidget(self.saveButton, 2, 1) self.layout.addWidget(self.savePortraitButton, 2, 2) self.widget = QWidget() self.widget.setLayout(self.layout) self.setAcceptDrops(True) self.setWidget(self.widget) mainWindow.addDockWidget(Qt.RightDockWidgetArea, self) def dragEnterEvent(self, event): if event.mimeData().hasImage(): event.acceptProposedAction() def dropEvent(self, event): if event.mimeData().hasImage(): dat = event.mimeData().imageData() img = QImage(dat) imgbuf = QBuffer() imgbuf.open(QIODevice.ReadWrite) img.save(imgbuf, "PNG") stringio = cStringIO.StringIO() stringio.write(imgbuf.data()) imgbuf.close() stringio.seek(0) final = self.openImage(stringio) self.newImage(final) event.acceptProposedAction() def saveImage(self, image, filename): if ".png" not in filename: #Linux issue workaround image.save(filename + '.png', "PNG", transparency=((254, 0, 254))) else: image.save(filename, "PNG", transparency=((254, 0, 254))) def openImage(self, path): image = im.open(path) image = image.convert("RGB") return image def poggifyImage(self, image): if image.size == (64, 64): overlay = im.open("data/pog_circle_64.png") elif image.size == (128, 128): overlay = im.open("data/pog_circle_128.png") elif image.size == (256, 256): overlay = im.open("data/pog_circle_256.png") else: raise NotImplementedError("Cannot create pogs of size " + str(image.size)) image.paste(overlay, None, overlay) olddat = image.getdata() newdat = [] for pixel in olddat: if pixel[0:3] == (254, 0, 254): newdat.append((254, 0, 254, 255)) else: newdat.append(pixel) image.putdata(newdat) return image def resizeImage(self, image, newsize): return image.resize(newsize, im.ANTIALIAS) def addPogBorder(self): self.editedImage = self.poggifyImage(self.editedImage) self.update() def cropImage(self, image, bounds): return image.crop(bounds) def externalCrop(self, boundA, boundB): if self.editedImage is None: return bounds = (min(boundA[0], boundB[0]), min(boundA[1], boundB[1]), max(boundA[0], boundB[0]), max(boundA[1], boundB[1])) self.editedImage = self.cropImage(self.editedImage, bounds) self.update() def resetImage(self): self.editedImage = self.currentImage self.update() def newImage(self, image): self.currentImage = image self.editedImage = self.currentImage self.update() def promptOpenFile(self): filename = promptLoadFile( 'Open Image', 'Image files (*.png *.jpg *.jpeg *.bmp *.gif *.tga)', POG_DIR) if filename is not None: image = self.openImage(filename) self.newImage(image) def promptSaveFile(self): filename = promptSaveFile('Save Pog', 'Pog files (*.png)', POG_DIR) if filename is not None: self.saveImage(self.editedImage, filename) def promptSavePortrait(self): filename = promptSaveFile('Save Portrait', 'Portrait files (*.png)', PORTRAIT_DIR) if filename is not None: self.saveImage(self.editedImage, filename) def displayImage(self, image): converted = imqt.ImageQt(image) converted = converted.copy() converted = QPixmap.fromImage(converted) label = QLabel() label.setPixmap(converted) self.scrollarea.setWidget(label) if (converted.height(), converted.width()) not in self.validBorderSizes: self.borderButton.setEnabled(False) else: self.borderButton.setEnabled(True) def update(self): self.displayImage(self.editedImage) def promptResize(self): sizesMenu = QMenu() sizeResults = {} for size in self.validBorderSizes: action = QAction("%s x %s" % (size[0], size[1]), self) sizeResults[action.text()] = size sizesMenu.addAction(action) result = sizesMenu.exec_(self.resizeButton.mapToGlobal(QPoint(0, 0))) if result: size = sizeResults[result.text()] self.editedImage = self.resizeImage(self.editedImage, size) self.update()
class scratchPadWidget(QDockWidget): """A mutually-editable shared text widget.""" def __init__(self, mainWindow): """Initializes the user list.""" super(QDockWidget, self).__init__(mainWindow) self.setWindowTitle(self.tr("Scratch Pad")) self.widget = QWidget(mainWindow) self.textArea = QTextEdit(mainWindow) self.currentEditingLabel = QLabel("No one is editing.") self.getLockButton = QPushButton("Edit") self.releaseLockButton = QPushButton("Confirm") #self.saveToFileButton = QPushButton("Save...") #self.loadButton = QPushButton("Load") self.layout = QGridLayout() self.layout.addWidget(self.currentEditingLabel, 0, 0, 1, 2) self.layout.addWidget(self.textArea, 1, 0, 1, 2) self.layout.addWidget(self.getLockButton, 2, 0) self.layout.addWidget(self.releaseLockButton, 2, 1) self.releaseLockButton.pressed.connect(self._releaseLock) self.getLockButton.pressed.connect(self._getLock) self.widget.setLayout(self.layout) self.setWidget(self.widget) self.setObjectName("Scratch Pad Widget") self.hasLock = False self.updateButtonStatus() try: with open(ospath.join(SAVE_DIR, "scratchpad.txt"), 'r') as autosave: self.textArea.setText(autosave.read()) except: pass mainWindow.addDockWidget(Qt.BottomDockWidgetArea, self) @property def currentText(self): return self.textArea.toPlainText() def updateButtonStatus(self): self.getLockButton.setEnabled(not self.hasLock) self.textArea.setReadOnly(not self.hasLock) self.releaseLockButton.setEnabled(self.hasLock) def _getLock(self): self.getScratchPadLock.emit() def _releaseLock(self): self.updateScratchPad.emit() self.releaseScratchPadLock.emit() def getLock(self): self.hasLock = True self.updateButtonStatus() def releaseLock(self, name): self.hasLock = False if name: self.currentEditingLabel.setText("%s is editing." % name) else: self.currentEditingLabel.setText("No one is editing.") self.updateButtonStatus() def updateText(self, txt): if len(txt) > 100000: print("Excessively long scratchpad data received. Might be an attack or just a bug.") return self.textArea.setText(txt) try: with open(ospath.join(SAVE_DIR, "scratchpad.txt"), 'w') as autosave: autosave.write(txt) except: pass getScratchPadLock = signal(doc= """Called to request lock for scratch pad.""" ) releaseScratchPadLock = signal(doc= """Called to indicate relinquishment of scratch pad lock.""" ) updateScratchPad = signal(doc= """Called to request that the scratchpad be updated.""" )