Switch to unified view

a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp
...
...
1499
    return false;
1499
    return false;
1500
}
1500
}
1501
1501
1502
void RclMain::startNativeViewer(Rcl::Doc doc, int pagenum, QString term)
1502
void RclMain::startNativeViewer(Rcl::Doc doc, int pagenum, QString term)
1503
{
1503
{
1504
    LOGDEB(("RclMain::startNativeViewer: page %d\n", pagenum));
1505
    // Look for appropriate viewer
1506
    string apptag;
1504
    string apptag;
1507
    doc.getmeta(Rcl::Doc::keyapptg, &apptag);
1505
    doc.getmeta(Rcl::Doc::keyapptg, &apptag);
1506
    LOGDEB(("RclMain::startNativeViewer: mtype [%s] apptag [%s] page %d "
1507
      "term [%s] url [%s] ipath [%s]\n", 
1508
      doc.mimetype.c_str(), apptag.c_str(), pagenum, 
1509
      (const char *)(term.toUtf8()), doc.url.c_str(), doc.ipath.c_str()
1510
         ));
1511
1512
    // Look for appropriate viewer
1508
    string cmdplusattr = theconfig->getMimeViewerDef(doc.mimetype, apptag, 
1513
    string cmdplusattr = theconfig->getMimeViewerDef(doc.mimetype, apptag, 
1509
                             prefs.useDesktopOpen);
1514
                             prefs.useDesktopOpen);
1510
1511
    if (cmdplusattr.empty()) {
1515
    if (cmdplusattr.empty()) {
1512
    QMessageBox::warning(0, "Recoll", 
1516
    QMessageBox::warning(0, "Recoll", 
1513
                 tr("No external viewer configured for mime type [")
1517
                 tr("No external viewer configured for mime type [")
1514
                 + doc.mimetype.c_str() + "]");
1518
                 + doc.mimetype.c_str() + "]");
1515
    return;
1519
    return;
1516
    }
1520
    }
1517
1521
1518
    if (pagenum == -1) {
1522
    // Separate command string and viewer attributes (if any)
1519
  pagenum = 1;
1520
  string lterm;
1521
  if (m_source.isNotNull())
1522
      pagenum = m_source->getFirstMatchPage(doc, lterm);
1523
  if (pagenum == -1)
1524
      pagenum = 1;
1525
  else
1526
      term = QString::fromUtf8(lterm.c_str());
1527
    }
1528
    char cpagenum[20];
1529
    sprintf(cpagenum, "%d", pagenum);
1530
1531
    // Extract possible viewer attributes
1532
    ConfSimple attrs;
1523
    ConfSimple viewerattrs;
1533
    string cmd;
1524
    string cmd;
1534
    theconfig->valueSplitAttributes(cmdplusattr, cmd, attrs);
1525
    theconfig->valueSplitAttributes(cmdplusattr, cmd, viewerattrs);
1535
    bool ignoreipath = false;
1526
    bool ignoreipath = false;
1536
    if (attrs.get("ignoreipath", cmdplusattr))
1527
    if (viewerattrs.get("ignoreipath", cmdplusattr))
1537
        ignoreipath = stringToBool(cmdplusattr);
1528
        ignoreipath = stringToBool(cmdplusattr);
1538
1529
1539
    // Split the command line
1530
    // Split the command line
1540
    vector<string> lcmd;
1531
    vector<string> lcmd;
1541
    if (!stringToStrings(cmd, lcmd)) {
1532
    if (!stringToStrings(cmd, lcmd)) {
1542
    QMessageBox::warning(0, "Recoll", 
1533
    QMessageBox::warning(0, "Recoll", 
1543
                 tr("Bad viewer command line for %1: [%2]\n"
1534
                 tr("Bad viewer command line for %1: [%2]\n"
1544
                "Please check the mimeconf file")
1535
                "Please check the mimeview file")
1545
                 .arg(QString::fromAscii(doc.mimetype.c_str()))
1536
                 .arg(QString::fromAscii(doc.mimetype.c_str()))
1546
                 .arg(QString::fromLocal8Bit(cmd.c_str())));
1537
                 .arg(QString::fromLocal8Bit(cmd.c_str())));
1547
    return;
1538
    return;
1548
    }
1539
    }
1549
1540
1550
    // Look for the command to execute in the exec path and the filters 
1541
    // Look for the command to execute in the exec path and the filters 
1551
    // directory
1542
    // directory
1552
    string cmdpath;
1543
    string execpath;
1553
    if (!ExecCmd::which(lcmd.front(), cmdpath)) {
1544
    if (!ExecCmd::which(lcmd.front(), execpath)) {
1554
    cmdpath = theconfig->findFilter(lcmd.front());
1545
    execpath = theconfig->findFilter(lcmd.front());
1555
    // findFilter returns its input param if the filter is not in
1546
    // findFilter returns its input param if the filter is not in
1556
    // the normal places. As we already looked in the path, we
1547
    // the normal places. As we already looked in the path, we
1557
    // have no use for a simple command name here (as opposed to
1548
    // have no use for a simple command name here (as opposed to
1558
    // mimehandler which will just let execvp do its thing). Erase
1549
    // mimehandler which will just let execvp do its thing). Erase
1559
    // cmdpath so that the user dialog will be started further
1550
    // execpath so that the user dialog will be started further
1560
    // down.
1551
    // down.
1561
    if (!cmdpath.compare(lcmd.front())) 
1552
    if (!execpath.compare(lcmd.front())) 
1562
        cmdpath.erase();
1553
        execpath.erase();
1563
1554
1564
    // Specialcase text/html because of the help browser need
1555
    // Specialcase text/html because of the help browser need
1565
    if (cmdpath.empty() && !doc.mimetype.compare("text/html")) {
1556
    if (execpath.empty() && !doc.mimetype.compare("text/html")) {
1566
        if (lookForHtmlBrowser(cmdpath)) {
1557
        if (lookForHtmlBrowser(execpath)) {
1567
        lcmd.clear();
1558
        lcmd.clear();
1568
        lcmd.push_back(cmdpath);
1559
        lcmd.push_back(execpath);
1569
        lcmd.push_back("%u");
1560
        lcmd.push_back("%u");
1570
        }
1561
        }
1571
    }
1562
    }
1572
    }
1563
    }
1573
1564
1574
1565
1575
    // Command not found: start the user dialog to help find another one:
1566
    // Command not found: start the user dialog to help find another one:
1576
    if (cmdpath.empty()) {
1567
    if (execpath.empty()) {
1577
    QString mt = QString::fromAscii(doc.mimetype.c_str());
1568
    QString mt = QString::fromAscii(doc.mimetype.c_str());
1578
    QString message = tr("The viewer specified in mimeview for %1: %2"
1569
    QString message = tr("The viewer specified in mimeview for %1: %2"
1579
                 " is not found.\nDo you want to start the "
1570
                 " is not found.\nDo you want to start the "
1580
                 " preferences dialog ?")
1571
                 " preferences dialog ?")
1581
        .arg(mt).arg(QString::fromLocal8Bit(lcmd.front().c_str()));
1572
        .arg(mt).arg(QString::fromLocal8Bit(lcmd.front().c_str()));
...
...
1592
    }
1583
    }
1593
        // The user will have to click on the link again to try the
1584
        // The user will have to click on the link again to try the
1594
        // new command.
1585
        // new command.
1595
    return;
1586
    return;
1596
    }
1587
    }
