mainwindow.cpp 8.84 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
#include "logging.h"
Henrique Pinto's avatar
Henrique Pinto committed
25
#include "mainwindow.h"
26
#include "kerfuffle/archive_kerfuffle.h"
27
#include "part/interface.h"
Henrique Pinto's avatar
Henrique Pinto committed
28

29
#include <KPluginFactory>
Henrique Pinto's avatar
Henrique Pinto committed
30
#include <KMessageBox>
31
#include <KLocalizedString>
Henrique Pinto's avatar
Henrique Pinto committed
32 33
#include <KActionCollection>
#include <KStandardAction>
34
#include <KRecentFilesAction>
35 36
#include <KEditToolBar>
#include <KShortcutsDialog>
Bhushan Shah's avatar
Bhushan Shah committed
37
#include <KService>
38
#include <KSharedConfig>
Bhushan Shah's avatar
Bhushan Shah committed
39
#include <KConfigGroup>
40
#include <KXMLGUIFactory>
Henrique Pinto's avatar
Henrique Pinto committed
41

42
#include <QDebug>
43 44
#include <QDragEnterEvent>
#include <QDragMoveEvent>
Lukáš Tinkl's avatar
Lukáš Tinkl committed
45 46
#include <QFileDialog>
#include <QMimeData>
47
#include <QPointer>
48
#include <QRegularExpression>
49

50 51
static bool isValidArchiveDrag(const QMimeData *data)
{
52
    return ((data->hasUrls()) && (data->urls().count() == 1));
53 54
}

55 56
MainWindow::MainWindow(QWidget *)
        : KParts::MainWindow()
Henrique Pinto's avatar
Henrique Pinto committed
57
{
58
    setXMLFile(QLatin1String( "arkui.rc" ));
Henrique Pinto's avatar
Henrique Pinto committed
59

60 61
    setupActions();
    statusBar();
Henrique Pinto's avatar
Henrique Pinto committed
62

63 64
    resize(640, 480);

65
    setAutoSaveSettings(QLatin1String( "MainWindow" ));
66

67
    setAcceptDrops(true);
Henrique Pinto's avatar
Henrique Pinto committed
68 69 70 71
}

MainWindow::~MainWindow()
{
72
    if (m_recentFilesAction) {
Laurent Montel's avatar
Laurent Montel committed
73
        m_recentFilesAction->saveEntries(KSharedConfig::openConfig()->group("Recent Files"));
74
    }
75 76

    guiFactory()->removeClient(m_part);
77 78
    delete m_part;
    m_part = 0;
Henrique Pinto's avatar
Henrique Pinto committed
79 80
}

81
void MainWindow::dragEnterEvent(QDragEnterEvent * event)
82
{
83
    qCDebug(ARK) << "dragEnterEvent" << event;
84

85
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
86 87 88
    if (iface->isBusy()) {
        return;
    }
89

Lukáš Tinkl's avatar
Lukáš Tinkl committed
90
    if (!event->source() && isValidArchiveDrag(event->mimeData())) {
91
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
92
    }
93
    return;
94 95
}

96
void MainWindow::dropEvent(QDropEvent * event)
97
{
98
    qCDebug(ARK) << "dropEvent" << event;
99

100
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
101 102 103
    if (iface->isBusy()) {
        return;
    }
104

Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
105 106
    if ((event->source() == NULL) &&
        (isValidArchiveDrag(event->mimeData()))) {
107
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
108
    }
109 110 111 112

    //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));
113 114
}

115
void MainWindow::dragMoveEvent(QDragMoveEvent * event)
116
{
117
    qCDebug(ARK) << "dragMoveEvent" << event;
118

119
    Interface *iface = qobject_cast<Interface*>(m_part);
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
120 121 122
    if (iface->isBusy()) {
        return;
    }
123

Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
124 125
    if ((event->source() == NULL) &&
        (isValidArchiveDrag(event->mimeData()))) {
126
        event->acceptProposedAction();
Raphael Kubo da Costa's avatar
Raphael Kubo da Costa committed
127
    }
128 129
}

130 131
bool MainWindow::loadPart()
{
Bhushan Shah's avatar
Bhushan Shah committed
132 133 134 135 136
    KPluginFactory *factory = 0;
    KService::Ptr service = KService::serviceByDesktopName(QLatin1String("ark_part"));

    if (service) {
        factory = KPluginLoader(service->library()).factory();
137
    }
Bhushan Shah's avatar
Bhushan Shah committed
138 139 140 141

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

    if (!m_part) {
142
        KMessageBox::error(this, i18n("Unable to find Ark's KPart component, please check your installation."));
143
        qCWarning(ARK) << "Error loading Ark KPart.";
144 145
        return false;
    }
146

Laurent Montel's avatar
Laurent Montel committed
147
    m_part->setObjectName( QLatin1String("ArkPart" ));
148 149
    setCentralWidget(m_part->widget());
    createGUI(m_part);
150

151 152
    connect(m_part, SIGNAL(busy()), this, SLOT(updateActions()));
    connect(m_part, SIGNAL(ready()), this, SLOT(updateActions()));
153
    connect(m_part, SIGNAL(quit()), this, SLOT(quit()));
154

155
    return true;
156 157
}

Henrique Pinto's avatar
Henrique Pinto committed
158 159
void MainWindow::setupActions()
{
160 161 162
    m_newAction = KStandardAction::openNew(this, SLOT(newArchive()), actionCollection());
    m_openAction = KStandardAction::open(this, SLOT(openArchive()), actionCollection());
    KStandardAction::quit(this, SLOT(quit()), actionCollection());
163

Lukáš Tinkl's avatar
Lukáš Tinkl committed
164
    m_recentFilesAction = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), actionCollection());
