X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Pydun.py;h=ad2399c3dd2ca97bc84a203d0e0f88b78848d6a2;hb=2227f3a5b96f76146f18ccae74c5877d8a8fa6fe;hp=770870b52e8cea930ad41671c83f5e35af7ede81;hpb=83671b1fa22ae6d43cf71e5453754516d6076409;p=pydun%2FPydun.git diff --git a/Pydun.py b/Pydun.py index 770870b..ad2399c 100644 --- a/Pydun.py +++ b/Pydun.py @@ -1,16 +1,19 @@ -#!/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- #Pydun.py - mapping tool #copyright (c) 2013 WATAHIKI Hiroyuki -#url: http://sourceforge.jp/projects/pydun/ +#url: http://osdn.jp/projects/pydun/ #email: hrwatahiki at gmail.com +#twitter: @hrwatahiki +#blog: http://hrwatahiki.blogspot.jp/ import sys import os.path -import codecs import locale +import urllib.request, urllib.parse, urllib.error +import xml.etree.ElementTree import webbrowser from PySide import QtCore, QtGui import yaml @@ -20,8 +23,9 @@ _mapengine = None _mapimages = None _undomanager = None -projecturl = "http://sourceforge.jp/projects/pydun/" -projectversion = "1.0.3" +projecturl = "http://osdn.jp/projects/pydun/" +projectrssurl = "http://osdn.jp/projects/pydun/releases/rss" +projectversion = "1.1.0" class MainWindow(QtGui.QMainWindow): @@ -30,22 +34,23 @@ class MainWindow(QtGui.QMainWindow): global _mapengine global _mapimages global _undomanager + global config super(MainWindow, self).__init__(parent) _undomanager = UndoManager() - _mapimages = MapImages() + _mapimages = MapImages(config.get("showWallMenuString", False)) self.setmenu() _undomanager.changed.connect(self.updateundostate) self.new() if len(sys.argv) >= 2: - self.open(unicode(sys.argv[1], locale.getpreferredencoding())) + self.open(sys.argv[1]) self.mainframe = MainFrame(self) self.setCentralWidget(self.mainframe) self.statusbar = QtGui.QStatusBar(self) - self.statusbar.showMessage(u"") + self.statusbar.showMessage("") self.setStatusBar(self.statusbar) if "windowSize" in config: self.resize( @@ -54,62 +59,68 @@ class MainWindow(QtGui.QMainWindow): config["windowSize"]["height"])) def setmenu(self): + global config #File menu - filemenu = self.menuBar().addMenu(u"ファイル(&F)") + filemenu = self.menuBar().addMenu("ファイル(&F)") - newact = QtGui.QAction(u"新規(&N)", self) + newact = QtGui.QAction("新規(&N)", self) newact.triggered.connect(self.new_triggered) newact.setShortcut(QtGui.QKeySequence.New) filemenu.addAction(newact) - openact = QtGui.QAction(u"開く(&O)...", self) + openact = QtGui.QAction("開く(&O)...", self) openact.triggered.connect(self.open_triggered) openact.setShortcut(QtGui.QKeySequence.Open) filemenu.addAction(openact) - saveact = QtGui.QAction(u"上書き保存(&S)", self) + saveact = QtGui.QAction("上書き保存(&S)", self) saveact.triggered.connect(self.save_triggered) saveact.setShortcut(QtGui.QKeySequence.Save) filemenu.addAction(saveact) - saveasact = QtGui.QAction(u"名前をつけて保存(&A)...", self) + saveasact = QtGui.QAction("名前をつけて保存(&A)...", self) saveasact.triggered.connect(self.saveas_triggered) saveasact.setShortcut(QtGui.QKeySequence.SaveAs) filemenu.addAction(saveasact) - exitact = QtGui.QAction(u"終了(&E)", self) + exitact = QtGui.QAction("終了(&E)", self) exitact.triggered.connect(self.exit_triggered) exitact.setShortcut(QtGui.QKeySequence.Quit) filemenu.addAction(exitact) #Edit menu - editmenu = self.menuBar().addMenu(u"編集(&E)") - self.undoact = QtGui.QAction(u"元に戻す(&U)", self) + editmenu = self.menuBar().addMenu("編集(&E)") + self.undoact = QtGui.QAction("元に戻す(&U)", self) self.undoact.triggered.connect(self.undo_triggered) self.undoact.setShortcut(QtGui.QKeySequence.Undo) editmenu.addAction(self.undoact) - self.redoact = QtGui.QAction(u"やり直し(&R)", self) + self.redoact = QtGui.QAction("やり直し(&R)", self) self.redoact.triggered.connect(self.redo_triggered) self.redoact.setShortcut(QtGui.QKeySequence.Redo) editmenu.addAction(self.redoact) editmenu.addSeparator() - setmapsizeact = QtGui.QAction(u"マップのサイズ(&S)", self) + setmapsizeact = QtGui.QAction("マップのサイズ(&S)", self) setmapsizeact.triggered.connect(self.setmapsize_triggered) editmenu.addAction(setmapsizeact) - setorigineact = QtGui.QAction(u"座標設定(&O)", self) + setorigineact = QtGui.QAction("座標設定(&O)", self) setorigineact.triggered.connect(self.setorigine_triggered) editmenu.addAction(setorigineact) + wallmenustringact = QtGui.QAction("壁メニューに文字を表示する(&W)", self) + wallmenustringact.setCheckable(True) + wallmenustringact.setChecked(config.get("showWallMenuString", False)) + wallmenustringact.triggered.connect(self.togglewallmenustring_triggered) + editmenu.addAction(wallmenustringact) #Help menu - helpmenu = self.menuBar().addMenu(u"ヘルプ(&H)") - tutorialact = QtGui.QAction(u"ヘルプの表示(&H)", self) + helpmenu = self.menuBar().addMenu("ヘルプ(&H)") + tutorialact = QtGui.QAction("ヘルプの表示(&H)", self) tutorialact.triggered.connect(self.tutorial_triggered) tutorialact.setShortcut(QtGui.QKeySequence.HelpContents) helpmenu.addAction(tutorialact) - projectact = QtGui.QAction(u"プロジェクトのWebサイト(&W)", self) + projectact = QtGui.QAction("プロジェクトのWebサイト(&W)", self) projectact.triggered.connect(self.project_triggered) helpmenu.addAction(projectact) - aboutact = QtGui.QAction(u"Pydunについて(&A)...", self) + aboutact = QtGui.QAction("Pydunについて(&A)...", self) aboutact.triggered.connect(self.about_triggered) helpmenu.addAction(aboutact) @@ -125,48 +136,62 @@ class MainWindow(QtGui.QMainWindow): self.redoact.setDisabled(True) def setTitle(self, filename): + s = self.getfilename(filename) + " - Pydun" + self.setWindowTitle(s) + + def getfilename(self, filename): if filename == None: - s = u"新規作成" + s = "無題" else: - s = os.path.basename(filename) - s ="Pydun - " + s - self.setWindowTitle(s) + s = os.path.splitext(os.path.basename(filename))[0] + return s @QtCore.Slot() def new_triggered(self): - if QtGui.QMessageBox.Ok == QtGui.QMessageBox.question( - self, u"確認", u"新しいマップを作成しますか?", - (QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)): + if self.confirmdiscarding(): self.new() + return True + return False def new(self): global _mapengine _mapengine = MapEngine(20, 20, 1, -1, 0, +19) - _undomanager.clear() - _undomanager.save(_mapengine.savestring()) + _undomanager.init(_mapengine.savestring()) self.setTitle(None) try: self.mainframe.mapframe.repaint() except: pass + def confirmdiscarding(self): + if not _undomanager.commited: + dlg = PydunAskSaveDialog(self, self.getfilename(_mapengine.filename)) + ret = dlg.exec_() + if ret == QtGui.QMessageBox.Cancel: + return False + elif ret == QtGui.QMessageBox.Save: + saved = self.save_triggered() + if not saved: + return False + return True + @QtCore.Slot() def open_triggered(self): - d = "" - try: - d = os.path.dirname(_mapengine.filename) - except: - pass - filename = QtGui.QFileDialog.getOpenFileName( - dir=d, - filter=u"*.pydun;;*.*", selectedFilter=u"*.pydun") - if filename[0] != u"": - self.open(filename[0]) + if self.confirmdiscarding(): + d = "" + try: + d = os.path.dirname(_mapengine.filename) + except: + pass + filename = QtGui.QFileDialog.getOpenFileName( + dir=d, + filter="*.pydun;;*.*", selectedFilter="*.pydun") + if filename[0] != "": + self.open(filename[0]) def open(self, filename): _mapengine.load(filename) - _undomanager.clear() - _undomanager.save(_mapengine.savestring()) + _undomanager.init(_mapengine.savestring()) self.setTitle(_mapengine.filename) try: self.mainframe.mapframe.repaint() @@ -177,8 +202,10 @@ class MainWindow(QtGui.QMainWindow): def save_triggered(self): if _mapengine.filename: self.save(_mapengine.filename) + saved = True else: - self.saveas_triggered() + saved = self.saveas_triggered() + return saved @QtCore.Slot() def saveas_triggered(self): @@ -189,12 +216,16 @@ class MainWindow(QtGui.QMainWindow): pass filename = QtGui.QFileDialog.getSaveFileName( dir=d, - filter=u"*.pydun;;*.*", selectedFilter=u"*.pydun") - if filename[0] != u"": + filter="*.pydun;;*.*", selectedFilter="*.pydun") + if filename[0] != "": self.save(filename[0]) + return True + else: + return False def save(self, filename): _mapengine.save(filename) + _undomanager.commit() self.setTitle(_mapengine.filename) @QtCore.Slot() @@ -210,9 +241,7 @@ class MainWindow(QtGui.QMainWindow): def exit(self): global config global configfilename - if QtGui.QMessageBox.Ok == QtGui.QMessageBox.question( - self, u"確認", u"終了しますか?", - (QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)): + if self.confirmdiscarding(): config["windowSize"] = dict() config["windowSize"]["width"] = self.size().width() config["windowSize"]["height"] = self.size().height() @@ -236,14 +265,14 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def setorigine_triggered(self): - title = u"座標設定" + title = "座標設定" if self.mainframe.mapframe.setoriginemode: QtGui.QMessageBox.information( - self, title, u"座標設定を中止します。", QtGui.QMessageBox.Ok) + self, title, "座標設定を中止します。", QtGui.QMessageBox.Ok) self.mainframe.mapframe.setoriginemode = False else: if QtGui.QMessageBox.Ok == QtGui.QMessageBox.information( - self, title, u"基準にする地点をクリックしてください。", + self, title, "基準にする地点をクリックしてください。", (QtGui.QMessageBox.Ok| QtGui.QMessageBox.Cancel)): self.mainframe.mapframe.setoriginemode = True @@ -259,8 +288,16 @@ class MainWindow(QtGui.QMainWindow): self.mainframe.mapframe.repaint() @QtCore.Slot() + def togglewallmenustring_triggered(self): + global config + config["showWallMenuString"] = not config.get("showWallMenuString", False) + QtGui.QMessageBox.information( + self, "壁メニューに文字を表示する", "表示の切替は再起動後に有効になります。", + (QtGui.QMessageBox.Ok)) + + @QtCore.Slot() def tutorial_triggered(self): - url = os.path.dirname(os.path.abspath(__file__)) + "/help/index.html" + url = basedir() + "/help/index.html" webbrowser.open_new_tab(url) @QtCore.Slot() @@ -270,15 +307,17 @@ class MainWindow(QtGui.QMainWindow): @QtCore.Slot() def about_triggered(self): QtGui.QMessageBox.about(self, "Pydun", - u"

