OSDN Git Service

Ver0.22
[gefu/Gefu.git] / simpletextview.cpp
1 #include "mainwindow.h"
2 #include "preferences.h"
3 #include "simpletextview.h"
4
5 #include <QDebug>
6 #include <QMenu>
7 #include <QSettings>
8 #include <QShortcut>
9 #include <QTextCodec>
10 #include <QStatusBar>
11 #include <QApplication>
12
13 ///////////////////////////////////////////////////////////////////////////////
14 /// \brief SimpleTextView::SimpleTextView
15 /// \param parent   親ウィジェット
16 ///
17 /// コンストラクタ
18 ///
19 SimpleTextView::SimpleTextView(QWidget *parent) :
20     QPlainTextEdit(parent),
21     AbstractView(),
22     m_source()
23 {
24     setReadOnly(true);
25     setContextMenuPolicy(Qt::NoContextMenu);
26 }
27
28 ///////////////////////////////////////////////////////////////////////////////
29 /// \brief SimpleTextView::initialize
30 /// \param w    メインウィンドウオブジェクト
31 ///
32 /// 初期化処理を行います。
33 ///
34 void SimpleTextView::initialize(MainWindow *w)
35 {
36     qDebug() << "SimpleTextView::initialize()";
37
38     connect(this, SIGNAL(statusChanged(QString)), w, SLOT(view_statusChanged(QString)));
39     connect(this, SIGNAL(copyAvailable(bool)), w, SLOT(view_copyAvailable(bool)));
40
41     installEventFilter(w);
42 }
43
44 ///////////////////////////////////////////////////////////////////////////////
45 /// \brief SimpleTextView::setSource
46 /// \param source   表示するデータ
47 ///
48 /// データを表示します。
49 ///
50 void SimpleTextView::setSource(const QByteArray &source)
51 {
52     qDebug() << "SimpleTextView::setSource()" << source.size();
53
54     m_source = source;
55     if (m_source.size() == 0) {
56         setPlainText("");
57         emit statusChanged("");
58         return;
59     }
60
61     std::string code = detectCode(m_source.left(1024));
62     QTextCodec *codec = QTextCodec::codecForName(code.c_str());
63
64     setPlainText(codec->toUnicode(m_source));
65
66     emit statusChanged(code.c_str());
67 }
68
69 void SimpleTextView::convertFromEUC()
70 {
71     QTextCodec *codec = QTextCodec::codecForName("EUC-JP");
72     setPlainText(codec->toUnicode(m_source));
73     emit statusChanged("EUC-JP");
74 }
75
76 void SimpleTextView::convertFromJIS()
77 {
78     QTextCodec *codec = QTextCodec::codecForName("ISO 2022-JP");
79     setPlainText(codec->toUnicode(m_source));
80     emit statusChanged("ISO 2022-JP");
81 }
82
83 void SimpleTextView::convertFromSJIS()
84 {
85     QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
86     setPlainText(codec->toUnicode(m_source));
87     emit statusChanged("Shift-JIS");
88 }
89
90 void SimpleTextView::convertFromUTF8()
91 {
92     QTextCodec *codec = QTextCodec::codecForName("UTF-8");
93     setPlainText(codec->toUnicode(m_source));
94     emit statusChanged("UTF-8");
95 }
96
97 void SimpleTextView::convertFromUTF16()
98 {
99     QTextCodec *codec = QTextCodec::codecForName("UTF-16");
100     setPlainText(codec->toUnicode(m_source));
101     emit statusChanged("UTF-16");
102 }
103
104 void SimpleTextView::convertFromUTF16BE()
105 {
106     QTextCodec *codec = QTextCodec::codecForName("UTF-16BE");
107     setPlainText(codec->toUnicode(m_source));
108     emit statusChanged("UTF-16BE");
109 }
110
111 void SimpleTextView::convertFromUTF16LE()
112 {
113     QTextCodec *codec = QTextCodec::codecForName("UTF-16LE");
114     setPlainText(codec->toUnicode(m_source));
115     emit statusChanged("UTF-16LE");
116 }
117
118 // http://dobon.net/vb/dotnet/string/detectcode.html より拝借
119 std::string SimpleTextView::detectCode(const QByteArray &bytes)
120 {
121     typedef unsigned char byte;
122     const byte bEscape = 0x1B;
123     const byte bAt = 0x40;
124     const byte bDollar = 0x24;
125     const byte bAnd = 0x26;
126     const byte bOpen = 0x28;    //'('
127     const byte bB = 0x42;
128     const byte bD = 0x44;
129     const byte bJ = 0x4A;
130     const byte bI = 0x49;
131
132     int len = bytes.size();
133     byte b1, b2, b3, b4;
134
135     bool isBinary = false;
136     for (int i = 0; i < len; i++) {
137         b1 = bytes[i];
138         if (b1 <= 0x06 || b1 == 0x7F || b1 == 0xFF) {
139             //'binary'
140             isBinary = true;
141             if (b1 == 0x00 && i < len - 1 && static_cast<byte>(bytes[i + 1]) <= 0x7F) {
142                 return "UTF-16LE";
143             }
144         }
145     }
146     if (isBinary) {
147         return "UTF-8";
148     }
149
150     bool notJapanese = true;
151     for (int i = 0; i < len; i++) {
152         b1 = bytes[i];
153         if (b1 == bEscape || 0x80 <= b1) {
154             notJapanese = false;
155             break;
156         }
157     }
158     if (notJapanese) {
159         return "UTF-8";
160     }
161
162     for (int i = 0; i < len - 2; i++) {
163         b1 = bytes[i];
164         b2 = bytes[i + 1];
165         b3 = bytes[i + 2];
166
167         if (b1 == bEscape){
168             if ((b2 == bDollar && b3 == bAt) ||
169                 (b2 == bDollar && b3 == bB) ||
170                 (b2 == bOpen && (b3 == bB || b3 == bJ)) ||
171                 (b2 == bOpen && b3 == bI))
172             {
173                 return "ISO 2022-JP";
174             }
175             if (i < len - 3) {
176                 b4 = bytes[i + 3];
177                 if (b2 == bDollar && b3 == bOpen && b4 == bD) {
178                     return "ISO 2022-JP";
179                 }
180                 if (i < len - 5 &&
181                     b2 == bAnd && b3 == bAt && b4 == bEscape &&
182                     bytes[i + 4] == bDollar && bytes[i + 5] == bB)
183                 {
184                     return "ISO 2022-JP";
185                 }
186             }
187         }
188     }
189
190     int sjis = 0;
191     int euc = 0;
192     int utf8 = 0;
193     for (int i = 0; i < len - 1; i++) {
194         b1 = bytes[i];
195         b2 = bytes[i + 1];
196         if (((0x81 <= b1 && b1 <= 0x9F) || (0xE0 <= b1 && b1 <= 0xFC)) &&
197             ((0x40 <= b2 && b2 <= 0x7E) || (0x80 <= b2 && b2 <= 0xFC)))
198         {
199             sjis += 2;
200             i++;
201         }
202     }
203     for (int i = 0; i < len - 1; i++) {
204         b1 = bytes[i];
205         b2 = bytes[i + 1];
206         if (((0xA1 <= b1 && b1 <= 0xFE) && (0xA1 <= b2 && b2 <= 0xFE)) ||
207             (b1 == 0x8E && (0xA1 <= b2 && b2 <= 0xDF)))
208         {
209             euc += 2;
210             i++;
211         }
212         else if (i < len - 2) {
213             b3 = bytes[i + 2];
214             if (b1 == 0x8F && (0xA1 <= b2 && b2 <= 0xFE) &&
215                 (0xA1 <= b3 && b3 <= 0xFE))
216             {
217                 euc += 3;
218                 i += 2;
219             }
220         }
221     }
222     for (int i = 0; i < len - 1; i++) {
223         b1 = bytes[i];
224         b2 = bytes[i + 1];
225         if ((0xC0 <= b1 && b1 <= 0xDF) && (0x80 <= b2 && b2 <= 0xBF)) {
226             utf8 += 2;
227             i++;
228         }
229         else if (i < len - 2) {
230             b3 = bytes[i + 2];
231             if ((0xE0 <= b1 && b1 <= 0xEF) && (0x80 <= b2 && b2 <= 0xBF) &&
232                 (0x80 <= b3 && b3 <= 0xBF))
233             {
234                 utf8 += 3;
235                 i += 2;
236             }
237         }
238     }
239
240     if (euc > sjis && euc > utf8) {
241         return "EUC-JP";
242     }
243     else if (sjis > euc && sjis > utf8) {
244         return "Shift-JIS";
245     }
246     else if (utf8 > euc && utf8 > sjis) {
247         return "UTF-8";
248     }
249
250 #ifdef Q_OS_WIN
251     return "Shift-JIS";
252 #else
253     return "UTF-8";
254 #endif
255 }
256
257
258 void SimpleTextView::scaleUp()
259 {
260     qDebug() << "SimpleTextView::scaleUp()";
261
262     Preferences prefs(this);
263     QFont font = prefs.getTextViewFont();
264     font.setPointSize(font.pointSize() + 1);
265     prefs.setTextViewFont(font);
266 }
267
268 void SimpleTextView::scaleDown()
269 {
270     qDebug() << "SimpleTextView::scaleDown()";
271
272     Preferences prefs(this);
273     QFont font = prefs.getTextViewFont();
274     font.setPointSize(font.pointSize() - 1);
275     prefs.setTextViewFont(font);
276 }