165 166 167 168 169
    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
170
    m_recentFilesAction->loadEntries(KSharedConfig::openConfig()->group("Recent Files"));
171 172
    connect(m_recentFilesAction, SIGNAL(triggered()),
            this, SLOT(openArchive()));
173

174
    createStandardStatusBarAction();
175

176 177
    KStandardAction::configureToolbars(this, SLOT(editToolbars()), actionCollection());
    KStandardAction::keyBindings(this, SLOT(editKeyBindings()), actionCollection());
178 179
}

180 181
void MainWindow::updateActions()
{
182 183 184 185
    Interface *iface = qobject_cast<Interface*>(m_part);
    m_newAction->setEnabled(!iface->isBusy());
    m_openAction->setEnabled(!iface->isBusy());
    m_recentFilesAction->setEnabled(!iface->isBusy());
186 187
}

188 189
void MainWindow::editKeyBindings()
{
190 191 192
    KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, this);
    dlg.addCollection(actionCollection());
    dlg.addCollection(m_part->actionCollection());
193

194
    dlg.configure();
195 196 197 198
}

void MainWindow::editToolbars()
{
Bhushan Shah's avatar
Bhushan Shah committed
199 200
    KConfigGroup cfg(KSharedConfig::openConfig(), "MainWindow");
    saveMainWindowSettings(cfg);
201

202
    QPointer<KEditToolBar> dlg = new KEditToolBar(factory(), this);
203
    dlg.data()->exec();
204

205
    createGUI(m_part);
206

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

209
    delete dlg.data();
Henrique Pinto's avatar
Henrique Pinto committed
210 211 212 213
}

void MainWindow::openArchive()
{
214 215
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);
216
    Q_UNUSED(iface);
Lukáš Tinkl's avatar
Lukáš Tinkl committed
217 218 219

    QFileDialog dlg(this, i18nc("to open an archive", "Open Archive"));
    dlg.setMimeTypeFilters(Kerfuffle::supportedMimeTypes());
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

    QStringList filters = dlg.nameFilters();
    filters.removeDuplicates();
    filters.sort(Qt::CaseInsensitive);

    // Create the "All supported archives" filter
    QRegularExpression rx("(\\*\\.[a-z]+\\.*[a-z0-9]*)+");
    QString allArchives(i18n("All supported archives ("));
    foreach(QString s, filters)
    {
        QRegularExpressionMatchIterator i = rx.globalMatch(s);
        while (i.hasNext()) {
            QRegularExpressionMatch match = i.next();
            allArchives.append(match.captured(1) + " ");
        }
    }
    filters.prepend(allArchives + ")");
    dlg.setNameFilters(filters);

Lukáš Tinkl's avatar
Lukáš Tinkl committed
239 240 241 242 243
    dlg.setFileMode(QFileDialog::ExistingFile);
    dlg.setAcceptMode(QFileDialog::AcceptOpen);
    if (dlg.exec() == QDialog::Accepted) {
        openUrl(dlg.selectedUrls().first());
    }
244
}
Henrique Pinto's avatar
Henrique Pinto committed
245

Lukáš Tinkl's avatar
Lukáš Tinkl committed
246
void MainWindow::openUrl(const QUrl& url)
247
{
248 249
    if (!url.isEmpty()) {
        m_part->setArguments(m_openArgs);
250

251 252 253 254 255 256
        if (m_part->openUrl(url)) {
            m_recentFilesAction->addUrl(url);
        } else {
            m_recentFilesAction->removeUrl(url);
        }
    }
Henrique Pinto's avatar
Henrique Pinto committed
257 258
}

259 260
void MainWindow::setShowExtractDialog(bool option)
{
261
    if (option) {
262
        m_openArgs.metaData()[QLatin1String( "showExtractDialog" )] = QLatin1String( "true" );
263
    } else {
264
        m_openArgs.metaData().remove(QLatin1String( "showExtractDialog" ));
265
    }
266 267
}

Henrique Pinto's avatar
Henrique Pinto committed
268 269
void MainWindow::quit()
{
270
    close();
271 272 273 274
}

void MainWindow::newArchive()
{
275 276
    qCDebug(ARK) << "Creating new archive";

277 278
    Interface *iface = qobject_cast<Interface*>(m_part);
    Q_ASSERT(iface);
279
    Q_UNUSED(iface);
Raphael Kubo da Costa's avatar
const++  
Raphael Kubo da Costa committed
280 281

    const QStringList mimeTypes = Kerfuffle::supportedWriteMimeTypes();
282

283
    qCDebug(ARK) << "Supported mimetypes are" << mimeTypes.join(QLatin1String(" "));
284

Lukáš Tinkl's avatar
Lukáš Tinkl committed
285 286
    QFileDialog dlg(this);
    dlg.setMimeTypeFilters(mimeTypes);
287 288 289
    QStringList filters = dlg.nameFilters();
    filters.sort(Qt::CaseInsensitive);
    dlg.setNameFilters(filters);
Ragnar Thomsen's avatar
Ragnar Thomsen committed
290
    dlg.setFileMode(QFileDialog::AnyFile);
Lukáš Tinkl's avatar
Lukáš Tinkl committed
291 292 293 294 295 296 297
    dlg.setAcceptMode(QFileDialog::AcceptSave);
    if (dlg.exec() == QDialog::Accepted) {
        m_openArgs.metaData()[QLatin1String( "createNewArchive" )] = QLatin1String( "true" );
        openUrl(dlg.selectedUrls().first());
        m_openArgs.metaData().remove(QLatin1String( "showExtractDialog" ));
        m_openArgs.metaData().remove(QLatin1String( "createNewArchive" ));
    }
Henrique Pinto's avatar
Henrique Pinto committed
298
}