Pydun.py "+ projectversion + "

" - u"

Copyright (c) 2013 WATAHIKI Hiroyuki

" - u"

url: " + projecturl + "

" - u"

e-mail: hrwatahiki at gmail.com

" - u"

このソフトウェアはMITライセンスです。

" - u"

このソフトウェアは以下のソフトウェアを使用しています。: " - u"Python, PySide, PyYAML " - u"これらの作成者に深く感謝いたします。

" - u"

詳細はLICENCE.txtを参照してください。

") + "

Pydun.py "+ projectversion + "

" + "

Copyright (c) 2013 WATAHIKI Hiroyuki

" + "

url: " + projecturl + "

" + "

e-mail: hrwatahiki at gmail.com

" + "

twitter: @hrwatahiki

" + "

blog: 作業記録

" + "

このソフトウェアはMITライセンスです。

" + "

このソフトウェアは以下のソフトウェアを使用しています。: " + "Python, PySide, PyYAML " + "これらの作成者に深く感謝いたします。

" + "

詳細はLICENCE.txtを参照してください。

") class MainFrame(QtGui.QFrame): @@ -293,30 +332,30 @@ class MainFrame(QtGui.QFrame): self.detail = QtGui.QLabel(self) self.detail.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) - self.detail.setText(u"") + self.detail.setText("") self.detail.setMaximumHeight(100) self.detail.setMinimumHeight(100) self.boxdrawbutton = QtGui.QRadioButton(self) - self.boxdrawbutton.setText(u"ボックス形式で壁を描画(&B)") + self.boxdrawbutton.setText("ボックス形式で壁を描画(&B)") self.boxdrawbutton.setChecked(True) self.boxdrawbutton.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.growdrawbutton = QtGui.QRadioButton(self) - self.growdrawbutton.setText(u"足跡形式で壁を描画(&G)") + self.growdrawbutton.setText("足跡形式で壁を描画(&G)") self.growdrawbutton.setChecked(False) self.growdrawbutton.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.backcolorbutton = QtGui.QRadioButton(self) - self.backcolorbutton.setText(u"背景色(&C)") + self.backcolorbutton.setText("背景色(&C)") self.backcolorbutton.setChecked(False) self.backcolorbutton.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.setbackcolorbutton = QtGui.QPushButton(self) - self.setbackcolorbutton.setText(u"背景色を設定(&S)...") + self.setbackcolorbutton.setText("背景色を設定(&S)...") self.setbackcolorbutton.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) @@ -325,6 +364,12 @@ class MainFrame(QtGui.QFrame): self.backcolorbox.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + latestversion = getlatestversion() + if latestversion != projectversion: + self.update = QtGui.QLabel(self) + self.update.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) + self.update.setText("最新のPydun({ver})がダウンロードできます。".format(url=projecturl, ver=latestversion)) + self.update.setOpenExternalLinks(True) layout = QtGui.QGridLayout(self) layout.addWidget(scrollarea, 0, 0, 1, 3) @@ -334,6 +379,8 @@ class MainFrame(QtGui.QFrame): layout.addWidget(self.backcolorbutton, 3, 1, 1, 2) layout.addWidget(self.setbackcolorbutton, 4, 1, 1, 1) layout.addWidget(self.backcolorbox, 4, 2, 1, 1) + if latestversion != projectversion: + layout.addWidget(self.update, 5, 0, 1, 3) self.setLayout(layout) @@ -351,7 +398,7 @@ class MainFrame(QtGui.QFrame): def create_wall_menu(self, direction): menu = QtGui.QMenu(self) for idx, img in enumerate(_mapimages.wall_icons): - act = QtGui.QAction(self) + act = QtGui.QAction(_mapimages.wall_texts[idx][direction], self) act.setIcon(img[direction]) def triggerd(idx): @@ -365,7 +412,7 @@ class MainFrame(QtGui.QFrame): @QtCore.Slot(int, int, int) def mouse_moved(self, x=0, y=0, b=QtCore.Qt.MouseButton.NoButton): - cood = u"({x}, {y})\n".format(x=_mapengine.viewx(x), y=_mapengine.viewy(y)) + cood = "({x}, {y})\n".format(x=_mapengine.viewx(x), y=_mapengine.viewy(y)) self.detail.setText(cood + _mapengine.getdetail(x, y)) self.mapframe.repaint() @@ -649,20 +696,20 @@ class DetailDialog(QtGui.QDialog): marklabel = QtGui.QLabel(self) marklabel.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight) - marklabel.setText(u"マーク(&M)") + marklabel.setText("マーク(&M)") marklabel.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) self.marktext = QtGui.QLineEdit(self) self.marktext.setMaxLength(1) - self.marktext.setText(u"") + self.marktext.setText("") self.marktext.setMinimumWidth(20) self.marktext.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) marklabel.setBuddy(self.marktext) self.forecolorbutton = QtGui.QPushButton(self) - self.forecolorbutton.setText(u"文字色(&C)...") + self.forecolorbutton.setText("文字色(&C)...") self.forecolorbutton.clicked.connect(self.forecolorbutton_clicked) self.forecolorbox = ColorBox(self) @@ -672,16 +719,18 @@ class DetailDialog(QtGui.QDialog): detaillabel = QtGui.QLabel(self) detaillabel.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) - detaillabel.setText(u"詳細(&D)") + detaillabel.setText("詳細(&D)") self.detailtext = QtGui.QTextEdit(self) - self.detailtext.setText(u"") + self.detailtext.setText("") detaillabel.setBuddy(self.detailtext) - self.buttonBox = QtGui.QDialogButtonBox( + self.buttonbox = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) + self.buttonbox.accepted.connect(self.accept) + self.buttonbox.rejected.connect(self.reject) + self.buttonbox.button(QtGui.QDialogButtonBox.Ok).setText("OK") + self.buttonbox.button(QtGui.QDialogButtonBox.Cancel).setText("キャンセル") layout = QtGui.QGridLayout() layout.addWidget(marklabel, 0, 0, 1, 1) @@ -690,12 +739,12 @@ class DetailDialog(QtGui.QDialog): layout.addWidget(self.forecolorbox, 0, 3, 1, 1) layout.addWidget(detaillabel, 1, 0, 1, 1) layout.addWidget(self.detailtext, 1, 1, 1, 3) - layout.addWidget(self.buttonBox, 2, 0, 1, 4) + layout.addWidget(self.buttonbox, 2, 0, 1, 4) self.setLayout(layout) self.setModal(True) def setvalue(self, x, y, mark, detail, color): - self.setWindowTitle("({x},{y})".format(x=x, y=y)) + self.setWindowTitle("({x}, {y})".format(x=x, y=y)) self.marktext.setText(mark) self.detailtext.setText(detail) self.forecolorbox.color = color @@ -709,25 +758,26 @@ class DetailDialog(QtGui.QDialog): if dlg.result() == QtGui.QDialog.Accepted: self.forecolorbox.color = dlg.currentColor() + class SetOrigineDialog(QtGui.QDialog): def __init__(self, parent=None): super(SetOrigineDialog, self).__init__(parent) - self.setWindowTitle(u"座標設定") + self.setWindowTitle("座標設定") promptlabel = QtGui.QLabel(self) promptlabel.setAlignment( QtCore.Qt.AlignVCenter | QtCore.Qt.AlignLeft) - promptlabel.setText(u"この地点の座標を入力してください。") + promptlabel.setText("この地点の座標を入力してください。") self.currentlabel = QtGui.QLabel(self) self.currentlabel.setAlignment( QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter) - self.currentlabel.setText(u"") + self.currentlabel.setText("") xlabel = QtGui.QLabel(self) xlabel.setAlignment( QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight) - xlabel.setText(u"&X") + xlabel.setText("&X") self.xbox = QtGui.QSpinBox(self) self.xbox.setRange(-999, +999) @@ -737,7 +787,7 @@ class SetOrigineDialog(QtGui.QDialog): ylabel = QtGui.QLabel(self) ylabel.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight) - ylabel.setText(u"&Y") + ylabel.setText("&Y") self.ybox = QtGui.QSpinBox(self) self.ybox.setRange(-999, +999) @@ -745,10 +795,12 @@ class SetOrigineDialog(QtGui.QDialog): self.ybox.setValue(0) ylabel.setBuddy(self.ybox) - self.buttonBox = QtGui.QDialogButtonBox( + self.buttonbox = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) - self.buttonBox.accepted.connect(self.accept) - self.buttonBox.rejected.connect(self.reject) + self.buttonbox.accepted.connect(self.accept) + self.buttonbox.rejected.connect(self.reject) + self.buttonbox.button(QtGui.QDialogButtonBox.Ok).setText("OK") + self.buttonbox.button(QtGui.QDialogButtonBox.Cancel).setText("キャンセル") layout = QtGui.QGridLayout() layout.addWidget(promptlabel, 0, 0, 1, 4) @@ -757,14 +809,14 @@ class SetOrigineDialog(QtGui.QDialog): layout.addWidget(self.xbox, 2, 1, 1, 1) layout.addWidget(ylabel, 2, 2, 1, 1) layout.addWidget(self.ybox, 2, 3, 1, 1) - layout.addWidget(self.buttonBox, 3, 0, 1, 4) + layout.addWidget(self.buttonbox, 3, 0, 1, 4) self.setLayout(layout) self.setModal(True) def setcurrent(self, x, y): self.xbox.setValue(x) self.ybox.setValue(y) - self.currentlabel.setText(u"現在の座標 ({x}, {y})".format(x=x, y=y)) + self.currentlabel.setText("現在の座標 ({x}, {y})".format(x=x, y=y)) @property def originex(self): @@ -778,10 +830,10 @@ class SetOrigineDialog(QtGui.QDialog): class SetSizeDialog(QtGui.QDialog): def __init__(self, parent=None): super(SetSizeDialog, self).__init__(parent) - self.setWindowTitle(u"マップのサイズ") + self.setWindowTitle("マップのサイズ") self.topbutton = QtGui.QRadioButton(self) - self.topbutton.setText(u"上(&T)") + self.topbutton.setText("上(&T)") self.topbutton.clicked.connect(self.updatewidgets) self.topsize = QtGui.QSpinBox(self) @@ -790,7 +842,7 @@ class SetSizeDialog(QtGui.QDialog): self.topsize.valueChanged.connect(self.updatewidgets) self.bottombutton = QtGui.QRadioButton(self) - self.bottombutton.setText(u"下(&B)") + self.bottombutton.setText("下(&B)") self.bottombutton.clicked.connect(self.updatewidgets) self.bottomsize = QtGui.QSpinBox(self) @@ -799,7 +851,7 @@ class SetSizeDialog(QtGui.QDialog): self.bottomsize.valueChanged.connect(self.updatewidgets) self.leftbutton = QtGui.QRadioButton(self) - self.leftbutton.setText(u"左(&L)") + self.leftbutton.setText("左(&L)") self.leftbutton.clicked.connect(self.updatewidgets) self.leftsize = QtGui.QSpinBox(self) @@ -808,7 +860,7 @@ class SetSizeDialog(QtGui.QDialog): self.leftsize.valueChanged.connect(self.updatewidgets) self.rightbutton = QtGui.QRadioButton(self) - self.rightbutton.setText(u"右(&R)") + self.rightbutton.setText("右(&R)") self.rightbutton.clicked.connect(self.updatewidgets) self.rightsize = QtGui.QSpinBox(self) @@ -819,12 +871,14 @@ class SetSizeDialog(QtGui.QDialog): self.sizelabel = QtGui.QLabel(self) self.sizelabel .setAlignment( QtCore.Qt.AlignVCenter | QtCore.Qt.AlignLeft) - self.sizelabel.setText(u"この地点の座標を入力してください。") + self.sizelabel.setText("この地点の座標を入力してください。") self.buttonbox = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) self.buttonbox.accepted.connect(self.accept) self.buttonbox.rejected.connect(self.reject) + self.buttonbox.button(QtGui.QDialogButtonBox.Ok).setText("OK") + self.buttonbox.button(QtGui.QDialogButtonBox.Cancel).setText("キャンセル") verticalgroup = QtGui.QButtonGroup(self) verticalgroup.addButton(self.topbutton) @@ -884,7 +938,7 @@ class SetSizeDialog(QtGui.QDialog): self.rightsize.setEnabled(True) self.sizelabel.setText( - u"変更前のサイズ: {w1} x {h1}\n変更後のサイズ: {w2} x {h2}".format( + "変更前のサイズ: {w1} x {h1}\n変更後のサイズ: {w2} x {h2}".format( w1=self._width, h1=self._height, w2=self._width+dw, h2=self._height+dh)) @@ -905,21 +959,31 @@ class SetSizeDialog(QtGui.QDialog): class MapImages(object): - def __init__(self): + def __init__(self, show_wall_menu_string): + if show_wall_menu_string: + vtext = ["なし", "壁", "扉", "扉(→)", "扉(←)", "一通(→)", "一通(←)", "隠", "隠(→)", "隠(←)",] + htext = ["なし", "壁", "扉", "扉(↓)", "扉(↑)", "一通(↓)", "一通(↑)", "隠", "隠(↓)", "隠(↑)",] + else: + vtext = ["", "", "", "", "", "", "", "", "", "",] + htext = ["", "", "", "", "", "", "", "", "", "",] self.wall_images = list() self.wall_icons = list() + self.wall_texts = list() for index in range(10): self.wall_images.append(dict()) self.wall_icons.append(dict()) + self.wall_texts.append(dict()) for direction in ["v", "h"]: filename = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - u"images", - u"wall_{direction}_{index:02}.png".format( + basedir(), + "images", + "wall_{direction}_{index:02}.png".format( direction=direction, index=index)) self.wall_images[index][direction] = QtGui.QImage() self.wall_images[index][direction].load(filename) self.wall_icons[index][direction] = QtGui.QIcon(filename) + self.wall_texts[index]["v"] = vtext[index] + self.wall_texts[index]["h"] = htext[index] @property def width(self): @@ -978,8 +1042,8 @@ class MapEngine(object): def represent_unicode(dumper, data): return dumper.represent_scalar("tag:yaml.org,2002:str", data) def construct_unicode(loader, node): - return unicode(loader.construct_scalar(node)) - yaml.add_representer(unicode, represent_unicode) + return str(loader.construct_scalar(node)) + yaml.add_representer(str, represent_unicode) yaml.add_constructor("tag:yaml.org,2002:str", construct_unicode) def getdata(self, x, y, direction): @@ -1030,13 +1094,13 @@ class MapEngine(object): def getnote(self, x, y): return self._note.get( - self.coodtokey(x, y), {"mark":u"", "detail":u"", "forecolor":u"#000000", "backcolor":u""}) + self.coodtokey(x, y), {"mark":"", "detail":"", "forecolor":"#000000", "backcolor":""}) def coodtokey(self, x, y): - return u"{x:+05d}_{y:+05d}".format(x=x, y=y) + return "{x:+05d}_{y:+05d}".format(x=int(x), y=int(y)) def keytocood(self, key): - return map(int, key.split("_")) + return list(map(int, key.split("_"))) def setmark(self, x, y, mark): note = self.getnote(x, y) @@ -1172,7 +1236,7 @@ class MapEngine(object): def save(self, filename): dt = self.savestring() - with codecs.open(filename, "w") as f: + with open(filename, "w", encoding='utf-8') as f: f.write(dt) self.filename = filename @@ -1185,13 +1249,13 @@ class MapEngine(object): #noteは表示用に座標変換する。 n = dict() - for nk, ni in self._note.items(): + for nk, ni in list(self._note.items()): if ni["mark"] != "" or ni["detail"] != "" or ni["backcolor"]: x, y = self.keytocood(nk) n[self.coodtokey(self.viewx(x), self.viewy(y))] = ni data["note"] = n return yaml.safe_dump(data, allow_unicode=True, - default_flow_style=False, encoding='utf-8') + default_flow_style=False, encoding='utf-8').decode('utf-8') def getmapstring(self): #出力用マップ作成 @@ -1222,7 +1286,7 @@ class MapEngine(object): return m def load(self, filename): - with codecs.open(filename, "r", encoding="utf-8") as f: + with open(filename, "r", encoding="utf-8") as f: st = f.read() self.loadfromstring(st) self.filename = filename @@ -1253,7 +1317,7 @@ class MapEngine(object): #noteは内部用に座標変換する。 n = dict() - for nk, ni in data["note"].items(): + for nk, ni in list(data["note"].items()): if ni["mark"] != "" or ni["detail"] != "" or ni["backcolor"] != "": x, y = self.keytocood(nk) n[self.coodtokey(self.worldx(x), self.worldy(y))] = ni @@ -1273,8 +1337,14 @@ class UndoManager(QtCore.QObject): self._undo = [None for x in range(self.MAX_UNDO_COUNT)] self._index = 0 self._undocount = 0 + self._commited = True self.changed.emit(self.canundo, self.canredo) + def init(self, data): + self.clear() + self.save(data) + self._commited = True + def save(self, obj): if self._index >= self.MAX_UNDO_COUNT: self._undo = self._undo[1:] @@ -1283,20 +1353,26 @@ class UndoManager(QtCore.QObject): self._undo[self._index] = obj self._index += 1 self._undocount = 0 + self._commited = False self.changed.emit(self.canundo, self.canredo) def undo(self): self._index -= 1 self._undocount += 1 + self._commited = False self.changed.emit(self.canundo, self.canredo) return self._undo[self._index - 1] def redo(self): self._index += 1 self._undocount -= 1 + self._commited = False self.changed.emit(self.canundo, self.canredo) return self._undo[self._index - 1] + def commit(self): + self._commited = True + @property def canundo(self): return (self._index > 1) @@ -1305,6 +1381,10 @@ class UndoManager(QtCore.QObject): def canredo(self): return (self._undocount > 0) + @property + def commited(self): + return self._commited + class PydunColorDialog(QtGui.QColorDialog): def __init__(self, parent, config): @@ -1330,6 +1410,17 @@ class PydunColorDialog(QtGui.QColorDialog): return self._config +class PydunAskSaveDialog(QtGui.QMessageBox): + def __init__(self, parent, filename): + super(PydunAskSaveDialog, self).__init__(parent) + self.setText("{filename} への変更を保存しますか?".format(filename=filename)) + self.setStandardButtons(QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel) + self.setDefaultButton(QtGui.QMessageBox.Save) + self.button(QtGui.QMessageBox.Save).setText("保存する(&S)") + self.button(QtGui.QMessageBox.Discard).setText("保存しない(&N)") + self.button(QtGui.QMessageBox.Cancel).setText("キャンセル") + + def getcolorstring(color): return "#{r:02x}{g:02x}{b:02x}".format(r=color.red(), g=color.green(), b=color.blue()) @@ -1339,6 +1430,21 @@ def getcolorfromstring(colorstring): int(colorstring[3:5], 16), int(colorstring[5:7], 16)) +def basedir(): + return os.path.dirname(os.path.abspath(sys.argv[0])) + +def getlatestversion(): + try: + rss = urllib.request.urlopen(projectrssurl) + rssstring = rss.read() + rsstree = xml.etree.ElementTree.fromstring(rssstring) + item = rsstree.find("channel/item/title") + ver = (item.text.split(" "))[2] + rss.close() + except: + ver = projectversion + return ver + def main(): loadconfig() @@ -1352,8 +1458,8 @@ def loadconfig(): global config global configfilename configfilename = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - u"Pydun.config") + basedir(), + "Pydun.config") try: with open(configfilename, "r") as f: config = yaml.safe_load(f)