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 Qt Linguist of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "batchtranslationdialog.h"
30 #include "phrase.h"
31 #include "messagemodel.h"
32 
33 #include <QtWidgets/QMessageBox>
34 #include <QtWidgets/QProgressDialog>
35 
36 QT_BEGIN_NAMESPACE
37 
CheckableListModel(QObject * parent)38 CheckableListModel::CheckableListModel(QObject *parent)
39   : QStandardItemModel(parent)
40 {
41 }
42 
flags(const QModelIndex & index) const43 Qt::ItemFlags CheckableListModel::flags(const QModelIndex &index) const
44 {
45     Q_UNUSED(index);
46     return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
47 }
48 
BatchTranslationDialog(MultiDataModel * dataModel,QWidget * w)49 BatchTranslationDialog::BatchTranslationDialog(MultiDataModel *dataModel, QWidget *w)
50  : QDialog(w), m_model(this), m_dataModel(dataModel)
51 {
52     m_ui.setupUi(this);
53     connect(m_ui.runButton, SIGNAL(clicked()), this, SLOT(startTranslation()));
54     connect(m_ui.moveUpButton, SIGNAL(clicked()), this, SLOT(movePhraseBookUp()));
55     connect(m_ui.moveDownButton, SIGNAL(clicked()), this, SLOT(movePhraseBookDown()));
56 
57     m_ui.phrasebookList->setModel(&m_model);
58     m_ui.phrasebookList->setSelectionBehavior(QAbstractItemView::SelectItems);
59     m_ui.phrasebookList->setSelectionMode(QAbstractItemView::SingleSelection);
60 }
61 
62 
setPhraseBooks(const QList<PhraseBook * > & phrasebooks,int modelIndex)63 void BatchTranslationDialog::setPhraseBooks(const QList<PhraseBook *> &phrasebooks, int modelIndex)
64 {
65     QString fn = QFileInfo(m_dataModel->srcFileName(modelIndex)).baseName();
66     setWindowTitle(tr("Batch Translation of '%1' - Qt Linguist").arg(fn));
67     m_model.clear();
68     m_model.insertColumn(0);
69     m_phrasebooks = phrasebooks;
70     m_modelIndex = modelIndex;
71     int count = phrasebooks.count();
72     m_model.insertRows(0, count);
73     for (int i = 0; i < count; ++i) {
74         QModelIndex idx(m_model.index(i, 0));
75         m_model.setData(idx, phrasebooks[i]->friendlyPhraseBookName());
76         int sortOrder;
77         if (phrasebooks[i]->language() != QLocale::C
78             && m_dataModel->language(m_modelIndex) != QLocale::C) {
79             if (phrasebooks[i]->language() != m_dataModel->language(m_modelIndex))
80                 sortOrder = 3;
81             else
82                 sortOrder = (phrasebooks[i]->country()
83                              == m_dataModel->model(m_modelIndex)->country()) ? 0 : 1;
84         } else {
85             sortOrder = 2;
86         }
87         m_model.setData(idx, sortOrder == 3 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
88         m_model.setData(idx, sortOrder, Qt::UserRole + 1);
89         m_model.setData(idx, i, Qt::UserRole);
90     }
91     m_model.setSortRole(Qt::UserRole + 1);
92     m_model.sort(0);
93 }
94 
startTranslation()95 void BatchTranslationDialog::startTranslation()
96 {
97     int translatedcount = 0;
98     QCursor oldCursor = cursor();
99     setCursor(Qt::BusyCursor);
100     int messageCount = m_dataModel->messageCount();
101 
102     QProgressDialog *dlgProgress;
103     dlgProgress = new QProgressDialog(tr("Searching, please wait..."), tr("&Cancel"), 0, messageCount, this);
104     dlgProgress->show();
105 
106     int msgidx = 0;
107     const bool translateTranslated = m_ui.ckTranslateTranslated->isChecked();
108     const bool translateFinished = m_ui.ckTranslateFinished->isChecked();
109     for (MultiDataModelIterator it(m_dataModel, m_modelIndex); it.isValid(); ++it) {
110         if (MessageItem *m = it.current()) {
111             if (!m->isObsolete()
112                 && (translateTranslated || m->translation().isEmpty())
113                 && (translateFinished || !m->isFinished())) {
114 
115                 // Go through them in the order the user specified in the phrasebookList
116                 for (int b = 0; b < m_model.rowCount(); ++b) {
117                     QModelIndex idx(m_model.index(b, 0));
118                     QVariant checkState = m_model.data(idx, Qt::CheckStateRole);
119                     if (checkState == Qt::Checked) {
120                         PhraseBook *pb = m_phrasebooks[m_model.data(idx, Qt::UserRole).toInt()];
121                         foreach (const Phrase *ph, pb->phrases()) {
122                             if (ph->source() == m->text()) {
123                                 m_dataModel->setTranslation(it, ph->target());
124                                 m_dataModel->setFinished(it, m_ui.ckMarkFinished->isChecked());
125                                 ++translatedcount;
126                                 goto done; // break 2;
127                             }
128                         }
129                     }
130                 }
131             }
132         }
133       done:
134         ++msgidx;
135         if (!(msgidx & 15))
136             dlgProgress->setValue(msgidx);
137         qApp->processEvents();
138         if (dlgProgress->wasCanceled())
139             break;
140     }
141     dlgProgress->hide();
142 
143     setCursor(oldCursor);
144     emit finished();
145     QMessageBox::information(this, tr("Linguist batch translator"),
146         tr("Batch translated %n entries", "", translatedcount), QMessageBox::Ok);
147 }
148 
movePhraseBookUp()149 void BatchTranslationDialog::movePhraseBookUp()
150 {
151     QModelIndexList indexes = m_ui.phrasebookList->selectionModel()->selectedIndexes();
152     if (indexes.count() <= 0) return;
153 
154     QModelIndex sel = indexes[0];
155     int row = sel.row();
156     if (row > 0) {
157         QModelIndex other = m_model.index(row - 1, 0);
158         QMap<int, QVariant> seldata = m_model.itemData(sel);
159         m_model.setItemData(sel, m_model.itemData(other));
160         m_model.setItemData(other, seldata);
161         m_ui.phrasebookList->selectionModel()->setCurrentIndex(other, QItemSelectionModel::ClearAndSelect);
162     }
163 }
164 
movePhraseBookDown()165 void BatchTranslationDialog::movePhraseBookDown()
166 {
167     QModelIndexList indexes = m_ui.phrasebookList->selectionModel()->selectedIndexes();
168     if (indexes.count() <= 0) return;
169 
170     QModelIndex sel = indexes[0];
171     int row = sel.row();
172     if (row < m_model.rowCount() - 1) {
173         QModelIndex other = m_model.index(row + 1, 0);
174         QMap<int, QVariant> seldata = m_model.itemData(sel);
175         m_model.setItemData(sel, m_model.itemData(other));
176         m_model.setItemData(other, seldata);
177         m_ui.phrasebookList->selectionModel()->setCurrentIndex(other, QItemSelectionModel::ClearAndSelect);
178     }
179 }
180 
181 QT_END_NAMESPACE
182