source: visorpdf/sources/main.cpp @ e0e368b

pruebas
Last change on this file since e0e368b was e0e368b, checked in by Pedro Buitrago <pbuitrago@…>, 8 years ago

agregando los directorios pendientes

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2
3Copyright 2012-2013 Adam Reichold
4Copyright 2014 Dorian Scholz
5Copyright 2012 Michał Trybus
6Copyright 2013 Chris Young
7
8This file is part of qpdfview.
9
10qpdfview is free software: you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation, either version 2 of the License, or
13(at your option) any later version.
14
15qpdfview is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with qpdfview.  If not, see <http://www.gnu.org/licenses/>.
22
23*/
24
25#include <iostream>
26
27#include <QApplication>
28#include <QDebug>
29#include <QDir>
30#include <QInputDialog>
31#include <QLibraryInfo>
32#include <QMessageBox>
33#include <QScopedPointer>
34#include <QTranslator>
35
36#ifdef WITH_DBUS
37
38#include <QDBusInterface>
39#include <QDBusReply>
40
41#endif // WITH_DBUS
42
43#ifdef WITH_SYNCTEX
44
45#include <synctex_parser.h>
46
47#endif // WITH_SYNCTEX
48
49#include "renderparam.h"
50#include "documentview.h"
51#include "database.h"
52#include "mainwindow.h"
53
54#ifdef WITH_SIGNALS
55
56#include "signalhandler.h"
57
58#endif // WITH_SIGNALS
59
60#ifdef __amigaos4__
61
62#include <proto/dos.h>
63#include <workbench/startup.h>
64
65const char* __attribute__((used)) stack_cookie = "\0$STACK:500000\0";
66
67#endif // __amigaos4__
68
69namespace
70{
71
72using namespace qpdfview;
73
74struct File
75{
76    QString filePath;
77    int page;
78
79    QString sourceName;
80    int sourceLine;
81    int sourceColumn;
82    QRectF enclosingBox;
83
84    File() : filePath(), page(-1), sourceName(), sourceLine(-1), sourceColumn(-1), enclosingBox() {}
85
86};
87
88enum ExitStatus
89{
90    ExitOk = 0,
91    ExitUnknownArgument = 1,
92    ExitIllegalArgument = 2,
93    ExitInconsistentArguments = 3,
94    ExitDBusError = 4
95};
96
97bool unique = false;
98bool quiet = false;
99
100QString instanceName;
101QString searchText;
102
103QList< File > files;
104
105MainWindow* mainWindow = 0;
106
107void loadTranslators()
108{
109    QTranslator* toolkitTranslator = new QTranslator(qApp);
110    QTranslator* applicationTranslator = new QTranslator(qApp);
111
112#if QT_VERSION >= QT_VERSION_CHECK(4,8,0)
113
114    if(toolkitTranslator->load(QLocale::system(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(toolkitTranslator); }
115
116    if(applicationTranslator->load(QLocale::system(), "qpdfview", "_", QDir(QApplication::applicationDirPath()).filePath("data"))) { qApp->installTranslator(applicationTranslator); }
117    else if(applicationTranslator->load(QLocale::system(), "qpdfview", "_", DATA_INSTALL_PATH)) { qApp->installTranslator(applicationTranslator); }
118
119#else
120
121    if(toolkitTranslator->load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(toolkitTranslator); }
122
123    if(applicationTranslator->load("qpdfview_" + QLocale::system().name(), QDir(QApplication::applicationDirPath()).filePath("data"))) { qApp->installTranslator(applicationTranslator); }
124    else if(applicationTranslator->load("qpdfview_" + QLocale::system().name(), DATA_INSTALL_PATH)) { qApp->installTranslator(applicationTranslator); }
125
126#endif // QT_VERSION
127}
128
129void parseCommandLineArguments()
130{
131    bool instanceNameIsNext = false;
132    bool searchTextIsNext = false;
133    bool noMoreOptions = false;
134
135    QRegExp fileAndPageRegExp("(.+)#(\\d+)");
136    QRegExp fileAndSourceRegExp("(.+)#src:(.+):(\\d+):(\\d+)");
137    QRegExp instanceNameRegExp("[A-Za-z_]+[A-Za-z0-9_]*");
138
139    QStringList arguments = QApplication::arguments();
140
141    if(!arguments.isEmpty())
142    {
143        arguments.removeFirst();
144    }
145
146    foreach(const QString& argument, arguments)
147    {
148        if(instanceNameIsNext)
149        {
150            if(argument.isEmpty())
151            {
152                qCritical() << QObject::tr("An empty instance name is not allowed.");
153                exit(ExitIllegalArgument);
154            }
155
156            instanceNameIsNext = false;
157            instanceName = argument;
158        }
159        else if(searchTextIsNext)
160        {
161            if(argument.isEmpty())
162            {
163                qCritical() << QObject::tr("An empty search text is not allowed.");
164                exit(ExitIllegalArgument);
165            }
166
167            searchTextIsNext = false;
168            searchText = argument;
169        }
170        else if(!noMoreOptions && argument.startsWith("--"))
171        {
172            if(argument == QLatin1String("--unique"))
173            {
174                unique = true;
175            }
176            else if(argument == QLatin1String("--quiet"))
177            {
178                quiet = true;
179            }
180            else if(argument == QLatin1String("--instance"))
181            {
182                instanceNameIsNext = true;
183            }
184            else if(argument == QLatin1String("--search"))
185            {
186                searchTextIsNext = true;
187            }
188            else if(argument == QLatin1String("--choose-instance"))
189            {
190                bool ok = false;
191                const QString chosenInstanceName = QInputDialog::getItem(0, QObject::tr("Choose instance"), QObject::tr("Instance:"), Database::instance()->loadInstanceNames(), 0, true, &ok);
192
193                if(ok)
194                {
195                    instanceName = chosenInstanceName;
196                }
197            }
198            else if(argument == QLatin1String("--help"))
199            {
200                std::cout << "Usage: qpdfview [options] [--] [file[#page]] [file[#src:name:line:column]] ..." << std::endl
201                          << std::endl
202                          << "Available options:" << std::endl
203                          << "  --help                      Show this information" << std::endl
204                          << "  --quiet                     Suppress warning messages when opening files" << std::endl
205                          << "  --search text               Search for text in the current tab" << std::endl
206                          << "  --unique                    Open files as tabs in unique window" << std::endl
207                          << "  --unique --instance name    Open files as tabs in named instance" << std::endl
208                          << "  --unique --choose-instance  Open files as tabs after choosing an instance name" << std::endl
209                          << std::endl
210                          << "Please report bugs at \"https://launchpad.net/qpdfview\"." << std::endl;
211
212                exit(ExitOk);
213            }
214            else if(argument == QLatin1String("--"))
215            {
216                noMoreOptions = true;
217            }
218            else
219            {
220                qCritical() << QObject::tr("Unknown command-line option '%1'.").arg(argument);
221                exit(ExitUnknownArgument);
222            }
223        }
224        else
225        {
226            File file;
227
228            if(fileAndPageRegExp.exactMatch(argument))
229            {
230                file.filePath = fileAndPageRegExp.cap(1);
231                file.page = fileAndPageRegExp.cap(2).toInt();
232            }
233            else if(fileAndSourceRegExp.exactMatch(argument))
234            {
235                file.filePath = fileAndSourceRegExp.cap(1);
236                file.sourceName = fileAndSourceRegExp.cap(2);
237                file.sourceLine = fileAndSourceRegExp.cap(3).toInt();
238                file.sourceColumn = fileAndSourceRegExp.cap(4).toInt();
239            }
240            else
241            {
242                file.filePath = argument;
243            }
244
245            files.append(file);
246        }
247    }
248
249    if(instanceNameIsNext)
250    {
251        qCritical() << QObject::tr("Using '--instance' requires an instance name.");
252        exit(ExitInconsistentArguments);
253    }
254
255    if(!unique && !instanceName.isEmpty())
256    {
257        qCritical() << QObject::tr("Using '--instance' is not allowed without using '--unique'.");
258        exit(ExitInconsistentArguments);
259    }
260
261    if(!instanceName.isEmpty() && !instanceNameRegExp.exactMatch(instanceName))
262    {
263        qCritical() << QObject::tr("An instance name must only contain the characters \"[A-Z][a-z][0-9]_\" and must not begin with a digit.");
264        exit(ExitIllegalArgument);
265    }
266
267    if(searchTextIsNext)
268    {
269        qCritical() << QObject::tr("Using '--search' requires a search text.");
270        exit(ExitInconsistentArguments);
271    }
272}
273
274void parseWorkbenchExtendedSelection(int argc, char** argv)
275{
276#ifdef __amigaos4__
277
278    if(argc == 0)
279    {
280        const int pathLength = 1024;
281        const QScopedArrayPointer< char > filePath(new char[pathLength]);
282
283        const struct WBStartup* wbStartup = reinterpret_cast< struct WBStartup* >(argv);
284
285        for(int index = 1; index < wbStartup->sm_NumArgs; ++index)
286        {
287            const struct WBArg* wbArg = wbStartup->sm_ArgList + index;
288
289            if((wbArg->wa_Lock) && (*wbArg->wa_Name))
290            {
291                IDOS->DevNameFromLock(wbArg->wa_Lock, filePath.data(), pathLength, DN_FULLPATH);
292                IDOS->AddPart(filePath.data(), wbArg->wa_Name, pathLength);
293
294                File file;
295                file.filePath = filePath.data();
296
297                files.append(file);
298            }
299        }
300    }
301
302#else
303
304    Q_UNUSED(argc);
305    Q_UNUSED(argv);
306
307#endif // __amigaos4__
308}
309
310void resolveSourceReferences()
311{
312#ifdef WITH_SYNCTEX
313
314    for(int index = 0; index < files.count(); ++index)
315    {
316        File& file = files[index];
317
318        if(!file.sourceName.isNull())
319        {
320            synctex_scanner_t scanner = synctex_scanner_new_with_output_file(file.filePath.toLocal8Bit(), 0, 1);
321
322            if(scanner != 0)
323            {
324                if(synctex_display_query(scanner, file.sourceName.toLocal8Bit(), file.sourceLine, file.sourceColumn) > 0)
325                {
326                    for(synctex_node_t node = synctex_next_result(scanner); node != 0; node = synctex_next_result(scanner))
327                    {
328                        int page = synctex_node_page(node);
329                        QRectF enclosingBox(synctex_node_box_visible_h(node), synctex_node_box_visible_v(node), synctex_node_box_visible_width(node), synctex_node_box_visible_height(node));
330
331                        if(file.page != page)
332                        {
333                            file.page = page;
334                            file.enclosingBox = enclosingBox;
335                        }
336                        else
337                        {
338                            file.enclosingBox = file.enclosingBox.united(enclosingBox);
339                        }
340                    }
341                }
342
343                synctex_scanner_free(scanner);
344            }
345            else
346            {
347                qWarning() << QObject::tr("SyncTeX data for '%1' could not be found.").arg(file.filePath);
348            }
349        }
350    }
351
352#endif // WITH_SYNCTEX
353}
354
355void activateUniqueInstance()
356{
357    qApp->setObjectName(instanceName);
358
359#ifdef WITH_DBUS
360
361    if(unique)
362    {
363        QString serviceName = QApplication::organizationDomain();
364
365        if(!instanceName.isEmpty())
366        {
367            serviceName.append('.');
368            serviceName.append(instanceName);
369        }
370
371        QScopedPointer< QDBusInterface > interface(new QDBusInterface(serviceName, "/MainWindow", "local.qpdfview.MainWindow", QDBusConnection::sessionBus()));
372
373        if(interface->isValid())
374        {
375            interface->call("raiseAndActivate");
376
377            foreach(const File& file, files)
378            {
379                QDBusReply< bool > reply = interface->call("jumpToPageOrOpenInNewTab", QFileInfo(file.filePath).absoluteFilePath(), file.page, true, file.enclosingBox, quiet);
380
381                if(!reply.isValid())
382                {
383                    qCritical() << QDBusConnection::sessionBus().lastError().message();
384
385                    exit(ExitDBusError);
386                }
387            }
388
389            if(!searchText.isEmpty())
390            {
391                interface->call("startSearch", searchText);
392            }
393
394            exit(ExitOk);
395        }
396        else
397        {
398            mainWindow = new MainWindow();
399
400            new MainWindowAdaptor(mainWindow);
401
402            if(!QDBusConnection::sessionBus().registerService(serviceName))
403            {
404                qCritical() << QDBusConnection::sessionBus().lastError().message();
405
406                delete mainWindow;
407                exit(ExitDBusError);
408            }
409
410            if(!QDBusConnection::sessionBus().registerObject("/MainWindow", mainWindow))
411            {
412                qCritical() << QDBusConnection::sessionBus().lastError().message();
413
414                delete mainWindow;
415                exit(ExitDBusError);
416            }
417        }
418
419        return;
420    }
421    else
422    {
423        mainWindow = new MainWindow();
424    }
425
426#else
427
428    mainWindow = new MainWindow();
429
430#endif // WITH_DBUS
431}
432
433void prepareSignalHandler()
434{
435#ifdef WITH_SIGNALS
436
437    if(SignalHandler::prepareSignals())
438    {
439        SignalHandler* signalHandler = new SignalHandler(mainWindow);
440
441        QObject::connect(signalHandler, SIGNAL(sigIntReceived()), mainWindow, SLOT(close()));
442        QObject::connect(signalHandler, SIGNAL(sigTermReceived()), mainWindow, SLOT(close()));
443    }
444    else
445    {
446        qWarning() << QObject::tr("Could not prepare signal handler.");
447    }
448
449#endif // WITH_SIGNALS
450}
451
452} // anonymous
453
454int main(int argc, char** argv)
455{
456    qRegisterMetaType< QList< QRectF > >("QList<QRectF>");
457    qRegisterMetaType< Rotation >("Rotation");
458    qRegisterMetaType< RenderParam >("RenderParam");
459
460    parseWorkbenchExtendedSelection(argc, argv);
461
462    QApplication application(argc, argv);
463
464    QApplication::setOrganizationDomain("local.qpdfview");
465    QApplication::setOrganizationName("qpdfview");
466    QApplication::setApplicationName("qpdfview");
467
468    QApplication::setApplicationVersion(APPLICATION_VERSION);
469
470    QApplication::setWindowIcon(QIcon(":icons/qpdfview.svg"));
471
472    loadTranslators();
473
474    parseCommandLineArguments();
475
476    resolveSourceReferences();
477
478    activateUniqueInstance();
479
480    prepareSignalHandler();
481
482    mainWindow->show();
483    mainWindow->setAttribute(Qt::WA_DeleteOnClose);
484
485    foreach(const File& file, files)
486    {
487        mainWindow->jumpToPageOrOpenInNewTab(file.filePath, file.page, true, file.enclosingBox, quiet);
488    }
489
490    if(!searchText.isEmpty())
491    {
492        mainWindow->startSearch(searchText);
493    }
494
495    return application.exec();
496}
Note: See TracBrowser for help on using the repository browser.