konqmain.cpp 14.8 KB
Newer Older
1
/* This file is part of the KDE project
2
   Copyright (C) 1998, 1999 Simon Hausmann <hausmann@kde.org>
3
   Copyright (C) 2016 David Faure <faure@kde.org>
4

5
6
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
7
8
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
9

10
   This program is distributed in the hope that it will be useful,
11
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
    General Public License for more details.
14

15
16
   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not, write to
Dirk Mueller's avatar
Dirk Mueller committed
17
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Dirk Mueller's avatar
Dirk Mueller committed
18
   Boston, MA 02110-1301, USA.
19
*/
20

21
22
23
24
#include "konqapplication.h"
#include "konqmisc.h"
#include "konqfactory.h"
#include "konqmainwindow.h"
25
#include "konqmainwindowfactory.h"
26
#include "konqsessionmanager.h"
27
#include "konqview.h"
Rafael Fernández López's avatar
Rafael Fernández López committed
28
#include "konqsettingsxt.h"
29
#include "konqurl.h"
30
#include "konqclosedwindowsmanager.h"
31

32
#include <KAboutData>
33
34
#include <KCrash>
#include <KLocalizedString>
35

36
#include <config-konqueror.h>
37
#include <konqueror-version.h>
38

David Faure's avatar
David Faure committed
39
#include "konqdebug.h"
40
#include <QFile>
David Faure's avatar
David Faure committed
41
#include <QDir>
42
#include <QDirIterator>
43
#include <QStandardPaths>
David Faure's avatar
David Faure committed
44

45
#include <KDBusService>
46
47
#include <QCommandLineParser>
#include <QCommandLineOption>
48
49
#include <KStartupInfo>
#include <KWindowSystem>
50
#include <kwindowsystem_version.h>
51

52
53
static void listSessions()
{
54
    const QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "sessions/";
55
56
    QDirIterator it(dir, QDir::Readable | QDir::NoDotAndDotDot | QDir::Dirs);
    while (it.hasNext()) {
57
58
59
60
        QFileInfo fileInfo(it.next());
        printf("%s\n", QFile::encodeName(fileInfo.baseName()).constData());
    }
}
61

