2 #include "simpletextview.h"
3 #include "mainwindow.h"
12 QString KeyEventToSequence(const QKeyEvent *event)
14 QString modifier = QString::null;
15 if (event->modifiers() & Qt::ShiftModifier) { modifier += "Shift+"; }
16 if (event->modifiers() & Qt::ControlModifier) { modifier += "Ctrl+"; }
17 if (event->modifiers() & Qt::AltModifier) { modifier += "Alt+"; }
18 if (event->modifiers() & Qt::MetaModifier) { modifier += "Meta+"; }
20 QString key = QKeySequence(event->key()).toString();
21 return QKeySequence(modifier + key).toString();
24 SimpleTextView::SimpleTextView(QWidget *parent) :
25 QPlainTextEdit(parent),
38 setContextMenuPolicy(Qt::DefaultContextMenu);
39 m_convEUC = new QAction(tr("EUC-JPで再読込"), this);
40 m_convJIS = new QAction(tr("ISO 2022-JP(JIS)で再読込"), this);
41 m_convSJIS = new QAction(tr("Shift-JISで再読込"), this);
42 m_convUTF8 = new QAction(tr("UTF-8で再読込"), this);
43 m_convUTF16 = new QAction(tr("UTF-16で再読込"), this);
44 m_convUTF16BE = new QAction(tr("UTF-16BEで再読込"), this);
45 m_convUTF16LE = new QAction(tr("UTF-16LEで再読込"), this);
46 m_copy = new QAction(tr("選択範囲をクリップボードにコピー"), this);
47 m_back = new QAction(tr("戻る"), this);
49 m_convEUC->setShortcut(QKeySequence("Shift+E"));
50 m_convJIS->setShortcut(QKeySequence("Shift+J"));
51 m_convSJIS->setShortcut(QKeySequence("Shift+S"));
52 m_convUTF8->setShortcut(QKeySequence("Shift+U"));
53 m_convUTF16->setShortcut(QKeySequence("Shift+I"));
54 m_convUTF16BE->setShortcut(QKeySequence("Shift+O"));
55 m_convUTF16LE->setShortcut(QKeySequence("Shift+P"));
56 m_copy->setShortcut(QKeySequence::Copy);
57 m_back->setShortcut(QKeySequence("Return"));
59 connect(m_convEUC, SIGNAL(triggered()), this, SLOT(convertFromEUC()));
60 connect(m_convJIS, SIGNAL(triggered()), this, SLOT(convertFromJIS()));
61 connect(m_convSJIS, SIGNAL(triggered()), this, SLOT(convertFromSJIS()));
62 connect(m_convUTF8, SIGNAL(triggered()), this, SLOT(convertFromUTF8()));
63 connect(m_convUTF16, SIGNAL(triggered()), this, SLOT(convertFromUTF16()));
64 connect(m_convUTF16BE, SIGNAL(triggered()), this, SLOT(convertFromUTF16BE()));
65 connect(m_convUTF16LE, SIGNAL(triggered()), this, SLOT(convertFromUTF16LE()));
66 connect(m_copy, SIGNAL(triggered()), this, SLOT(copy()));
67 connect(m_back, SIGNAL(triggered()), this, SLOT(back()));
69 connect(this, SIGNAL(copyAvailable(bool)), this, SLOT(onCopyAvailable(bool)));
71 m_copy->setEnabled(false);
74 void SimpleTextView::setSource(const QByteArray &source)
79 const char UTF8_BOM[] = { 0xEF, 0xBB, 0xBF };
80 const char UTF16BE_BOM[] = { 0xFE, 0xFF };
81 const char UTF16LE_BOM[] = { 0xFF, 0xFE };
83 if (m_source.indexOf(QByteArray(UTF8_BOM)) == 0) {
84 qDebug() << "Detect UTF-8 BOM";
87 else if (m_source.indexOf(QByteArray(UTF16BE_BOM)) == 0 ||
88 m_source.indexOf(QByteArray(UTF16LE_BOM)) == 0)
90 qDebug() << "Detect UTF-16 BOM";
94 QByteArray first1KB = m_source.left(1024);
96 QTextCodec *codec = QTextCodec::codecForName("UTF-8");
97 QString text = codec->toUnicode(first1KB).toLower();
98 if (text.indexOf("utf8") != -1 || text.indexOf("utf-8") != -1) {
102 if (text.indexOf("sjis") != -1 || text.indexOf("shift-jis") != -1 ||
103 text.indexOf("shift_jis") != -1)
108 if (text.indexOf("euc") != -1 || text.indexOf("euc-jp") != -1 ||
109 text.indexOf("euc_jp") != -1)
114 if (text.indexOf("jis") != -1 || text.indexOf("iso 2022-jp") != -1) {
119 std::string code = detectCode(first1KB);
120 codec = QTextCodec::codecForName(code.c_str());
121 setPlainText(codec->toUnicode(m_source));
122 getMainWnd()->statusBar()->showMessage(code.c_str());
125 void SimpleTextView::updateAppearance()
129 QPalette pal = this->palette();
130 if (settings.value(IniKey_ViewerInherit).toBool()) {
131 pal.setColor(QPalette::Base,
132 settings.value(IniKey_ViewColorBgNormal).value<QColor>());
133 pal.setColor(QPalette::Text,
134 settings.value(IniKey_ViewColorFgNormal).value<QColor>());
137 pal.setColor(QPalette::Base,
138 settings.value(IniKey_ViewerColorBg).value<QColor>());
139 pal.setColor(QPalette::Text,
140 settings.value(IniKey_ViewerColorFg).value<QColor>());
143 setFont(settings.value(IniKey_ViewerFont).value<QFont>());
146 void SimpleTextView::convertFromEUC()
148 QTextCodec *codec = QTextCodec::codecForName("EUC-JP");
149 setPlainText(codec->toUnicode(m_source));
150 getMainWnd()->statusBar()->showMessage("EUC-JP");
153 void SimpleTextView::convertFromJIS()
155 QTextCodec *codec = QTextCodec::codecForName("ISO 2022-JP");
156 setPlainText(codec->toUnicode(m_source));
157 getMainWnd()->statusBar()->showMessage("ISO 2022-JP");
160 void SimpleTextView::convertFromSJIS()
162 QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
163 setPlainText(codec->toUnicode(m_source));
164 getMainWnd()->statusBar()->showMessage("Shift-JIS");
168 void SimpleTextView::convertFromUTF8()
170 QTextCodec *codec = QTextCodec::codecForName("UTF-8");
171 setPlainText(codec->toUnicode(m_source));
172 getMainWnd()->statusBar()->showMessage("UTF-8");
175 void SimpleTextView::convertFromUTF16()
177 QTextCodec *codec = QTextCodec::codecForName("UTF-16");
178 setPlainText(codec->toUnicode(m_source));
179 getMainWnd()->statusBar()->showMessage("UTF-16");
182 void SimpleTextView::convertFromUTF16BE()
184 QTextCodec *codec = QTextCodec::codecForName("UTF-16BE");
185 setPlainText(codec->toUnicode(m_source));
186 getMainWnd()->statusBar()->showMessage("UTF-16BE");
189 void SimpleTextView::convertFromUTF16LE()
191 QTextCodec *codec = QTextCodec::codecForName("UTF-16LE");
192 setPlainText(codec->toUnicode(m_source));
193 getMainWnd()->statusBar()->showMessage("UTF-16LE");
196 void SimpleTextView::onCopyAvailable(bool yes)
198 m_copy->setEnabled(yes);
201 void SimpleTextView::back()
203 emit viewFinished(this);
206 void SimpleTextView::keyPressEvent(QKeyEvent *event)
208 QString ksq = KeyEventToSequence(event);
210 if (ksq == "Return" || ksq == "Backspace" || ksq == "W") {
211 emit viewFinished(this);
216 if (!ksq.isEmpty()) {
217 foreach (QObject *obj, this->children()) {
218 QAction *action = qobject_cast<QAction*>(obj);
219 if (action && action->isEnabled()) {
220 foreach (const QKeySequence &keySeq, action->shortcuts()) {
221 if (ksq == keySeq.toString()) {
222 qDebug() << "emit " << ksq << " " << action->objectName();
223 emit action->triggered();
231 foreach (QObject *obj, getMainWnd()->children()) {
232 QAction *action = qobject_cast<QAction*>(obj);
233 if (action && action->isEnabled()) {
234 foreach (const QKeySequence &keySeq, action->shortcuts()) {
235 if (ksq == keySeq.toString()) {
236 qDebug() << "emit " << ksq << " " << action->objectName();
237 emit action->triggered();
246 if (ksq != "Down" && ksq != "Up") {
250 QPlainTextEdit::keyPressEvent(event);
254 void SimpleTextView::contextMenuEvent(QContextMenuEvent *event)
256 qDebug() << "contextMenuEvent();";
258 menu.addAction(m_convEUC);
259 menu.addAction(m_convJIS);
260 menu.addAction(m_convSJIS);
261 menu.addAction(m_convUTF8);
262 menu.addAction(m_convUTF16BE);
263 menu.addAction(m_convUTF16LE);
265 menu.addAction(m_copy);
267 menu.addAction(m_back);
268 menu.exec(event->globalPos());
271 // http://dobon.net/vb/dotnet/string/detectcode.html より拝借
272 std::string SimpleTextView::detectCode(const QByteArray &bytes)
274 typedef unsigned char byte;
275 const byte bEscape = 0x1B;
276 const byte bAt = 0x40;
277 const byte bDollar = 0x24;
278 const byte bAnd = 0x26;
279 const byte bOpen = 0x28; //'('
280 const byte bB = 0x42;
281 const byte bD = 0x44;
282 const byte bJ = 0x4A;
283 const byte bI = 0x49;
285 int len = bytes.size();
288 bool isBinary = false;
289 for (int i = 0; i < len; i++) {
291 if (b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF) {
294 if (b1 == 0x00 && i < len - 1 && static_cast<byte>(bytes[i + 1]) <= 0x7F) {
303 bool notJapanese = true;
304 for (int i = 0; i < len; i++) {
306 if (b1 == bEscape || 0x80 <= b1) {
315 for (int i = 0; i < len - 2; i++) {
321 if ((b2 == bDollar && b3 == bAt) ||
322 (b2 == bDollar && b3 == bB) ||
323 (b2 == bOpen && (b3 == bB || b3 == bJ)) ||
324 (b2 == bOpen && b3 == bI))
326 return "ISO 2022-JP";
330 if (b2 == bDollar && b3 == bOpen && b4 == bD) {
331 return "ISO 2022-JP";
334 b2 == bAnd && b3 == bAt && b4 == bEscape &&
335 bytes[i + 4] == bDollar && bytes[i + 5] == bB)
337 return "ISO 2022-JP";
346 for (int i = 0; i < len - 1; i++) {
349 if (((0x81 <= b1 && b1 <= 0x9F) || (0xE0 <= b1 && b1 <= 0xFC)) &&
350 ((0x40 <= b2 && b2 <= 0x7E) || (0x80 <= b2 && b2 <= 0xFC)))
356 for (int i = 0; i < len - 1; i++) {
359 if (((0xA1 <= b1 && b1 <= 0xFE) && (0xA1 <= b2 && b2 <= 0xFE)) ||
360 (b1 == 0x8E && (0xA1 <= b2 && b2 <= 0xDF)))
365 else if (i < len - 2) {
367 if (b1 == 0x8F && (0xA1 <= b2 && b2 <= 0xFE) &&
368 (0xA1 <= b3 && b3 <= 0xFE))
375 for (int i = 0; i < len - 1; i++) {
378 if ((0xC0 <= b1 && b1 <= 0xDF) && (0x80 <= b2 && b2 <= 0xBF)) {
382 else if (i < len - 2) {
384 if ((0xE0 <= b1 && b1 <= 0xEF) && (0x80 <= b2 && b2 <= 0xBF) &&
385 (0x80 <= b3 && b3 <= 0xBF))
393 if (euc > sjis && euc > utf8) {
396 else if (sjis > euc && sjis > utf8) {
399 else if (utf8 > euc && utf8 > sjis) {