1588
    // Get rid of the command name. lcmd is now argv[1...n]
1589
    lcmd.erase(lcmd.begin());
1597
1590
1598
    // We may need a temp file, or not, depending on the command
1591
1599
    // arguments and the fact that this is a subdoc or not.
1592
    // Process the command arguments to determine if we need to create
1593
    // a temporary file.
1594
1595
    // If the command has a %i parameter it will manage the
1596
    // un-embedding. Else if ipath is not empty, we need a temp file.
1597
    // This can be overridden with the "ignoreipath" attribute
1600
    bool wantsipath = (cmd.find("%i") != string::npos) || ignoreipath;
1598
    bool groksipath = (cmd.find("%i") != string::npos) || ignoreipath;
1599
1600
    // wantsfile: do we actually need a local file ? The only other
1601
    // case here is an url %u (ie: for web history).
1601
    bool wantsfile = cmd.find("%f") != string::npos;
1602
    bool wantsfile = cmd.find("%f") != string::npos;
1603
    bool wantsparentfile = cmd.find("%F") != string::npos;
1604
1605
    if (wantsfile && wantsparentfile) {
1606
  QMessageBox::warning(0, "Recoll", 
1607
               tr("Viewer command line for %1 specifies both "
1608
              "file and parent file value: unsupported")
1609
               .arg(QString::fromAscii(doc.mimetype.c_str())));
1610
  return;
1611
    }
1612
  
1613
    string url = doc.url;
1614
    string fn = fileurltolocalpath(doc.url);
1615
    Rcl::Doc pdoc;
1616
    if (wantsparentfile) {
1617
  // We want the path for the parent document. For example to
1618
  // open the chm file, not the internal page. Note that we just
1619
  // override the other file name in this case.
1620
  if (m_source.isNull() || !m_source->getEnclosing(doc, pdoc)) {
1621
      QMessageBox::warning(0, "Recoll",
1622
               tr("Cannot find parent document"));
1623
      return;
1624
  }
1625
  // Override fn with the parent's : 
1626
  fn = fileurltolocalpath(pdoc.url);
1627
1628
  // If the parent document has an ipath too, we need to create
1629
  // a temp file even if the command takes an ipath
1630
  // parameter. We have no viewer which could handle a double
1631
  // embedding. Will have to change if such a one appears.
1632
  if (!pdoc.ipath.empty()) {
1633
      groksipath = false;
1634
  }
1635
    }
1636
1602
    bool istempfile = false;
1637
    bool istempfile = false;