62
63
64
65
static KonqMainWindow* handleCommandLine(QCommandLineParser &parser, const QString &workingDirectory, int *ret)
{
    *ret = 0;
    const QStringList args = parser.positionalArguments();
David Faure's avatar
David Faure committed
66
    qCDebug(KONQUEROR_LOG) << "args=" << args;
67
68
69
70
71
72
73
74
75
76
77
78
79
    // First the invocations that do not take urls.
    if (parser.isSet("sessions")) {
        listSessions();
        return nullptr;
    } else if (parser.isSet("open-session")) {
        const QString session = parser.value("open-session");
        QString sessionPath = session;
        if (!session.startsWith('/')) {
            sessionPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "sessions/" + session;
        }

        QDirIterator it(sessionPath, QDir::Readable | QDir::Files);
        if (!it.hasNext()) {
David Faure's avatar
David Faure committed
80
            qCWarning(KONQUEROR_LOG) << "session" << session << "not found or empty";
81
82
83
84
85
            *ret = 1;
            return nullptr;
        }

        KonqSessionManager::self()->restoreSessions(sessionPath);
86
87
88
89
90
        if (!KonqMainWindow::mainWindowList()->isEmpty()) {
            return KonqMainWindow::mainWindowList()->first();
        } else {
            return nullptr;
        }
91
92
    }

93
94
    const bool firstStart = !KonqMainWindow::mainWindowList();

95
96
97
98
    // Ask the user to recover session if applicable
    KonqSessionManager::self()->askUserToRestoreAutosavedAbandonedSessions();

    if (args.isEmpty()) {
99
100
        // No args. If --silent, do nothing, otherwise create a default window.
        if (!parser.isSet("silent")) {
101
102
103
104
105
106
107
            // #388333
            if (firstStart) {
                // If session recovery created some windows, no need for an empty window here.
                QList<KonqMainWindow *> *mainWindowList = KonqMainWindow::mainWindowList();
                if (mainWindowList && !mainWindowList->isEmpty()) {
                    return mainWindowList->at(0);
                }
108
109
            }

110
111
112
113
114
115
116
117
118
119
120
121
122
            KonqMainWindow *mainWin = KonqMainWindowFactory::createNewWindow();
            mainWin->show();
            return mainWin;
        }
    } else {
        // Now is a good time to parse each argument as a URL.
        QList<QUrl> urlList;
        for (int i = 0; i < args.count(); i++) {
            // KonqMisc::konqFilteredURL doesn't cope with local files... A bit of hackery below
            const QUrl url = QUrl::fromUserInput(args.at(i), workingDirectory);
            if (url.isLocalFile() && QFile::exists(url.toLocalFile())) { // "konqueror index.html"
                urlList += url;
            } else {
Friedrich W. H. Kossebau's avatar
Friedrich W. H. Kossebau committed
123
                urlList += KonqMisc::konqFilteredURL(nullptr, args.at(i));    // "konqueror slashdot.org"
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
            }
        }

        QList<QUrl> filesToSelect;

        if (parser.isSet("select")) {
            // Get all distinct directories from 'files' and open a tab
            // for each directory.
            QList<QUrl> dirs;
            Q_FOREACH (const QUrl &url, urlList) {
                const QUrl dir(url.adjusted(QUrl::RemoveFilename));
                if (!dirs.contains(dir)) {
                    dirs.append(dir);
                }
            }
            filesToSelect = urlList;
            urlList = dirs;
        }

        QUrl firstUrl = urlList.takeFirst();

        KParts::OpenUrlArguments urlargs;
        if (parser.isSet("mimetype")) {
            urlargs.setMimeType(parser.value("mimetype"));
        }

        KonqOpenURLRequest req;
        req.args = urlargs;
        req.filesToSelect = filesToSelect;
        req.tempFile = parser.isSet("tempfile");
        req.serviceName = parser.value("part");

        KonqMainWindow *mainwin = KonqMainWindowFactory::createNewWindow(firstUrl, req);
        mainwin->show();
        if (!urlList.isEmpty()) {
            // Open the other urls as tabs in that window
            mainwin->openMultiURL(urlList);
        }
        return mainwin;
    }
    return nullptr;
}
166

167
168
169
170
171
172
173
174
175
static void fixOldStartUrl() {
    QUrl startUrl(KonqSettings::startURL());
    if (startUrl.scheme() == "about") {
        startUrl.setScheme(KonqUrl::scheme());
        KonqSettings::setStartURL(startUrl.url());
        KonqSettings::self()->save();
    }
}

