1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "mainwindow.h"
52#include "encodingdialog.h"
53#include "previewform.h"
54
55#include <QAction>
56#include <QApplication>
57#include <QFileDialog>
58#include <QMenuBar>
59#include <QMessageBox>
60#include <QPlainTextEdit>
61#include <QRegularExpression>
62#include <QScreen>
63#include <QTextCodec>
64#include <QTextStream>
65
66MainWindow::MainWindow()
67{
68 textEdit = new QPlainTextEdit;
69 textEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
70 setCentralWidget(textEdit);
71
72 findCodecs();
73
74 previewForm = new PreviewForm(this);
75 previewForm->setCodecList(codecs);
76
77 createMenus();
78
79 setWindowTitle(tr(s: "Codecs"));
80
81 const QRect screenGeometry = screen()->geometry();
82 resize(w: screenGeometry.width() / 2, h: screenGeometry.height() * 2 / 3);
83}
84
85void MainWindow::open()
86{
87 const QString fileName = QFileDialog::getOpenFileName(parent: this);
88 if (fileName.isEmpty())
89 return;
90 QFile file(fileName);
91 if (!file.open(flags: QFile::ReadOnly)) {
92 QMessageBox::warning(parent: this, title: tr(s: "Codecs"),
93 text: tr(s: "Cannot read file %1:\n%2")
94 .arg(args: QDir::toNativeSeparators(pathName: fileName),
95 args: file.errorString()));
96 return;
97 }
98
99 const QByteArray data = file.readAll();
100
101 previewForm->setWindowTitle(tr(s: "Choose Encoding for %1").arg(a: QFileInfo(fileName).fileName()));
102 previewForm->setEncodedData(data);
103 if (previewForm->exec())
104 textEdit->setPlainText(previewForm->decodedString());
105}
106
107void MainWindow::save()
108{
109 const QAction *action = qobject_cast<const QAction *>(object: sender());
110 const QByteArray codecName = action->data().toByteArray();
111 const QString title = tr(s: "Save As (%1)").arg(a: QLatin1String(codecName));
112
113 QString fileName = QFileDialog::getSaveFileName(parent: this, caption: title);
114 if (fileName.isEmpty())
115 return;
116 QFile file(fileName);
117 if (!file.open(flags: QFile::WriteOnly | QFile::Text)) {
118 QMessageBox::warning(parent: this, title: tr(s: "Codecs"),
119 text: tr(s: "Cannot write file %1:\n%2")
120 .arg(args: QDir::toNativeSeparators(pathName: fileName),
121 args: file.errorString()));
122 return;
123 }
124
125 QTextStream out(&file);
126 out.setCodec(codecName.constData());
127 out << textEdit->toPlainText();
128}
129
130void MainWindow::about()
131{
132 QMessageBox::about(parent: this, title: tr(s: "About Codecs"),
133 text: tr(s: "The <b>Codecs</b> example demonstrates how to read and write "
134 "files using various encodings."));
135}
136
137void MainWindow::aboutToShowSaveAsMenu()
138{
139 const QString currentText = textEdit->toPlainText();
140 for (QAction *action : qAsConst(t&: saveAsActs)) {
141 const QByteArray codecName = action->data().toByteArray();
142 const QTextCodec *codec = QTextCodec::codecForName(name: codecName);
143 action->setVisible(codec && codec->canEncode(currentText));
144 }
145}
146
147void MainWindow::findCodecs()
148{
149 QMap<QString, QTextCodec *> codecMap;
150 QRegularExpression iso8859RegExp("^ISO[- ]8859-([0-9]+).*$");
151 QRegularExpressionMatch match;
152
153 const QList<int> mibs = QTextCodec::availableMibs();
154 for (int mib : mibs) {
155 QTextCodec *codec = QTextCodec::codecForMib(mib);
156
157 QString sortKey = codec->name().toUpper();
158 char rank;
159
160 if (sortKey.startsWith(s: QLatin1String("UTF-8"))) {
161 rank = 1;
162 } else if (sortKey.startsWith(s: QLatin1String("UTF-16"))) {
163 rank = 2;
164 } else if ((match = iso8859RegExp.match(subject: sortKey)).hasMatch()) {
165 if (match.capturedRef(nth: 1).size() == 1)
166 rank = 3;
167 else
168 rank = 4;
169 } else {
170 rank = 5;
171 }
172 sortKey.prepend(c: QLatin1Char('0' + rank));
173
174 codecMap.insert(akey: sortKey, avalue: codec);
175 }
176 for (const auto &codec : qAsConst(t&: codecMap))
177 codecs += codec;
178}
179
180void MainWindow::createMenus()
181{
182 QMenu *fileMenu = menuBar()->addMenu(title: tr(s: "&File"));
183 QAction *openAct =
184 fileMenu->addAction(text: tr(s: "&Open..."), object: this, slot: &MainWindow::open);
185 openAct->setShortcuts(QKeySequence::Open);
186
187 QMenu *saveAsMenu = fileMenu->addMenu(title: tr(s: "&Save As"));
188 connect(sender: saveAsMenu, signal: &QMenu::aboutToShow,
189 receiver: this, slot: &MainWindow::aboutToShowSaveAsMenu);
190 for (const QTextCodec *codec : qAsConst(t&: codecs)) {
191 const QByteArray name = codec->name();
192 QAction *action = saveAsMenu->addAction(text: tr(s: "%1...").arg(a: QLatin1String(name)));
193 action->setData(QVariant(name));
194 connect(sender: action, signal: &QAction::triggered, receiver: this, slot: &MainWindow::save);
195 saveAsActs.append(t: action);
196 }
197
198 fileMenu->addSeparator();
199 QAction *exitAct = fileMenu->addAction(text: tr(s: "E&xit"), object: this, slot: &QWidget::close);
200 exitAct->setShortcuts(QKeySequence::Quit);
201
202 auto toolMenu = menuBar()->addMenu(title: tr(s: "&Tools"));
203 auto encodingAction = toolMenu->addAction(text: tr(s: "Encodings"), object: this, slot: &MainWindow::encodingDialog);
204 encodingAction->setShortcut(Qt::CTRL + Qt::Key_E);
205 encodingAction->setToolTip(tr(s: "Shows a dialog allowing to convert to common encoding in programming languages."));
206
207
208 menuBar()->addSeparator();
209
210 QMenu *helpMenu = menuBar()->addMenu(title: tr(s: "&Help"));
211 helpMenu->addAction(text: tr(s: "&About"), object: this, slot: &MainWindow::about);
212 helpMenu->addAction(text: tr(s: "About &Qt"), qApp, slot: &QApplication::aboutQt);
213}
214
215void MainWindow::encodingDialog()
216{
217 if (!m_encodingDialog) {
218 m_encodingDialog = new EncodingDialog(this);
219 const QRect screenGeometry = screen()->geometry();
220 m_encodingDialog->setMinimumWidth(screenGeometry.width() / 4);
221 }
222 m_encodingDialog->show();
223 m_encodingDialog->raise();
224
225}
226

source code of qtbase/examples/widgets/tools/codecs/mainwindow.cpp