keepassxc

Форк
0
/
IconDownloaderDialog.cpp 
217 строк · 6.7 Кб
1
/*
2
 *  Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
3
 *
4
 *  This program is free software: you can redistribute it and/or modify
5
 *  it under the terms of the GNU General Public License as published by
6
 *  the Free Software Foundation, either version 2 or (at your option)
7
 *  version 3 of the License.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17

18
#include "IconDownloaderDialog.h"
19
#include "ui_IconDownloaderDialog.h"
20

21
#include "core/Config.h"
22
#include "core/Database.h"
23
#include "core/Entry.h"
24
#include "core/Metadata.h"
25
#include "core/Tools.h"
26
#include "gui/IconDownloader.h"
27
#include "gui/IconModels.h"
28
#include "gui/Icons.h"
29
#include "osutils/OSUtils.h"
30
#ifdef Q_OS_MACOS
31
#include "gui/osutils/macutils/MacUtils.h"
32
#endif
33

34
#include <QStandardItemModel>
35

36
IconDownloaderDialog::IconDownloaderDialog(QWidget* parent)
37
    : QDialog(parent)
38
    , m_ui(new Ui::IconDownloaderDialog())
39
    , m_dataModel(new QStandardItemModel(this))
40
{
41
    setWindowFlags(Qt::Window);
42
    setAttribute(Qt::WA_DeleteOnClose);
43

44
    m_ui->setupUi(this);
45
    showFallbackMessage(false);
46

47
    m_dataModel->clear();
48
    m_dataModel->setHorizontalHeaderLabels({tr("URL"), tr("Status")});
49

50
    m_ui->tableView->setModel(m_dataModel);
51
    m_ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
52

53
    connect(m_ui->cancelButton, SIGNAL(clicked()), SLOT(abortDownloads()));
54
    connect(m_ui->closeButton, SIGNAL(clicked()), SLOT(close()));
55
}
56

57
IconDownloaderDialog::~IconDownloaderDialog()
58
{
59
    abortDownloads();
60
}
61

62
void IconDownloaderDialog::downloadFavicons(const QSharedPointer<Database>& database,
63
                                            const QList<Entry*>& entries,
64
                                            bool force)
65
{
66
    m_db = database;
67
    m_urlToEntries.clear();
68
    abortDownloads();
69
    for (const auto& e : entries) {
70
        // Only consider entries with a valid URL and without a custom icon
71
        auto webUrl = e->webUrl();
72
        if (!webUrl.isEmpty() && (force || e->iconUuid().isNull())) {
73
            m_urlToEntries.insert(webUrl, e);
74
        }
75
    }
76

77
    if (m_urlToEntries.count() > 0) {
78
#ifdef Q_OS_MACOS
79
        macUtils()->raiseOwnWindow();
80
        Tools::wait(100);
81
#endif
82
        showFallbackMessage(false);
83
        m_ui->progressLabel->setText(tr("Please wait, processing entry list…"));
84
        open();
85
        QApplication::processEvents();
86

87
        for (const auto& url : m_urlToEntries.uniqueKeys()) {
88
            m_dataModel->appendRow(QList<QStandardItem*>()
89
                                   << new QStandardItem(url) << new QStandardItem(tr("Downloading…")));
90
            m_activeDownloaders.append(createDownloader(url));
91
        }
92

93
        // Setup the dialog
94
        updateProgressBar();
95
        updateCancelButton();
96
        QApplication::processEvents();
97

98
        // Start the downloads
99
        for (auto downloader : m_activeDownloaders) {
100
            downloader->download();
101
        }
102
    }
103
}
104

105
void IconDownloaderDialog::downloadFaviconInBackground(const QSharedPointer<Database>& database, Entry* entry)
106
{
107
    m_db = database;
108
    m_urlToEntries.clear();
109
    abortDownloads();
110

111
    auto webUrl = entry->webUrl();
112
    if (!webUrl.isEmpty()) {
113
        m_urlToEntries.insert(webUrl, entry);
114
    }
115

116
    if (m_urlToEntries.count() > 0) {
117
        m_activeDownloaders.append(createDownloader(webUrl));
118
        m_activeDownloaders.first()->download();
119
    }
120
}
121

122
IconDownloader* IconDownloaderDialog::createDownloader(const QString& url)
123
{
124
    auto downloader = new IconDownloader();
125
    connect(downloader,
126
            SIGNAL(finished(const QString&, const QImage&)),
127
            this,
128
            SLOT(downloadFinished(const QString&, const QImage&)));
129

130
    downloader->setUrl(url);
131
    return downloader;
132
}
133

134
void IconDownloaderDialog::downloadFinished(const QString& url, const QImage& icon)
135
{
136
    // Prevent re-entrance from multiple calls finishing at the same time
137
    QMutexLocker locker(&m_mutex);
138

139
    // Cleanup the icon downloader that sent this signal
140
    auto downloader = qobject_cast<IconDownloader*>(sender());
141
    if (downloader) {
142
        downloader->deleteLater();
143
        m_activeDownloaders.removeAll(downloader);
144
    }
145

146
    updateProgressBar();
147
    updateCancelButton();
148

149
    if (m_db && !icon.isNull()) {
150
        // Don't add an icon larger than 128x128, but retain original size if smaller
151
        constexpr auto maxIconSize = 128;
152
        auto scaledIcon = icon;
153
        if (icon.width() > maxIconSize || icon.height() > maxIconSize) {
154
            scaledIcon = icon.scaled(maxIconSize, maxIconSize);
155
        }
156

157
        QByteArray serializedIcon = Icons::saveToBytes(scaledIcon);
158
        QUuid uuid = m_db->metadata()->findCustomIcon(serializedIcon);
159
        if (uuid.isNull()) {
160
            uuid = QUuid::createUuid();
161
            m_db->metadata()->addCustomIcon(uuid, serializedIcon);
162
            updateTable(url, tr("Ok"));
163
        } else {
164
            updateTable(url, tr("Already Exists"));
165
        }
166

167
        // Set the icon on all the entries associated with this url
168
        for (const auto entry : m_urlToEntries.values(url)) {
169
            entry->setIcon(uuid);
170
        }
171
    } else {
172
        showFallbackMessage(true);
173
        updateTable(url, tr("Download Failed"));
174
        return;
175
    }
176
}
177

178
void IconDownloaderDialog::showFallbackMessage(bool state)
179
{
180
    // Show fallback message if the option is not active
181
    bool show = state && !config()->get(Config::Security_IconDownloadFallback).toBool();
182
    m_ui->fallbackLabel->setVisible(show);
183
}
184

185
void IconDownloaderDialog::updateProgressBar()
186
{
187
    int total = m_urlToEntries.uniqueKeys().count();
188
    int value = total - m_activeDownloaders.count();
189
    m_ui->progressBar->setValue(value);
190
    m_ui->progressBar->setMaximum(total);
191
    m_ui->progressLabel->setText(
192
        tr("Downloading favicons (%1/%2)…").arg(QString::number(value), QString::number(total)));
193
}
194

195
void IconDownloaderDialog::updateCancelButton()
196
{
197
    m_ui->cancelButton->setEnabled(!m_activeDownloaders.isEmpty());
198
}
199

200
void IconDownloaderDialog::updateTable(const QString& url, const QString& message)
201
{
202
    for (int i = 0; i < m_dataModel->rowCount(); ++i) {
203
        if (m_dataModel->item(i, 0)->text() == url) {
204
            m_dataModel->item(i, 1)->setText(message);
205
        }
206
    }
207
}
208

209
void IconDownloaderDialog::abortDownloads()
210
{
211
    for (auto* downloader : m_activeDownloaders) {
212
        downloader->deleteLater();
213
    }
214
    m_activeDownloaders.clear();
215
    updateProgressBar();
216
    updateCancelButton();
217
}
218

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.