Andrius da Costa Ribas's avatar
Andrius da Costa Ribas committed
176
extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
177
{
178
179
    QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // says QtWebEngine
    KonquerorApplication app(argc, argv);
180
    KLocalizedString::setApplicationDomain("konqueror");
181

182
183
184
185
    KAboutData aboutData("konqueror", i18n("Konqueror"), KONQUEROR_VERSION);
    aboutData.setShortDescription(i18n("Web browser, file manager and document viewer."));
    aboutData.addLicense(KAboutLicense::GPL_V2);
    aboutData.setCopyrightStatement(i18n("(C) 1999-2016, The Konqueror developers"));
186
    aboutData.setHomepage("https://konqueror.org/");
187

188
189
    aboutData.addAuthor(i18n("Stefano Crocco"), i18n("Current maintainer"), "stefano.crocco@alice.it");
    aboutData.addAuthor(i18n("David Faure"), i18n("Developer (framework, parts, JavaScript, I/O library) and former maintainer"), "faure@kde.org");
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    aboutData.addAuthor(i18n("Simon Hausmann"), i18n("Developer (framework, parts)"), "hausmann@kde.org");
    aboutData.addAuthor(i18n("Michael Reiher"), i18n("Developer (framework)"), "michael.reiher@gmx.de");
    aboutData.addAuthor(i18n("Matthias Welk"), i18n("Developer"), "welk@fokus.gmd.de");
    aboutData.addAuthor(i18n("Alexander Neundorf"), i18n("Developer (List views)"), "neundorf@kde.org");
    aboutData.addAuthor(i18n("Michael Brade"), i18n("Developer (List views, I/O library)"), "brade@kde.org");
    aboutData.addAuthor(i18n("Lars Knoll"), i18n("Developer (HTML rendering engine)"), "knoll@kde.org");
    aboutData.addAuthor(i18n("Dirk Mueller"), i18n("Developer (HTML rendering engine)"), "mueller@kde.org");
    aboutData.addAuthor(i18n("Peter Kelly"), i18n("Developer (HTML rendering engine)"), "pmk@post.com");
    aboutData.addAuthor(i18n("Waldo Bastian"), i18n("Developer (HTML rendering engine, I/O library)"), "bastian@kde.org");
    aboutData.addAuthor(i18n("Germain Garand"), i18n("Developer (HTML rendering engine)"), "germain@ebooksfrance.org");
    aboutData.addAuthor(i18n("Leo Savernik"), i18n("Developer (HTML rendering engine)"), "l.savernik@aon.at");
    aboutData.addAuthor(i18n("Stephan Kulow"), i18n("Developer (HTML rendering engine, I/O library, regression test framework)"), "coolo@kde.org");
    aboutData.addAuthor(i18n("Antti Koivisto"), i18n("Developer (HTML rendering engine)"), "koivisto@kde.org");
    aboutData.addAuthor(i18n("Zack Rusin"),  i18n("Developer (HTML rendering engine)"), "zack@kde.org");
    aboutData.addAuthor(i18n("Tobias Anton"), i18n("Developer (HTML rendering engine)"), "anton@stud.fbi.fh-darmstadt.de");
    aboutData.addAuthor(i18n("Lubos Lunak"), i18n("Developer (HTML rendering engine)"), "l.lunak@kde.org");
    aboutData.addAuthor(i18n("Maks Orlovich"), i18n("Developer (HTML rendering engine, JavaScript)"), "maksim@kde.org");
    aboutData.addAuthor(i18n("Allan Sandfeld Jensen"), i18n("Developer (HTML rendering engine)"), "kde@carewolf.com");
    aboutData.addAuthor(i18n("Apple Safari Developers"), i18n("Developer (HTML rendering engine, JavaScript)"));
    aboutData.addAuthor(i18n("Harri Porten"), i18n("Developer (JavaScript)"), "porten@kde.org");
    aboutData.addAuthor(i18n("Koos Vriezen"), i18n("Developer (Java applets and other embedded objects)"), "koos.vriezen@xs4all.nl");
    aboutData.addAuthor(i18n("Matt Koss"), i18n("Developer (I/O library)"), "koss@miesto.sk");
    aboutData.addAuthor(i18n("Alex Zepeda"), i18n("Developer (I/O library)"), "zipzippy@sonic.net");
    aboutData.addAuthor(i18n("Richard Moore"), i18n("Developer (Java applet support)"), "rich@kde.org");
    aboutData.addAuthor(i18n("Dima Rogozin"), i18n("Developer (Java applet support)"), "dima@mercury.co.il");
    aboutData.addAuthor(i18n("Wynn Wilkes"), i18n("Developer (Java 2 security manager support,\n and other major improvements to applet support)"), "wynnw@calderasystems.com");
    aboutData.addAuthor(i18n("Stefan Schimanski"), i18n("Developer (Netscape plugin support)"), "schimmi@kde.org");
    aboutData.addAuthor(i18n("George Staikos"), i18n("Developer (SSL, Netscape plugins)"), "staikos@kde.org");
    aboutData.addAuthor(i18n("Dawit Alemayehu"), i18n("Developer (I/O library, Authentication support)"), "adawit@kde.org");
    aboutData.addAuthor(i18n("Carsten Pfeiffer"), i18n("Developer (framework)"), "pfeiffer@kde.org");
    aboutData.addAuthor(i18n("Torsten Rahn"), i18n("Graphics/icons"), "torsten@kde.org");
    aboutData.addAuthor(i18n("Torben Weis"), i18n("KFM author"), "weis@kde.org");
    aboutData.addAuthor(i18n("Joseph Wenninger"), i18n("Developer (navigation panel framework)"), "jowenn@kde.org");
    aboutData.addAuthor(i18n("Stephan Binner"), i18n("Developer (misc stuff)"), "binner@kde.org");
    aboutData.addAuthor(i18n("Ivor Hewitt"), i18n("Developer (AdBlock filter)"), "ivor@ivor.org");
    aboutData.addAuthor(i18n("Eduardo Robles Elvira"), i18n("Developer (framework)"), "edulix@gmail.com");

    KAboutData::setApplicationData(aboutData);

229
230
    KCrash::initialize();

231
    QCommandLineParser parser;
232
    parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    aboutData.setupCommandLine(&parser);

    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("silent")}, i18n("Start without a default window, when called without URLs")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("preload")}, i18n("Preload for later use. This mode does not support URLs on the command line")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("profile")}, i18n("Profile to open (DEPRECATED, IGNORED)"), i18n("profile")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("sessions")}, i18n("List available sessions")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("open-session")}, i18n("Session to open"), i18n("session")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("mimetype")}, i18n("Mimetype to use for this URL (e.g. text/html or inode/directory)"), i18n("mimetype")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("part")}, i18n("Part to use (e.g. khtml or kwebkitpart)"), i18n("service")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("select")}, i18n("For URLs that point to files, opens the directory and selects the file, instead of opening the actual file")));
    parser.addOption(QCommandLineOption(QStringList{QStringLiteral("tempfile")}, i18n("The files/URLs opened by the application will be deleted after use")));

    parser.addPositionalArgument(QStringLiteral("[URL]"), i18n("Location to open"));

    parser.process(app);
    aboutData.processCommandLine(&parser);

