mainwindow.cpp 10.3 KB
Newer Older
1 2 3
/*
 * ark -- archiver for the KDE project
 *
4
 * Copyright (C) 2002-2003: Georg Robbers <Georg.Robbers@urz.uni-hd.de>
5 6 7
 * Copyright (C) 2003: Helio Chissini de Castro <helio@conectiva.com>
 * Copyright (C) 2007 Henrique Pinto <henrique.pinto@kdemail.net>
 * Copyright (C) 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */
24

Henrique Pinto's avatar
Henrique Pinto committed
25
#include "mainwindow.h"
26
#include "logging.h"
27
#include "kerfuffle/archive_kerfuffle.h"
28
#include "kerfuffle/createdialog.h"
29
#include "kerfuffle/settingspage.h"
30
#include "part/interface.h"
Henrique Pinto's avatar
Henrique Pinto committed
31

32
#include <KPluginFactory>
Henrique Pinto's avatar
Henrique Pinto committed
33
#include <KMessageBox>
34
#include <KLocalizedString>
Henrique Pinto's avatar
Henrique Pinto committed
35 36
#include <KActionCollection>
#include <KStandardAction>
37
#include <KRecentFilesAction>
38 39
#include <KEditToolBar>
#include <KShortcutsDialog>
Bhushan Shah's avatar
Bhushan Shah committed
40
#include <KService>
41
#include <KSharedConfig>
42
#include <KConfigDialog>
Bhushan Shah's avatar
Bhushan Shah committed
43
#include <KConfigGroup>
44
#include <KConfigSkeleton>
45
#include <KXMLGUIFactory>
Henrique Pinto's avatar
Henrique Pinto committed
46

47
#include <QDebug>
48 49
#include <QDragEnterEvent>
#include <QDragMoveEvent>
Lukáš Tinkl's avatar
Lukáš Tinkl committed
50 51
#include <QFileDialog>
#include <QMimeData>
52
#include <QPointer>
53
#include <QRegularExpression>
54

55 56
static bool isValidArchiveDrag(const QMimeData *data)
{
57
    return ((data->hasUrls()) && (data->urls().count() == 1));
58 59
}

60 61
MainWindow::MainWindow(QWidget *)
        : KParts::MainWindow()
Henrique Pinto's avatar
Henrique Pinto committed
62
{
63
    setXMLFile(QLatin1String( "arkui.rc" ));
Henrique Pinto's avatar
Henrique Pinto committed
64

65 66
    setupActions();
    statusBar();
Henrique Pinto's avatar
Henrique Pinto committed
67

68 69
    resize(640, 480);

70
    setAutoSaveSettings(QLatin1String( "MainWindow" ));
71

72
    setAcceptDrops(true);
Henrique Pinto's avatar
Henrique Pinto committed
73 74 75 76
}

MainWindow::~MainWindow()
{
77
    if (m_recentFilesAction) {
Laurent Montel's avatar
Laurent Montel committed
78
        m_recentFilesAction->saveEntries(KSharedConfig::openConfig()->group("Recent Files"));
79
    }
80 81

    guiFactory()->removeClient(m_part);
82 83
    delete m_part;
    m_part = 0;
Henrique Pinto's avatar
Henrique Pinto committed
84 85
}

86
void MainWindow::dragEnterEvent(QDragEnterEvent * event)
87
{
88
    qCDebug(ARK) << "dragEnterEvent" << event;
89

90
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
91 92 93
    if (iface->isBusy()) {
        return;
    }
94

Lukáš Tinkl's avatar
Lukáš Tinkl committed
95
    if (!event->source() && isValidArchiveDrag(event->mimeData())) {
96
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
97
    }
98
    return;
99 100
}

101
void MainWindow::dropEvent(QDropEvent * event)
102
{
103
    qCDebug(ARK) << "dropEvent" << event;
104

105
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
106 107 108
    if (iface->isBusy()) {
        return;
    }
109

Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
110 111
    if ((event->source() == NULL) &&
        (isValidArchiveDrag(event->mimeData()))) {
112
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
113
    }
114 115 116 117

    //TODO: if this call provokes a message box the drag will still be going
    //while the box is onscreen. looks buggy, do something about it
    openUrl(event->mimeData()->urls().at(0));
118 119
}

120
void MainWindow::dragMoveEvent(QDragMoveEvent * event)
121
{
122
    qCDebug(ARK) << "dragMoveEvent" << event;
123

124
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
125 126 127
    if (iface->isBusy()) {
        return;
    }
128

Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
129 130
    if ((event->source() == NULL) &&
        (isValidArchiveDrag(event->mimeData()))) {
131
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
132
    }
133 134
}