1603
    string fn = fileurltolocalpath(doc.url);
1638
1604
    string orgfn = fn;
1639
    LOGDEB(("RclMain::startNV: groksipath %d wantsf %d wantsparentf %d\n", 
1605
    string url = doc.url;
1640
      groksipath, wantsfile, wantsparentfile));
1606
1641
1607
    // If the command wants a file but this is not a file url, or
1642
    // If the command wants a file but this is not a file url, or
1608
    // there is an ipath that it won't understand, we need a temp file:
1643
    // there is an ipath that it won't understand, we need a temp file:
1609
    theconfig->setKeyDir(path_getfather(fn));
1644
    theconfig->setKeyDir(path_getfather(fn));
1610
    if ((wantsfile && fn.empty()) || (!wantsipath && !doc.ipath.empty())) {
1645
    if (((wantsfile || wantsparentfile) && fn.empty()) ||
1646
  (!groksipath && !doc.ipath.empty())) {
1611
    TempFile temp;
1647
    TempFile temp;
1648
  Rcl::Doc& thedoc = wantsparentfile ? pdoc : doc;
1612
    if (!FileInterner::idocToFile(temp, string(), theconfig, doc)) {
1649
    if (!FileInterner::idocToFile(temp, string(), theconfig, thedoc)) {
1613
        QMessageBox::warning(0, "Recoll",
1650
        QMessageBox::warning(0, "Recoll",
1614
                 tr("Cannot extract document or create "
1651
                 tr("Cannot extract document or create "
1615
                    "temporary file"));
1652
                    "temporary file"));
1616
        return;
1653
        return;
1617
    }
1654
    }
...
...
1645
            fn = temp->filename();
1682
            fn = temp->filename();
1646
            url = string("file://") + fn;
1683
            url = string("file://") + fn;
1647
        }
1684
        }
1648
    }
1685
    }
1649
1686
1650
    // Get rid of the command name. lcmd is now argv[1...n]
1687
    // If we are not called with a page number (which would happen for a call
1651
    lcmd.erase(lcmd.begin());
1688
    // from the snippets window), see if we can compute a page number anyway.
1689
    if (pagenum == -1) {
1690
  pagenum = 1;
1691
  string lterm;
1692
  if (m_source.isNotNull())
1693
      pagenum = m_source->getFirstMatchPage(doc, lterm);
1694
  if (pagenum == -1)
1695
      pagenum = 1;
1696
  else // We get the match term used to compute the page
1697
      term = QString::fromUtf8(lterm.c_str());
1698
    }
1699
    char cpagenum[20];
1700
    sprintf(cpagenum, "%d", pagenum);
1701
1652
1702
1653
    // Substitute %xx inside arguments
1703
    // Substitute %xx inside arguments
1654
    string efftime;
1704
    string efftime;
1655
    if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
1705
    if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
1656
        efftime = doc.dmtime.empty() ? doc.fmtime : doc.dmtime;
1706
        efftime = doc.dmtime.empty() ? doc.fmtime : doc.dmtime;
...
...
1660
    // Try to keep the letters used more or less consistent with the reslist
1710
    // Try to keep the letters used more or less consistent with the reslist
1661
    // paragraph format.
1711
    // paragraph format.
1662
    map<string, string> subs;
1712
    map<string, string> subs;
1663
    subs["D"] = efftime;
1713
    subs["D"] = efftime;
1664
    subs["f"] = fn;
1714
    subs["f"] = fn;
1665
    subs["F"] = orgfn;
1715
    subs["F"] = fn;
1666
    subs["i"] = doc.ipath;
1716
    subs["i"] = FileInterner::getLastIpathElt(doc.ipath);
1667
    subs["M"] = doc.mimetype;
1717
    subs["M"] = doc.mimetype;
1668
    subs["p"] = cpagenum;
1718
    subs["p"] = cpagenum;
1669
    subs["s"] = (const char*)term.toLocal8Bit();
1719
    subs["s"] = (const char*)term.toLocal8Bit();
1670
    subs["U"] = url;
1720
    subs["U"] = url;
1671
    subs["u"] = url;
1721
    subs["u"] = url;
...
...
1703
    zg_send_event(ZGSEND_OPEN, doc);
1753
    zg_send_event(ZGSEND_OPEN, doc);
1704
1754
1705
    // We keep pushing back and never deleting. This can't be good...
1755
    // We keep pushing back and never deleting. This can't be good...
1706
    ExecCmd *ecmd = new ExecCmd;
1756
    ExecCmd *ecmd = new ExecCmd;
1707
    m_viewers.push_back(ecmd);
1757
    m_viewers.push_back(ecmd);
1708
    ecmd->startExec(cmdpath, lcmd, false, false);
1758
    ecmd->startExec(execpath, lcmd, false, false);
1709
}
1759
}
1710
1760
1711
void RclMain::startManual()
1761
void RclMain::startManual()
1712
{
1762
{
1713
    startManual(string());
1763
    startManual(string());