250
251
252
253
254
255
256
    KDBusService dbusService(KDBusService::Unique);
    QObject::connect(&dbusService, &KDBusService::activateRequested, [&parser](const QStringList &arguments, const QString &workingDirectory) {
        parser.parse(arguments);
        int ret;
        KonqMainWindow *mainWindow = handleCommandLine(parser, workingDirectory, &ret);
        if (mainWindow) {
            // terminate startup notification and activate the mainwindow:
257
258
259
260
#if KWINDOWSYSTEM_VERSION >= QT_VERSION_CHECK(5,62,0)
            mainWindow->setAttribute(Qt::WA_NativeWindow, true);
            KStartupInfo::setNewStartupId(mainWindow->windowHandle(), KStartupInfo::startupId());
#else
261
            KStartupInfo::setNewStartupId(mainWindow, KStartupInfo::startupId());
262
#endif
263
264
265
            KWindowSystem::forceActiveWindow(mainWindow->winId());
        }
    });
266

267
    fixOldStartUrl();
268
269
270
271
272

    if (app.isSessionRestored()) {
        KonqSessionManager::self()->askUserToRestoreAutosavedAbandonedSessions();

        int n = 1;
273
        while (KonqMainWindow::canBeRestored(n)) {
274
            const QString className = KXmlGuiWindow::classNameOfToplevel(n);
275
            if (className == QLatin1String("KonqMainWindow")) {
276
                (new KonqMainWindow())->restore(n);
277
            } else {
David Faure's avatar
David Faure committed
278
                qCWarning(KONQUEROR_LOG) << "Unknown class" << className << "in session saved data!";
279
            }
280
281
            ++n;
        }
282
    } else if (parser.isSet("preload")) {
283
        new KonqMainWindow(KonqUrl::url(KonqUrl::Type::Blank)); // prepare an empty window, with the web renderer preloaded
284
    } else {
285
286
287
288
        int ret = 0;
        KonqMainWindow *mainWindow = handleCommandLine(parser, QDir::currentPath(), &ret);
        if (!mainWindow) {
            return ret;
289
290
        }
    }
291
292

    const int ret = app.exec();
293

294
295
    // Delete all KonqMainWindows, so that we don't have
    // any parts loaded when KLibLoader::cleanUp is called.
296
    // (and Qt doesn't delete WA_DeleteOnClose widgets on exit anyway :()
Friedrich W. H. Kossebau's avatar
Friedrich W. H. Kossebau committed
297
    while (KonqMainWindow::mainWindowList() != nullptr) {
298
        // the list will be deleted by last KonqMainWindow
299
300
        delete KonqMainWindow::mainWindowList()->first();
    }
Alexander Kellett's avatar
Alexander Kellett committed
301

302
303
304
    // Notify the session manager that the instance was closed without errors, and normally.
    KonqSessionManager::self()->disableAutosave();
    KonqSessionManager::self()->deleteOwnedSessions();
305

306
307
    KonqClosedWindowsManager::destroy();

308
    return ret;
309
}