135 136
bool MainWindow::loadPart()
{
Bhushan Shah's avatar
Bhushan Shah committed
137 138 139 140 141
    KPluginFactory *factory = 0;
    KService::Ptr service = KService::serviceByDesktopName(QLatin1String("ark_part"));

    if (service) {
        factory = KPluginLoader(service->library()).factory();
142
    }
Bhushan Shah's avatar
Bhushan Shah committed
143 144 145 146

    m_part = factory ? static_cast<KParts::ReadWritePart*>(factory->create<KParts::ReadWritePart>(this)) : 0;

    if (!m_part) {
147
        KMessageBox::error(this, i18n("Unable to find Ark's KPart component, please check your installation."));
148
        qCWarning(ARK) << "Error loading Ark KPart.";
149 150
        return false;
    }
151

Laurent Montel's avatar
Laurent Montel committed
152
    m_part->setObjectName( QLatin1String("ArkPart" ));
153 154
    setCentralWidget(m_part->widget());
    createGUI(m_part);
155

156 157
    connect(m_part, SIGNAL(busy()), this, SLOT(updateActions()));
    connect(m_part, SIGNAL(ready()), this, SLOT(updateActions()));
158
    connect(m_part, SIGNAL(quit()), this, SLOT(quit()));
159

160
    return true;
161 162
}

Henrique Pinto's avatar
Henrique Pinto committed
163 164
void MainWindow::setupActions()
{
165 166 167
    m_newAction = KStandardAction::openNew(this, SLOT(newArchive()), actionCollection());
    m_openAction = KStandardAction::open(this, SLOT(openArchive()), actionCollection());
    KStandardAction::quit(this, SLOT(quit()), actionCollection());
168

Lukáš Tinkl's avatar
Lukáš Tinkl committed
169
    m_recentFilesAction = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), actionCollection());
170 171 172 173 174
    m_recentFilesAction->setToolBarMode(KRecentFilesAction::MenuMode);
    m_recentFilesAction->setToolButtonPopupMode(QToolButton::DelayedPopup);
    m_recentFilesAction->setIconText(i18nc("action, to open an archive", "Open"));
    m_recentFilesAction->setStatusTip(i18n("Click to open an archive, click and hold to open a recently-opened archive"));
    m_recentFilesAction->setToolTip(i18n("Open an archive"));
Laurent Montel's avatar
Laurent Montel committed
175
    m_recentFilesAction->loadEntries(KSharedConfig::openConfig()->group("Recent Files"));
176 177
    connect(m_recentFilesAction, SIGNAL(triggered()),
            this, SLOT(openArchive()));
178

179
    createStandardStatusBarAction();
180

181 182
    KStandardAction::configureToolbars(this, SLOT(editToolbars()), actionCollection());
    KStandardAction::keyBindings(this, SLOT(editKeyBindings()), actionCollection());
183
    KStandardAction::preferences(this, SLOT(showSettings()), actionCollection());
184 185
}

186 187
void MainWindow::updateActions()
{
188 189 190 191
    Interface *iface = qobject_cast<Interface*>(m_part);
    m_newAction->setEnabled(!iface->isBusy());
    m_openAction->setEnabled(!iface->isBusy());
    m_recentFilesAction->setEnabled(!iface->isBusy());
192 193
}

194 195
void MainWindow::editKeyBindings()
{
196 197 198
    KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this);
    dlg.addCollection(actionCollection());
    dlg.addCollection(m_part->actionCollection());
199

200
    dlg.configure();
201 202 203 204
}

void MainWindow::editToolbars()
{
Bhushan Shah's avatar
Bhushan Shah committed
205 206
    KConfigGroup cfg(KSharedConfig::openConfig(), "MainWindow");
    saveMainWindowSettings(cfg);
207

208
    QPointer<KEditToolBar> dlg = new KEditToolBar(factory(), this);
209
    dlg.data()->exec();
210

211
    createGUI(m_part);
212

Bhushan Shah's avatar
Bhushan Shah committed
213
    applyMainWindowSettings(KSharedConfig::openConfig()->group(QLatin1String("MainWindow")));
214

215
    delete dlg.data();
Henrique Pinto's avatar
Henrique Pinto committed
216 217 218 219
}

void MainWindow::openArchive()
{
220 221
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);
222
    Q_UNUSED(iface);
Lukáš Tinkl's avatar
Lukáš Tinkl committed
223

224 225
    QPointer<QFileDialog> dlg = new QFileDialog(this, i18nc("to open an archive", "Open Archive"));
    dlg->setMimeTypeFilters(Kerfuffle::supportedMimeTypes());
226

227
    QStringList filters = dlg->nameFilters();
228 229 230 231
    filters.removeDuplicates();
    filters.sort(Qt::CaseInsensitive);

    // Create the "All supported archives" filter
232
    QRegularExpression rx(QStringLiteral("(\\*\\.[a-z]+\\.*[a-z0-9]*)+"));
233
    QString allArchives(i18n("All supported archives ("));
234
    foreach(const QString &s, filters)
235 236 237 238
    {
        QRegularExpressionMatchIterator i = rx.globalMatch(s);
        while (i.hasNext()) {
            QRegularExpressionMatch match = i.next();
239
            allArchives.append(match.captured(1) + QLatin1Char(' '));
240 241
        }
    }
242
    filters.prepend(allArchives + QLatin1Char(')'));
243
    dlg->setNameFilters(filters);
244

245 246 247 248
    dlg->setFileMode(QFileDialog::ExistingFile);
    dlg->setAcceptMode(QFileDialog::AcceptOpen);
    if (dlg->exec() == QDialog::Accepted) {
        openUrl(dlg->selectedUrls().first());
Lukáš Tinkl's avatar
Lukáš Tinkl committed
249
    }
250
    delete dlg;
251
}
Henrique Pinto's avatar
Henrique Pinto committed
252

Lukáš Tinkl's avatar
Lukáš Tinkl committed
253
void MainWindow::openUrl(const QUrl& url)
254
{
255 256
    if (!url.isEmpty()) {
        m_part->setArguments(m_openArgs);
257

258 259 260 261 262 263
        if (m_part->openUrl(url)) {
            m_recentFilesAction->addUrl(url);
        } else {
            m_recentFilesAction->removeUrl(url);
        }
    }
Henrique Pinto's avatar
Henrique Pinto committed
264 265
}

266 267
void MainWindow::setShowExtractDialog(bool option)
{
268
    if (option) {
269
        m_openArgs.metaData()[QLatin1String( "showExtractDialog" )] = QLatin1String( "true" );
270
    } else {
271
        m_openArgs.metaData().remove(QLatin1String( "showExtractDialog" ));
272
    }
273 274
}

Henrique Pinto's avatar
Henrique Pinto committed
275 276
void MainWindow::quit()
{
277
    close();
278 279
}

280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
void MainWindow::showSettings()
{
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);

    KConfigDialog *dialog = new KConfigDialog(this, QLatin1String("settings"), iface->config());

    foreach (Kerfuffle::SettingsPage *page, iface->settingsPages(this)) {
        dialog->addPage(page, page->name(), page->iconName());
    }
    // Hide the icons list if only one page has been added.
    dialog->setFaceType(KPageDialog::Auto);

    connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(writeSettings()));
    dialog->show();
}

void MainWindow::writeSettings()
{
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);
    iface->config()->save();
}

304 305
void MainWindow::newArchive()
{
306 307
    qCDebug(ARK) << "Creating new archive";

308 309
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);
310
    Q_UNUSED(iface);
Raphael Kubo da Costa's avatar
const++  
Raphael Kubo da Costa committed
311

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
    QPointer<Kerfuffle::CreateDialog> dialog = new Kerfuffle::CreateDialog(
        Q_NULLPTR, // parent
        i18n("Create a new Archive"), // caption
        QUrl()); // startDir

    dialog.data()->show();
    dialog.data()->restoreWindowSize();

    if (dialog.data()->exec()) {
        const QUrl saveFileUrl = dialog.data()->selectedUrls().first();
        const QString password = dialog.data()->password();

        qCDebug(ARK) << "CreateDialog returned URL:" << saveFileUrl.toString();
        qCDebug(ARK) << "CreateDialog returned mime:" << dialog.data()->currentMimeFilter();

Lukáš Tinkl's avatar
Lukáš Tinkl committed
327
        m_openArgs.metaData()[QLatin1String( "createNewArchive" )] = QLatin1String( "true" );
328 329 330 331 332 333 334 335 336 337 338 339
        m_openArgs.metaData()[QLatin1String("encryptionPassword")] = password;

        if (dialog.data()->isHeaderEncryptionChecked()) {
            m_openArgs.metaData()[QLatin1String("encryptHeader")] = QLatin1String("true");
        }

        openUrl(saveFileUrl);

        m_openArgs.metaData().remove(QLatin1String("showExtractDialog"));
        m_openArgs.metaData().remove(QLatin1String("createNewArchive"));
        m_openArgs.metaData().remove(QLatin1String("encryptionPassword"));
        m_openArgs.metaData().remove(QLatin1String("encryptHeader"));
Lukáš Tinkl's avatar
Lukáš Tinkl committed
340
    }
341 342

    delete dialog.data();
Henrique Pinto's avatar
Henrique Pinto committed
343
}