diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4a278e1..1bea621f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,128 +1,128 @@
project(kile)
cmake_minimum_required(VERSION 3.0.0)
set(KILE_VERSION CACHE STRING "Kile's version; can be used to set the internal version of Kile on MacOSX")
find_package(ECM 5.19.0 REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMAddAppIcon)
include(ECMOptionalAddSubdirectory)
include(ECMInstallIcons)
include(ECMSetupVersion)
include(ECMMarkNonGuiExecutable)
include(ECMGenerateHeaders)
include(GenerateExportHeader)
include(CMakePackageConfigHelpers)
include(FeatureSummary)
include(WriteBasicConfigVersionFile)
include(CheckFunctionExists)
include(KDEInstallDirs)
include(KDECMakeSettings)
kde_enable_exceptions()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules)
-find_package(Qt5 5.3 CONFIG REQUIRED
+find_package(Qt5 5.6 CONFIG REQUIRED
Core
DBus
Widgets
Script
Test
)
find_package(KF5 5.31 REQUIRED COMPONENTS
Config
CoreAddons
Crash
DBusAddons
DocTools
GuiAddons
I18n
IconThemes
Init
KHtml
KIO
Parts
TextEditor
WindowSystem
XmlGui
)
find_package(Okular5 REQUIRED)
set_package_properties(Okular5 PROPERTIES
DESCRIPTION "Okular core library"
URL "http://okular.kde.org")
find_package(Poppler COMPONENTS Qt5)
set_package_properties("Poppler" PROPERTIES
TYPE RECOMMENDED
PURPOSE "Support for PDF file operations.")
if(Poppler_Qt5_FOUND)
set(HAVE_POPPLER TRUE)
include_directories(${Poppler_INCLUDE_DIRS})
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/src/config.h)
# find_package(SharedMimeInfo REQUIRED)
add_definitions(
# -DQT_USE_QSTRINGBUILDER
# -DQT_NO_CAST_FROM_ASCII
# -DQT_NO_CAST_FROM_BYTEARRAY
# -DQT_USE_FAST_OPERATOR_PLUS
-DQT_NO_CAST_TO_ASCII
-DQT_STRICT_ITERATORS
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_SIGNALS_SLOTS_KEYWORDS
)
if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
add_definitions(-DQT_MESSAGELOGCONTEXT)
endif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
add_subdirectory(doc)
add_subdirectory(src)
########### install files ###############
install(
FILES kile.xml
DESTINATION ${XDG_MIME_INSTALL_DIR})
# update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})
install(
FILES
kile.upd
DESTINATION ${KDE_INSTALL_DATAROOTDIR}/kconf_update)
install(
PROGRAMS
kile1.6_upd.pl
kile1.7_upd.pl
kile1.9_upd.pl
kile1.9-1_upd.pl
kile2.0-1_upd.pl
kile2.0-2_upd.pl
kile2.0-3_upd.pl
kile2.0-4_upd.pl
kile2.0-5_upd.pl
DESTINATION ${KDE_INSTALL_DATAROOTDIR}/kconf_update)
install(FILES
AUTHORS
ChangeLog
README
README.cwl
kile-remote-control.txt
README.MacOSX
DESTINATION ${KDE_INSTALL_DATAROOTDIR}/doc/kile)
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/src/dialogs/usermenu/usermenutree.cpp b/src/dialogs/usermenu/usermenutree.cpp
index 95d6914e..992fb7aa 100644
--- a/src/dialogs/usermenu/usermenutree.cpp
+++ b/src/dialogs/usermenu/usermenutree.cpp
@@ -1,1110 +1,1034 @@
/***********************************************************************************
Copyright (C) 2011-2012 by Holger Danielsson (holger.danielsson@versanet.de)
***********************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include "dialogs/usermenu/usermenuitem.h"
#include "dialogs/usermenu/usermenutree.h"
#include "kiledebug.h"
// Qt::UserRole+1: menutype
// Qt::UserRole+2: errorcode for menu item
namespace KileMenu {
// - Separators are shown as a horizontal line (Qt:UserRole+1)
// - Menu items with errors are displayed in red (Qt:UserRole+2)
void MenuentryDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const
{
QString menutitle = index.data(Qt::DisplayRole).toString();
int error = index.data(Qt::UserRole+2).toInt();
// any errors?
if (index.column()==0 && error!=UserMenuItem::MODEL_ERROR_NONE ) {
QStyleOptionViewItem optionCustom = option;
optionCustom.palette.setColor(QPalette::Text, Qt::red);
QStyledItemDelegate::paint( painter, optionCustom, index );
}
else {
QStyledItemDelegate::paint( painter, option, index );
}
// display separators
QString itemtype = index.data(Qt::UserRole+1).toString();
if ( itemtype == "separator" ) {
QRect r = option.rect;
int y = ( r.bottom() + r.top() ) / 2;
painter->save();
QPen pen = QPen(Qt::gray);
painter->setPen(pen);
painter->drawLine(r.left()+3,y, r.right()-20,y);
painter->restore();
}
}
///////////////////////////// UserMenuTree //////////////////////////////
UserMenuTree::UserMenuTree(QWidget *parent)
: QTreeWidget(parent)
{
setColumnCount(2);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::Fixed);
header()->setSectionsMovable(false);
header()->setStretchLastSection(false);
setColumnWidth(1,140);
setItemDelegateForColumn(0, new MenuentryDelegate(parent));
// drag and drop
setDragEnabled(true);
setDropIndicatorShown(true);
//setAcceptDrops(true);
setDragDropMode(QAbstractItemView::InternalMove);
setDragDropOverwriteMode(false);
initEnvPathlist();
}
bool UserMenuTree::isEmpty()
{
return ( topLevelItemCount() == 0 );
}
///////////////////////////// PATH environment variable //////////////////////////////
// save PATH to search for executable files
void UserMenuTree::initEnvPathlist()
{
QString envpath;
#if QT_VERSION >= 0x040600
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
if ( env.contains("PATH") ) {
envpath = env.value("PATH");
}
#else
// Returns the environment of the calling process as a list of key=value pairs.
QStringList environment = QProcess::systemEnvironment();
foreach ( const QString &s, environment ) {
if ( s.startsWith(QLatin1String("PATH=")) ) {
envpath = s.mid(5);
break;
}
}
#endif
#ifdef Q_WS_WIN
m_envPathlist = envpath.split(';');
#else
m_envPathlist = envpath.split(':');
#endif
m_envPathlist.append(".");
}
bool UserMenuTree::isItemExecutable(const QString &filename)
{
if ( filename.isEmpty() ) {
return false;
}
// absolute paths can be checked immediately
QFileInfo fi(filename);
if ( fi.isAbsolute() ) {
return fi.isExecutable();
}
// search in all paths
for (int i=0; i 0 ) {
QString temp = m_envPathlist[0];
m_envPathlist[0] = m_envPathlist[i];
m_envPathlist[i] = temp;
}
return true;
}
}
return false;
}
///////////////////////////// context menu event //////////////////////////////
// build a context menu
void UserMenuTree::contextMenuRequested(const QPoint &pos)
{
KILE_DEBUG_MAIN << "context menu requested ..." ;
m_popupItem = dynamic_cast(itemAt(pos));
if ( !m_popupItem ) {
KILE_DEBUG_MAIN << "... no item found";
return;
}
KILE_DEBUG_MAIN << "... popup item found: " << m_popupItem->text(0);
bool submenu = ( m_popupItem->menutype() == UserMenuData::Submenu );
bool separator = ( m_popupItem->menutype() == UserMenuData::Separator );
QMenu popup;
- QAction *action = Q_NULLPTR;
- QSignalMapper signalMapper;
- connect(&signalMapper, SIGNAL(mapped(int)), this, SLOT(slotPopupActivated(int)));
// insert standard menu items
- action = popup.addAction(QIcon::fromTheme("usermenu-insert-above.png"),i18n("Insert above"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_INSERT_ABOVE);
- action = popup.addAction(QIcon::fromTheme("usermenu-insert-below.png"),i18n("Insert below"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_INSERT_BELOW);
+ popup.addAction(QIcon::fromTheme("usermenu-insert-above.png"),i18n("Insert above"), this, [this] {insertMenuItem(m_popupItem, false);});
+ popup.addAction(QIcon::fromTheme("usermenu-insert-below.png"),i18n("Insert below"), this, [this] {insertMenuItem(m_popupItem, true);});
popup.addSeparator();
// insert separators
if ( !separator ) {
- action = popup.addAction(QIcon::fromTheme("usermenu-separator-above.png"),i18n("Insert a separator above"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SEPARATOR_ABOVE);
- action = popup.addAction(QIcon::fromTheme("usermenu-separator-below.png"),i18n("Insert a separator below"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SEPARATOR_BELOW);
+ popup.addAction(QIcon::fromTheme("usermenu-separator-above.png"),i18n("Insert a separator above"), this, [this] {insertSeparator(m_popupItem, false);});
+ popup.addAction(QIcon::fromTheme("usermenu-separator-below.png"),i18n("Insert a separator below"), this, [this] {insertSeparator(m_popupItem, true);});
popup.addSeparator();
}
// insert submenus
- action = popup.addAction(QIcon::fromTheme("usermenu-submenu-above.png"),i18n("Insert a submenu above"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SUBMENU_ABOVE);
- action = popup.addAction(QIcon::fromTheme("usermenu-submenu-below.png"),i18n("Insert a submenu below"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SUBMENU_BELOW);
+ popup.addAction(QIcon::fromTheme("usermenu-submenu-above.png"),i18n("Insert a submenu above"), this, [this] {insertSubmenu(m_popupItem, false);});
+ popup.addAction(QIcon::fromTheme("usermenu-submenu-below.png"),i18n("Insert a submenu below"), this, [this] {insertSubmenu(m_popupItem, true);});
popup.addSeparator();
// insert into submenus
if ( submenu ) {
- action = popup.addAction(QIcon::fromTheme("usermenu-into-submenu.png"),i18n("Insert into this submenu"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_INTO_SUBMENU);
- action = popup.addAction(i18n("Insert a separator into this submenu"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SEPARATOR_INTO_SUBMENU);
- action = popup.addAction(i18n("Insert a submenu into this submenu"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_SUBMENU_INTO_SUBMENU);
+ popup.addAction(QIcon::fromTheme("usermenu-into-submenu.png"),i18n("Insert into this submenu"), this, [this] {insertIntoSubmenu(m_popupItem, UserMenuData::Text);});
+ popup.addAction(i18n("Insert a separator into this submenu"), this, [this] {insertIntoSubmenu(m_popupItem, UserMenuData::Separator);});
+ popup.addAction(i18n("Insert a submenu into this submenu"), this, [this] {insertIntoSubmenu(m_popupItem, UserMenuData::Submenu);});
popup.addSeparator();
}
// delete actions
- action = popup.addAction(QIcon::fromTheme("usermenu-delete.png"),i18n("Delete this item"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action,POPUP_DELETE_ITEM);
+ popup.addAction(QIcon::fromTheme("usermenu-delete.png"),i18n("Delete this item"), this, [this] {itemDelete(m_popupItem);});
popup.addSeparator();
- action = popup.addAction(QIcon::fromTheme("usermenu-clear.png"),i18n("Delete the complete tree"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_DELETE_TREE);
+ popup.addAction(QIcon::fromTheme("usermenu-clear.png"),i18n("Delete the complete tree"), this, [this] {deleteMenuTree();});
// expand/collapse tree
if ( submenu ) {
popup.addSeparator();
if ( m_popupItem->isExpanded() ) {
- action = popup.addAction(i18n("Collapse submenu"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action,POPUP_COLLAPSE_ITEM);
+ popup.addAction(i18n("Collapse submenu"), this, [this] {m_popupItem->setExpanded(false);});
}
else {
- action = popup.addAction(i18n("Expand submenu"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action,POPUP_EXPAND_ITEM);
+ popup.addAction(i18n("Expand submenu"), this, [this] {m_popupItem->setExpanded(true);});
}
popup.addSeparator();
- action = popup.addAction(i18n("Collapse complete tree"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action,POPUP_COLLAPSE_TREE);
- action = popup.addAction(i18n("Expand complete tree"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action,POPUP_EXPAND_TREE);
+ popup.addAction(i18n("Collapse complete tree"), this, [this] {collapseAll();});
+ popup.addAction(i18n("Expand complete tree"), this, [this] {expandAll();});
}
// if there are any errors with this item, some info is available
int error = m_popupItem->data(0,Qt::UserRole+2).toInt();
if ( error != UserMenuItem::MODEL_ERROR_NONE ) {
popup.addSeparator();
- action = popup.addAction(QIcon::fromTheme("help-about.png"),i18n("Info"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, POPUP_ITEM_INFO);
+ popup.addAction(QIcon::fromTheme("help-about.png"),i18n("Info"), this, [this] {itemInfo(m_popupItem);});
}
// const QPoint& pos parameter in the customContextMenuRequested() signal is normally in widget coordinates.
// But classes like QTreeWidget, which inherit from QAbstractScrollArea1 instead use the coordinates of their viewport()
if ( !popup.isEmpty() ) {
popup.exec( viewport()->mapToGlobal(pos) );
}
}
-// a context menu action was selected
-void UserMenuTree::slotPopupActivated(int id)
-{
- KILE_DEBUG_MAIN << "popup activated with id: " << id;
- switch (id ) {
- case POPUP_INSERT_ABOVE:
- insertMenuItem (m_popupItem, false);
- break;
- case POPUP_INSERT_BELOW:
- insertMenuItem (m_popupItem, true);
- break;
- case POPUP_SEPARATOR_ABOVE:
- insertSeparator(m_popupItem, false);
- break;
- case POPUP_SEPARATOR_BELOW:
- insertSeparator(m_popupItem, true);
- break;
- case POPUP_SUBMENU_ABOVE:
- insertSubmenu (m_popupItem, false);
- break;
- case POPUP_SUBMENU_BELOW:
- insertSubmenu (m_popupItem, true);
- break;
- case POPUP_INTO_SUBMENU:
- insertIntoSubmenu(m_popupItem, UserMenuData::Text);
- break;
- case POPUP_SEPARATOR_INTO_SUBMENU:
- insertIntoSubmenu(m_popupItem, UserMenuData::Separator);
- break;
- case POPUP_SUBMENU_INTO_SUBMENU:
- insertIntoSubmenu(m_popupItem, UserMenuData::Submenu);
- break;
- case POPUP_DELETE_ITEM:
- itemDelete(m_popupItem);
- break;
- case POPUP_DELETE_TREE:
- deleteMenuTree();
- break;
- case POPUP_COLLAPSE_ITEM:
- m_popupItem->setExpanded(false);
- break;
- case POPUP_EXPAND_ITEM:
- m_popupItem->setExpanded(true);
- break;
- case POPUP_COLLAPSE_TREE:
- collapseAll();
- break;
- case POPUP_EXPAND_TREE:
- expandAll();
- break;
- case POPUP_ITEM_INFO:
- itemInfo(m_popupItem);
- break;
- }
-}
-
///////////////////////////// read XML //////////////////////////////
// read an xml file and check for errors
bool UserMenuTree::readXml(const QString &filename)
{
KILE_DEBUG_MAIN << "read xml file " << filename;
QDomDocument doc("UserMenu");
QFile file(filename);
if ( !file.open(QFile::ReadOnly | QFile::Text) ) {
KMessageBox::error(this, i18n("File '%1' does not exist.", filename));
return false;
}
if ( !doc.setContent( &file ) ) {
file.close();
return false;
}
file.close();
KILE_DEBUG_MAIN << "parse xml ...";
blockSignals(true);
// clear menutree
clear();
// read toplevelitems
QDomElement root = doc.documentElement();
QDomElement e = root.firstChildElement();
while ( !e.isNull()) {
QString tag = e.tagName();
UserMenuItem *item = Q_NULLPTR;
if ( tag == "submenu" ) {
item = readXmlSubmenu(e);
}
else if ( tag == "separator" ) {
item = readXmlSeparator();
}
else { /* if ( tag == "menu" ) */
item = readXmlMenuentry(e);
}
if ( item ) {
addTopLevelItem(item);
}
e = e.nextSiblingElement();
}
// the xml menu is built, now check for errors
setErrorCodes();
// polish menutree
expandAll();
if ( topLevelItemCount() > 0 ) {
setCurrentItem( topLevelItem(0) );
}
blockSignals(false);
return true;
}
// a separator tag was found
UserMenuItem *UserMenuTree::readXmlSeparator()
{
return new UserMenuItem(UserMenuData::Separator, QString());
}
// read tags for a submenu
UserMenuItem *UserMenuTree::readXmlSubmenu(const QDomElement &element)
{
UserMenuItem *submenuitem = new UserMenuItem(UserMenuData::Submenu, QString()) ;
QString title;
if ( element.hasChildNodes() ) {
QDomElement e = element.firstChildElement();
while ( !e.isNull()) {
UserMenuItem *item = Q_NULLPTR;
QString tag = e.tagName();
if ( tag == "title" ) {
title = e.text();
}
else if ( tag == "submenu" ) {
item = readXmlSubmenu(e);
}
else if ( tag == "separator" ) {
item = readXmlSeparator();
}
else { /* if ( tag == "menu" ) */
item = readXmlMenuentry(e);
}
submenuitem->setMenutitle(title);
submenuitem->setText(0,title);
if ( item ) {
submenuitem->addChild(item);
}
e = e.nextSiblingElement();
}
}
return submenuitem;
}
// read tags for a standard menu item
UserMenuItem *UserMenuTree::readXmlMenuentry(const QDomElement &element)
{
QString menutypename = element.attribute("type");
UserMenuData::MenuType menutype = UserMenuData::xmlMenuType(menutypename);
UserMenuItem *menuentryitem = new UserMenuItem(menutype, QString()) ;
// default values
QString title;
QString plaintext;
QString filename;
QString parameter;
QString icon;
QString shortcut;
bool needsSelection = false;
bool useContextMenu = false;
bool replaceSelection = false;
bool selectInsertion = false;
bool insertOutput = false;
// read values
if ( element.hasChildNodes() ) {
QDomElement e = element.firstChildElement();
while ( !e.isNull()) {
QString tag = e.tagName();
QString text = e.text();
int index = UserMenuData::xmlMenuTag(tag);
switch (index) {
case UserMenuData::XML_TITLE:
title = text;
break;
case UserMenuData::XML_PLAINTEXT:
plaintext = text;
break;
case UserMenuData::XML_FILENAME:
filename = text;
break;
case UserMenuData::XML_PARAMETER:
parameter = text;
break;
case UserMenuData::XML_ICON:
icon = text;
break;
case UserMenuData::XML_SHORTCUT:
shortcut = text;
break;
case UserMenuData::XML_NEEDSSELECTION:
needsSelection = str2bool(text);
break;
case UserMenuData::XML_USECONTEXTMENU:
useContextMenu = str2bool(text);
break;
case UserMenuData::XML_REPLACESELECTION:
replaceSelection = str2bool(text);
break;
case UserMenuData::XML_SELECTINSERTION:
selectInsertion = str2bool(text);
break;
case UserMenuData::XML_INSERTOUTPUT:
insertOutput = str2bool(text);
break;
}
e = e.nextSiblingElement();
}
// save values
menuentryitem->setMenutitle(title);
// add code newline
plaintext = UserMenuData::decodeLineFeed(plaintext);
menuentryitem->setPlaintext(plaintext);
menuentryitem->setFilename(filename);
menuentryitem->setParameter(parameter);
if ( !icon.isEmpty() ) {
menuentryitem->setMenuicon(icon);
menuentryitem->setIcon(0,QIcon::fromTheme(icon));
}
if ( !shortcut.isEmpty() ) {
QKeySequence seq = QKeySequence::fromString(shortcut,QKeySequence::PortableText);
shortcut = seq.toString(QKeySequence::NativeText);
menuentryitem->setShortcut(shortcut);
menuentryitem->setText(1,shortcut);
}
menuentryitem->setNeedsSelection(needsSelection);
menuentryitem->setUseContextMenu(useContextMenu);
menuentryitem->setReplaceSelection(replaceSelection);
menuentryitem->setSelectInsertion(selectInsertion);
menuentryitem->setInsertOutput(insertOutput);
menuentryitem->setText(0,title);
}
return menuentryitem;
}
///////////////////////////// write XML //////////////////////////////
bool UserMenuTree::writeXml(const QString &filename)
{
KILE_DEBUG_MAIN << "write xml file " << filename;
QFile file(filename);
if ( !file.open(QFile::WriteOnly | QFile::Text) ) {
KMessageBox::error(this, i18n("File '%1' could not be opened to save the usermenu file.", filename));
return false;
}
QXmlStreamWriter xmlWriter(&file);
xmlWriter.setAutoFormatting(true);
xmlWriter.setAutoFormattingIndent(2) ;
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement("UserMenu");
for (int i = 0; i < topLevelItemCount(); ++i) {
writeXmlItem(&xmlWriter, dynamic_cast(topLevelItem(i)) );
}
xmlWriter.writeEndDocument();
file.close();
return true;
}
void UserMenuTree::writeXmlItem(QXmlStreamWriter *xml, UserMenuItem *item)
{
switch (item->menutype()) {
case UserMenuData::Separator:
writeXmlSeparator(xml);
break;
case UserMenuData::Submenu:
writeXmlSubmenu(xml,item);
break;
default:
writeXmlMenuentry(xml,item);
break;
}
}
// write xml tags for a standard menu item
void UserMenuTree::writeXmlMenuentry(QXmlStreamWriter *xml, UserMenuItem *item)
{
int menutype = item->menutype();
QString menutypename = UserMenuData::xmlMenuTypeName(menutype);
xml->writeStartElement("menu");
xml->writeAttribute("type", menutypename);
QString menutitle = ( item->text(0) == EMPTY_MENUENTRY ) ? QString() : item->text(0);
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_TITLE),menutitle);
if ( menutype == UserMenuData::Text ) {
QString plaintext = item->plaintext();
if ( !plaintext.isEmpty() ) {
// encode newline characters
plaintext = UserMenuData::encodeLineFeed(plaintext);
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_PLAINTEXT), plaintext);
}
}
else { /* if ( menutype!=UserMenuData::FileContent || menutype==UserMenuData:Program) */
// both types use a filename
QString filename = item->filename();
if ( !filename.isEmpty() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_FILENAME), filename);
// but UserMenuItem::Program may have an additional parameter
if ( menutype == UserMenuData::Program) {
QString parameter = item->parameter();
if ( !parameter.isEmpty() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_PARAMETER), parameter);
}
}
}
}
QString icon = item->menuicon();
if ( !icon.isEmpty() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_ICON),icon);
}
QKeySequence seq = QKeySequence::fromString( item->shortcut(), QKeySequence::NativeText );
if ( !seq.isEmpty() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_SHORTCUT), seq.toString(QKeySequence::PortableText));
}
if ( item->needsSelection() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_NEEDSSELECTION), "true");
}
if ( item->useContextMenu() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_USECONTEXTMENU), "true");
}
if ( item->replaceSelection() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_REPLACESELECTION), "true");
}
if ( item->selectInsertion() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_SELECTINSERTION), "true");
}
if ( item->insertOutput() ) {
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_INSERTOUTPUT), "true");
}
xml->writeEndElement();
}
// write xml tags for a submenu
void UserMenuTree::writeXmlSubmenu(QXmlStreamWriter *xml, UserMenuItem *item)
{
xml->writeStartElement("submenu");
QString menutitle = item->text(0);
if ( menutitle == EMPTY_MENUENTRY ) {
menutitle.clear();
}
else if ( menutitle.right(LENGTH_SUBSTITUTE) == EMPTY_SUBMENU ) {
menutitle = menutitle.left(menutitle.length()-LENGTH_SUBSTITUTE);
}
xml->writeTextElement(UserMenuData::xmlMenuTagName(UserMenuData::XML_TITLE),menutitle);
for ( int i=0; ichildCount(); ++i ) {
writeXmlItem(xml, dynamic_cast(item->child(i)) );
}
xml->writeEndElement();
}
// write xml tag for a separator
void UserMenuTree::writeXmlSeparator(QXmlStreamWriter *xml)
{
xml->writeStartElement("separator");
xml->writeEndElement();
}
///////////////////////////// check menutree and set error codes //////////////////////////////
// the complete menutree was build, now check for errors
// - empty menutitles
// - useless submenus without children
// - empty filenames, not existing or not executable files
void UserMenuTree::setErrorCodes()
{
KILE_DEBUG_MAIN << "check menutree for errors and set error codes ...";
for (int i = 0; i < topLevelItemCount(); ++i) {
UserMenuItem *item = dynamic_cast(topLevelItem(i));
UserMenuData::MenuType type = item->menutype();
bool executable = ( type==UserMenuData::Program && isItemExecutable(item->filename()) );
item->setModelData(executable);
if ( type != UserMenuData::Separator ) {
checkMenuTitle(item);
}
if ( type == UserMenuData::Submenu ) {
checkSubmenu(item);
}
}
}
void UserMenuTree::checkMenuTitle(UserMenuItem *item)
{
if ( item->menutitle().isEmpty() ) {
item->setText(0,EMPTY_MENUENTRY);
KILE_DEBUG_MAIN << "empty menutitle changed to " << EMPTY_MENUENTRY;
}
}
void UserMenuTree::checkSubmenu(UserMenuItem *item)
{
QString menutitle = item->menutitle();
int children = item->childCount();
if ( menutitle.isEmpty() ) {
menutitle = EMPTY_MENUENTRY;
}
else if ( children == 0 ) {
menutitle += EMPTY_SUBMENU;
}
item->setText(0,menutitle);
for ( int i=0; i(item->child(i));
child->setModelData();
UserMenuData::MenuType type = child->menutype();
if ( type != UserMenuData::Separator ) {
checkMenuTitle(child);
}
if ( type == UserMenuData::Submenu ) {
checkSubmenu(child);
}
}
}
///////////////////////////// check menutree //////////////////////////////
// check for errors (true=no errors)
bool UserMenuTree::errorCheck()
{
KILE_DEBUG_MAIN << "check menutree for errors ...";
for (int i = 0; i < topLevelItemCount(); ++i) {
UserMenuItem *item = dynamic_cast(topLevelItem(i));
UserMenuData::MenuType type = item->menutype();
if ( type != UserMenuData::Separator ) {
if ( item->data(0,Qt::UserRole+2).toInt() != UserMenuItem::MODEL_ERROR_NONE ) {
return false;
}
}
if ( type == UserMenuData::Submenu ) {
if ( checkSubmenuError(item) == false ) {
return false;
}
}
}
return true;
}
bool UserMenuTree::checkSubmenuError(UserMenuItem *item)
{
int children = item->childCount();
for ( int i=0; i(item->child(i));
UserMenuData::MenuType type = child->menutype();
if ( type != UserMenuData::Separator ) {
if ( child->data(0,Qt::UserRole+2).toInt() != UserMenuItem::MODEL_ERROR_NONE ) {
return false;
}
}
if ( type == UserMenuData::Submenu ) {
if ( checkSubmenuError(child) == false ) {
return false;
}
}
}
return true;
}
///////////////////////////// tree ops //////////////////////////////
// insert a standard menu item
bool UserMenuTree::insertMenuItem(QTreeWidgetItem *current, bool below)
{
QString menulabel = getMenuTitle(i18n("Please enter a label for this menu item:"));
if ( menulabel.isEmpty() ) {
return false;
}
if ( below ) {
insertMenuItemBelow(current,UserMenuData::Text,menulabel);
}
else {
insertMenuItemAbove(current,UserMenuData::Text,menulabel);
}
return true;
}
// insert a submenu item
bool UserMenuTree::insertSubmenu(QTreeWidgetItem *current, bool below)
{
QString menulabel = getMenuTitle(i18n("Please enter a label for this submenu:"));
if ( menulabel.isEmpty() ) {
return false;
}
if ( below ) {
insertMenuItemBelow(current,UserMenuData::Submenu,menulabel);
}
else {
insertMenuItemAbove(current,UserMenuData::Submenu,menulabel);
}
return true;
}
// insert a separator item
bool UserMenuTree::insertSeparator(QTreeWidgetItem *current, bool below)
{
if(below) {
insertMenuItemBelow(current,UserMenuData::Separator, QString());
}
else {
insertMenuItemAbove(current,UserMenuData::Separator, QString());
}
return true;
}
void UserMenuTree::insertMenuItemAbove(QTreeWidgetItem *current, UserMenuData::MenuType type, const QString &menulabel)
{
QTreeWidgetItem *parent = ( current ) ? current->parent() : Q_NULLPTR;
int index = itemIndex(parent,current);
UserMenuItem *item = new UserMenuItem(type,menulabel);
insertItem(parent,index,item);
item->setText(0,menulabel);
setCurrentItem(item);
}
void UserMenuTree::insertMenuItemBelow(QTreeWidgetItem *current, UserMenuData::MenuType type, const QString &menulabel)
{
UserMenuItem *item;
QTreeWidgetItem *parent = ( current ) ? current->parent() : Q_NULLPTR;
if(!parent) {
item = new UserMenuItem(this,current,type,menulabel);
}
else {
item = new UserMenuItem(parent,current,type,menulabel);
}
item->setText(0,menulabel);
setCurrentItem(item);
}
void UserMenuTree::insertIntoSubmenu(QTreeWidgetItem *current, UserMenuData::MenuType type)
{
QString menulabel;
if ( type == UserMenuData::Text || type == UserMenuData::Submenu ) {
menulabel = getMenuTitle(i18n("Please enter a label for this entry:"));
if ( menulabel.isEmpty() ) {
return;
}
}
UserMenuItem *item = new UserMenuItem(type,menulabel);
insertItem(current,0,item);
setCurrentItem(item);
}
// delete an item
void UserMenuTree::itemDelete(QTreeWidgetItem *current)
{
int children,index;
QTreeWidgetItem *item, *selectitem;
QTreeWidgetItem *parent = current->parent();
if(!parent) {
children = topLevelItemCount();
index = indexOfTopLevelItem(current);
if ( index < children-1 ) {
selectitem = topLevelItem(index+1);
}
else if ( index > 0 ) {
selectitem = topLevelItem(index-1);
}
else {
selectitem = Q_NULLPTR;
}
item = takeTopLevelItem(index);
}
else {
children = parent->childCount();
index = parent->indexOfChild(current);
if ( index < children-1 ) {
selectitem = parent->child(index+1);
}
else if ( index > 0 ) {
selectitem = parent->child(index-1);
}
else {
selectitem = parent;
}
item = parent->takeChild(index);
}
delete item;
if(selectitem) {
setCurrentItem(selectitem);
}
}
// move an item one position up
void UserMenuTree::itemUp()
{
QTreeWidgetItem *current = currentItem();
UserMenuItem *aboveitem = dynamic_cast(itemAbove(current));
if (!aboveitem) {
return;
}
bool expanded = current->isExpanded();
blockSignals(true);
QTreeWidgetItem *aboveparent = aboveitem->parent();
int aboveindex = itemIndex(aboveparent,aboveitem);
UserMenuItem *parent = dynamic_cast(current->parent());
int index = itemIndex(parent,current);
takeItem(parent,current);
if ( parent!=aboveparent && index!=0 ) {
aboveindex++;
}
if ( parent==aboveparent && aboveitem->menutype()==UserMenuData::Submenu ) {
insertItem(aboveitem,0,current);
}
else {
insertItem(aboveparent,aboveindex,current);
}
// update model data of old and new parent, if it has changed
UserMenuItem *newparent = dynamic_cast(current->parent());
if ( parent != newparent ) {
if ( parent ) {
parent->setModelData();
parent->setText(0, parent->updateMenutitle());
}
if ( newparent ) {
newparent->setModelData();
newparent->setText(0, newparent->updateMenutitle());
}
}
current->setExpanded(expanded);
setCurrentItem(current);
blockSignals(false);
}
// move an item one position down
void UserMenuTree::itemDown()
{
QTreeWidgetItem *current = currentItem();
bool expanded = current->isExpanded();
blockSignals(true);
// get all necessary parameter
UserMenuItem *parent = dynamic_cast(current->parent());
int index = itemIndex(parent,current);
int children = numChildren(parent);
// successor exists?
if ( index < children-1 ) {
UserMenuItem *successor = dynamic_cast( itemAtIndex(parent,index+1) );
takeItem(parent,current);
if ( successor->menutype() == UserMenuData::Submenu ) {
successor->insertChild(0,current);
}
else {
insertItem(parent,index+1,current);
}
}
else if ( parent ) {
QTreeWidgetItem *grandparent = parent->parent();
int parentindex = itemIndex(grandparent,parent);
takeItem(parent,current);
insertItem(grandparent,parentindex+1,current);
}
// update model data of old and new parent, if it has changed
UserMenuItem *newparent = dynamic_cast(current->parent());
if ( parent != newparent ) {
if ( parent ) {
parent->setModelData();
parent->setText(0, parent->updateMenutitle());
}
if ( newparent ) {
newparent->setModelData();
newparent->setText(0, newparent->updateMenutitle());
}
}
current->setExpanded(expanded);
setCurrentItem(current);
blockSignals(false);
}
////////////////////////////// delete tree //////////////////////////////
// delete the whole menutree
void UserMenuTree::deleteMenuTree()
{
if ( KMessageBox::questionYesNo(this, i18n("Do you really want to clear the complete menutree?") ) == KMessageBox::Yes ) {
blockSignals(true);
clear();
blockSignals(false);
}
}
////////////////////////////// info //////////////////////////////
// prepare info for en item with errors
void UserMenuTree::itemInfo(UserMenuItem *item)
{
int error = item->data(0,Qt::UserRole+2).toInt();
QStringList list;
if ( error & UserMenuItem::MODEL_ERROR_EMPTY ) {
list << i18n("This menuitem has no title.");
}
if ( error & UserMenuItem::MODEL_ERROR_SUBMENU ) {
list << i18n("This submenu item is useless without children.");
}
if ( error & UserMenuItem::MODEL_ERROR_TEXT ) {
list << i18n("This item offers no text to insert.");
}
if ( error & UserMenuItem::MODEL_ERROR_FILE_EMPTY ) {
list << i18n("No file is given for this task.");
}
if ( error & UserMenuItem::MODEL_ERROR_FILE_EXIST ) {
list << i18n("The file for this item does not exist.");
}
if ( error & UserMenuItem::MODEL_ERROR_FILE_EXECUTABLE ) {
list << i18n("The file for this item is not executable.");
}
QString msg = i18n("Error:");
if ( list.size() == 1 ) {
msg += "
" + list[0] + "
";
}
else {
msg += "";
foreach ( const QString &s, list ) {
msg += "- " + s + "
";
}
msg += "
";
}
KMessageBox::information(this, msg, i18n("Menutree Error"));
}
////////////////////////////// auxiliary //////////////////////////////
int UserMenuTree::itemIndex(QTreeWidgetItem *parent, QTreeWidgetItem *item)
{
return ( parent ) ? parent->indexOfChild(item) : indexOfTopLevelItem(item);
}
QTreeWidgetItem *UserMenuTree::itemAtIndex(QTreeWidgetItem *parent, int index)
{
return ( parent ) ? parent->child(index) : topLevelItem(index);
}
int UserMenuTree::numChildren(QTreeWidgetItem *parent)
{
return ( parent ) ? parent->childCount() : topLevelItemCount();
}
void UserMenuTree::insertItem(QTreeWidgetItem *parent, int index, QTreeWidgetItem *item)
{
if ( parent ) {
parent->insertChild(index,item);
}
else {
insertTopLevelItem(index,item);
}
}
void UserMenuTree::takeItem(QTreeWidgetItem *parent, QTreeWidgetItem *item)
{
if ( parent ) {
int index = parent->indexOfChild(item);
parent->takeChild(index);
}
else {
int index = indexOfTopLevelItem(item);
takeTopLevelItem(index);
}
}
bool UserMenuTree::str2bool(const QString &value)
{
return ( value == "true" );
}
QString UserMenuTree::getMenuTitle(const QString &title)
{
bool ok;
QString value = QInputDialog::getText(this, i18n("Name"), title, QLineEdit::Normal, QString(), &ok);
return ( ok ) ? value : QString();
}
}
diff --git a/src/dialogs/usermenu/usermenutree.h b/src/dialogs/usermenu/usermenutree.h
index 6e9c8af7..8b91b792 100644
--- a/src/dialogs/usermenu/usermenutree.h
+++ b/src/dialogs/usermenu/usermenutree.h
@@ -1,113 +1,100 @@
/***********************************************************************************
Copyright (C) 2011-2012 by Holger Danielsson (holger.danielsson@versanet.de)
***********************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef USERMENUTREE_H
#define USERMENUTREE_H
#include
#include
#include
#include
#include
#include
namespace KileMenu {
class MenuentryDelegate : public QStyledItemDelegate {
public:
MenuentryDelegate(QObject *parent=0) : QStyledItemDelegate(parent) {}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override;
};
class UserMenuTree : public QTreeWidget
{
Q_OBJECT
public:
explicit UserMenuTree(QWidget *parent);
~UserMenuTree() {}
bool insertMenuItem(QTreeWidgetItem *current, bool below=true);
bool insertSubmenu(QTreeWidgetItem *current, bool below=true);
bool insertSeparator(QTreeWidgetItem *current, bool below=true);
void itemDelete(QTreeWidgetItem *current);
void itemUp();
void itemDown();
void contextMenuRequested(const QPoint &pos);
bool readXml(const QString &filename);
bool writeXml(const QString &filename);
bool errorCheck();
bool isItemExecutable(const QString &filename);
bool isEmpty();
-private Q_SLOTS:
- void slotPopupActivated(int id);
-
private:
- enum PopupType { POPUP_INSERT_ABOVE=0x00, POPUP_INSERT_BELOW=0x01,
- POPUP_SEPARATOR_ABOVE=0x02, POPUP_SEPARATOR_BELOW=0x03,
- POPUP_SUBMENU_ABOVE=0x04, POPUP_SUBMENU_BELOW=0x05,
- POPUP_INTO_SUBMENU=0x06, POPUP_SEPARATOR_INTO_SUBMENU=0x07, POPUP_SUBMENU_INTO_SUBMENU=0x08,
- POPUP_DELETE_ITEM=0x09, POPUP_DELETE_TREE=0x0A,
- POPUP_COLLAPSE_ITEM=0x0B, POPUP_EXPAND_ITEM=0x0C,
- POPUP_COLLAPSE_TREE=0x0D, POPUP_EXPAND_TREE=0x0E,
- POPUP_ITEM_INFO=0x0F
- };
-
UserMenuItem *m_popupItem;
void setErrorCodes();
bool checkSubmenuError(UserMenuItem *item);
QStringList m_envPathlist;
void initEnvPathlist();
void insertMenuItemAbove(QTreeWidgetItem *current, UserMenuData::MenuType type, const QString &menulabel);
void insertMenuItemBelow(QTreeWidgetItem *current, UserMenuData::MenuType type, const QString &menulabel);
void insertIntoSubmenu(QTreeWidgetItem *current, UserMenuData::MenuType type);
void deleteMenuTree();
int itemIndex(QTreeWidgetItem *parent, QTreeWidgetItem *item);
QTreeWidgetItem *itemAtIndex(QTreeWidgetItem *parent, int index);
int numChildren(QTreeWidgetItem *parent);
void insertItem(QTreeWidgetItem *parent, int index, QTreeWidgetItem *item);
void takeItem(QTreeWidgetItem *parent, QTreeWidgetItem *item);
UserMenuItem *readXmlSeparator();
UserMenuItem *readXmlSubmenu(const QDomElement &element);
UserMenuItem *readXmlMenuentry(const QDomElement &element);
void writeXmlItem(QXmlStreamWriter *xml, UserMenuItem *item);
void writeXmlMenuentry(QXmlStreamWriter *xml, UserMenuItem *item);
void writeXmlSubmenu(QXmlStreamWriter *xml, UserMenuItem *item);
void writeXmlSeparator(QXmlStreamWriter *xml);
void checkMenuTitle(UserMenuItem *item);
void checkSubmenu(UserMenuItem *item);
bool str2bool(const QString &value);
QString getMenuTitle(const QString &title);
void itemInfo(UserMenuItem *item);
};
}
#endif
diff --git a/src/livepreview.h b/src/livepreview.h
index cb71315a..4607a18d 100644
--- a/src/livepreview.h
+++ b/src/livepreview.h
@@ -1,196 +1,195 @@
/********************************************************************************
Copyright (C) 2011-2018 by Michel Ludwig (michel.ludwig@kdemail.net)
********************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef LIVEPREVIEW_H
#define LIVEPREVIEW_H
#include "documentinfo.h"
#include "kileinfo.h"
#include "kileproject.h"
#include "kiletool.h"
#include "editorextension.h"
#include "widgets/previewwidget.h"
#include
#include
#include
-#include
#include
#include
#include
#include
#include
namespace KileDocument {
class TextInfo;
}
namespace KileTool
{
class LivePreviewManager : public QObject
{
Q_OBJECT
public:
// has to be instatiated after the view manager only!
LivePreviewManager(KileInfo *ki, KActionCollection *ac);
~LivePreviewManager();
// live preview won't be run in 'boot up' mode, which is enabled by default
void disableBootUpMode();
void readConfig(KConfig *config);
void writeConfig();
static void readLivePreviewStatusSettings(KConfigGroup &configGroup, LivePreviewUserStatusHandler *handler);
static void writeLivePreviewStatusSettings(KConfigGroup &configGroup, LivePreviewUserStatusHandler *handler);
void compilePreview(KileDocument::LaTeXInfo *info, KTextEditor::View *view);
void showPreviewCompileIfNecessary(KileDocument::LaTeXInfo *info, KTextEditor::View *view);
bool isLivePreviewActive() const;
bool isLivePreviewPossible() const;
bool isLivePreviewEnabledForCurrentDocument();
void setLivePreviewEnabledForCurrentDocument(bool b);
void buildLivePreviewMenu(KConfig *config);
QString getPreviewFile() const;
inline QUrl getPreviewFileURL() const {
return QUrl::fromLocalFile(getPreviewFile());
}
Q_SIGNALS:
void livePreviewSuccessful();
void livePreviewRunning();
void livePreviewStopped(); // disabled or stopped
public Q_SLOTS:
void handleTextChanged(KTextEditor::Document *doc);
void handleDocumentSavedOrUploaded(KTextEditor::Document *doc, bool savedAs);
void handleMasterDocumentChanged();
void recompileLivePreview();
void refreshLivePreview();
void showCursorPositionInDocumentViewer();
private Q_SLOTS:
void handleDocumentModificationTimerTimeout();
// TextInfo* object due to the signal 'aboutToBeDestroyed(KileDocument::TextInfo*)'
void removeLaTeXInfo(KileDocument::TextInfo *info);
void removeProject(KileProject *project);
void toolDestroyed();
void toolDone(KileTool::Base *base, int i, bool childToolSpawned);
void childToolDone(KileTool::Base *base, int i, bool childToolSpawned);
void handleTextViewActivated(KTextEditor::View *view, bool clearPreview = true, bool forceCompilation = false);
void handleTextViewClosed(KTextEditor::View *view, bool wasActiveView);
void handleDocumentOpened(KileDocument::TextInfo *info);
void handleProjectOpened(KileProject *project);
void handleProjectItemAdded(KileProject *project, KileProjectItem *item);
void handleProjectItemRemoved(KileProject *project, KileProjectItem *item);
void handleDocumentSavedAs(KTextEditor::View*, KileDocument::TextInfo*);
void handleSpawnedChildTool(KileTool::Base *parent, KileTool::Base *child);
void previewForCurrentDocumentActionTriggered(bool b);
void livePreviewToolActionTriggered();
private:
class PreviewInformation;
KileInfo *m_ki;
bool m_bootUpMode;
QPointer m_previewStatusLed;
KToggleAction *m_previewForCurrentDocumentAction;
QAction *m_recompileLivePreviewAction;
QTimer *m_ledBlinkingTimer, *m_documentChangedTimer;
QHash m_runningPathToPreviewPathHash;
QHash m_runningPreviewPathToPathHash;
QString m_runningPreviewFile;
KileDocument::LaTeXInfo *m_runningLaTeXInfo;
KTextEditor::View *m_runningTextView;
KileProject *m_runningProject;
PreviewInformation *m_runningPreviewInformation;
QHash m_runningTextHash;
PreviewInformation *m_shownPreviewInformation;
QHash m_latexInfoToPreviewInformationHash;
QHash m_projectToPreviewInformationHash;
PreviewInformation *m_masterDocumentPreviewInformation;
// all the members required to handle tool actions for live preview
QHash m_livePreviewToolToActionHash;
QHash m_actionToLivePreviewToolHash;
QActionGroup *m_livePreviewToolActionGroup;
QLinkedList m_livePreviewToolActionList;
PreviewInformation* findPreviewInformation(KileDocument::TextInfo *textInfo, KileProject* *locatedProject = Q_NULLPTR,
LivePreviewUserStatusHandler* *userStatusHandler = Q_NULLPTR,
LaTeXOutputHandler* *latexOutputHandler = Q_NULLPTR);
bool isCurrentDocumentOrProject(KTextEditor::Document *doc);
void updatePreviewInformationAfterCompilationFinished();
void displayErrorMessage(const QString &text, bool clearFirst = false);
void createActions(KActionCollection *ac);
void populateViewerControlToolBar();
void synchronizeViewWithCursor(KileDocument::TextInfo *info, KTextEditor::View *view,
const KTextEditor::Cursor& newPosition,
bool calledFromCursorPositionChange = false);
void stopAndClearPreview();
void showPreviewDisabled();
void showPreviewRunning();
void showPreviewFailed();
void showPreviewSuccessful();
void showPreviewOutOfDate();
void stopLivePreview();
void clearLivePreview();
void deleteAllLivePreviewInformation();
void handleProjectItemAdditionOrRemoval(KileProject *project, KileProjectItem *item);
void fillTextHashForMasterDocument(QHash &textHash);
void disablePreview();
void clearRunningLivePreviewInformation();
void updateLivePreviewToolActions(LivePreviewUserStatusHandler *statusHandler);
void setLivePreviewToolActionsEnabled(bool b);
bool ensureDocumentIsOpenInViewer(PreviewInformation *previewInformation, bool *hadToOpen = Q_NULLPTR);
void reloadDocumentInViewer();
};
}
#endif
diff --git a/src/widgets/projectview.cpp b/src/widgets/projectview.cpp
index 3e7bca1e..9a4e93cc 100644
--- a/src/widgets/projectview.cpp
+++ b/src/widgets/projectview.cpp
@@ -1,910 +1,896 @@
/****************************************************************************************
begin : Tue Aug 12 2003
copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net)
2006 - 2010 by Michel Ludwig (michel.ludwig@kdemail.net)
****************************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "widgets/projectview.h"
#include
#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include "kileinfo.h"
#include "documentinfo.h"
#include "kiledocmanager.h"
#include
#include
const int KPV_ID_OPEN = 0, KPV_ID_SAVE = 1, KPV_ID_CLOSE = 2,
KPV_ID_OPTIONS = 3, KPV_ID_ADD = 4, KPV_ID_REMOVE = 5,
KPV_ID_BUILDTREE = 6, KPV_ID_ARCHIVE = 7, KPV_ID_ADDFILES = 8,
KPV_ID_INCLUDE = 9, KPV_ID_OPENWITH = 10, KPV_ID_OPENALLFILES = 11;
namespace KileWidget {
/*
* ProjectViewItem
*/
ProjectViewItem::ProjectViewItem(QTreeWidget *parent, KileProjectItem *item, bool ar)
: QTreeWidgetItem(parent, QStringList(item->url().fileName())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item)
{
setArchiveState(ar);
}
ProjectViewItem::ProjectViewItem(QTreeWidget *parent, QTreeWidgetItem *after, KileProjectItem *item, bool ar)
: QTreeWidgetItem(parent, after), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item)
{
setText(0, item->url().fileName());
setArchiveState(ar);
}
ProjectViewItem::ProjectViewItem(QTreeWidgetItem *parent, KileProjectItem *item, bool ar)
: QTreeWidgetItem(parent, QStringList(item->url().fileName())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(item)
{
setArchiveState(ar);
}
//use this to create folders
ProjectViewItem::ProjectViewItem(QTreeWidgetItem *parent, const QString& name)
: QTreeWidgetItem(parent, QStringList(name)), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR)
{
}
//use this to create non-project files
ProjectViewItem::ProjectViewItem(QTreeWidget *parent, const QString& name)
: QTreeWidgetItem(parent, QStringList(name)), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR)
{
}
ProjectViewItem::ProjectViewItem(QTreeWidget *parent, const KileProject *project)
: QTreeWidgetItem(parent, QStringList(project->name())), m_docinfo(Q_NULLPTR), m_folder(-1), m_projectItem(Q_NULLPTR)
{
}
ProjectViewItem::~ProjectViewItem()
{
KILE_DEBUG_MAIN << "DELETING PROJVIEWITEM " << m_url.fileName();
}
KileProjectItem* ProjectViewItem::projectItem()
{
return m_projectItem;
}
ProjectViewItem* ProjectViewItem::parent()
{
return dynamic_cast(QTreeWidgetItem::parent());
}
ProjectViewItem* ProjectViewItem::firstChild()
{
return dynamic_cast(QTreeWidgetItem::child(0));
}
void ProjectViewItem::setInfo(KileDocument::Info *docinfo)
{
m_docinfo = docinfo;
}
KileDocument::Info* ProjectViewItem::getInfo()
{
return m_docinfo;
}
void ProjectViewItem::setType(KileType::ProjectView type)
{
m_type = type;
}
KileType::ProjectView ProjectViewItem::type() const
{
return m_type;
}
void ProjectViewItem::urlChanged(const QUrl &url)
{
// don't allow empty URLs
if(!url.isEmpty()) {
setURL(url);
setText(0, url.fileName());
}
}
void ProjectViewItem::nameChanged(const QString & name)
{
setText(0, name);
}
void ProjectViewItem::isrootChanged(bool isroot)
{
KILE_DEBUG_MAIN << "SLOT isrootChanged " << text(0) << " to " << isroot;
if(isroot) {
setIcon(0, QIcon::fromTheme("masteritem"));
}
else {
if(m_projectItem && m_projectItem->type() == KileProjectItem::ProjectFile) {
setIcon(0, QIcon::fromTheme("kile"));
}
else if(m_projectItem && m_projectItem->type() == KileProjectItem::Bibliography) {
setIcon(0, QIcon::fromTheme("viewbib"));
}
else if(type() == KileType::ProjectItem) {
setIcon(0, QIcon::fromTheme("projectitem"));
}
else {
setIcon(0, QIcon::fromTheme("file"));
}
}
}
void ProjectViewItem::slotURLChanged(KileDocument::Info*, const QUrl &url)
{
urlChanged(url);
}
bool ProjectViewItem::operator<(const QTreeWidgetItem& other) const
{
try {
const ProjectViewItem& otherItem = dynamic_cast(other);
// order in the tree:
// - first, root items without container (sorted in ascending order)
// - then, container items in fixed order (images, packages, other, projectfile)
if(otherItem.type() == KileType::Folder) {
if(type() != KileType::Folder) {
return true;
}
else {
// 'm_folder' is set to a type from 'KileProject::Type'
// we want: Image < Package < Other < ProjectFile
switch(m_folder) {
case KileProjectItem::Image:
return true;
case KileProjectItem::Package:
return (otherItem.m_folder == KileProjectItem::Image) ? false : true;
case KileProjectItem::Other:
return (otherItem.m_folder == KileProjectItem::Image
|| otherItem.m_folder == KileProjectItem::Package) ? false : true;
case KileProjectItem::ProjectFile:
return false;
default: // dummy
return false;
}
}
}
else if(type() == KileType::Folder) {
return false;
}
else {
return QTreeWidgetItem::operator<(other);
}
}
catch(std::bad_cast&) {
return QTreeWidgetItem::operator<(other);
}
}
void ProjectViewItem::setURL(const QUrl &url)
{
m_url = url;
}
const QUrl &ProjectViewItem::url()
{
return m_url;
}
void ProjectViewItem::setArchiveState(bool ar)
{
setText(1, ar ? "*" : "");
}
void ProjectViewItem::setFolder(int folder)
{
m_folder = folder;
}
int ProjectViewItem::folder() const
{
return m_folder;
}
/*
* ProjectView
*/
ProjectView::ProjectView(QWidget *parent, KileInfo *ki) : QTreeWidget(parent), m_ki(ki), m_nProjects(0)
{
setColumnCount(2);
QStringList labelList;
labelList << i18n("Files & Projects") << i18n("Include in Archive");
setHeaderLabels(labelList);
setColumnWidth(1, 10);
setFocusPolicy(Qt::ClickFocus);
header()->hide();
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setRootIsDecorated(true);
setAllColumnsShowFocus(true);
setSelectionMode(QTreeWidget::SingleSelection);
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(slotClicked(QTreeWidgetItem*)));
setAcceptDrops(true);
}
void ProjectView::slotClicked(QTreeWidgetItem *item)
{
if(!item) {
item = currentItem();
}
ProjectViewItem *itm = static_cast(item);
if(itm) {
if(itm->type() == KileType::File) {
emit(fileSelected(itm->url()));
}
else if(itm->type() == KileType::ProjectItem) {
emit(fileSelected(itm->projectItem()));
}
else if(itm->type() != KileType::Folder) {
// don't open project configuration files (*.kilepr)
if(itm->url().toLocalFile().right(7) != ".kilepr") {
//determine mimeType and open file with preferred application
QMimeDatabase db;
QMimeType pMime = db.mimeTypeForUrl(itm->url());
if(pMime.name().startsWith(QLatin1String("text/"))) {
emit(fileSelected(itm->url()));
}
else {
KRun::runUrl(itm->url(), pMime.name(), this, KRun::RunFlags());
}
}
}
clearSelection();
}
}
void ProjectView::slotFile(int id)
{
ProjectViewItem *item = dynamic_cast(currentItem());
if(item) {
if(item->type() == KileType::File) {
switch(id) {
case KPV_ID_OPEN:
emit(fileSelected(item->url()));
break;
case KPV_ID_SAVE:
emit(saveURL(item->url()));
break;
case KPV_ID_ADD:
emit(addToProject(item->url()));
break;
case KPV_ID_CLOSE:
emit(closeURL(item->url()));
return; //don't access "item" later on
default:
break;
}
}
}
}
void ProjectView::slotProjectItem(int id)
{
ProjectViewItem *item = dynamic_cast(currentItem());
if(item) {
if(item->type() == KileType::ProjectItem || item->type() == KileType::ProjectExtra) {
switch(id) {
case KPV_ID_OPEN:
emit(fileSelected(item->projectItem()));
break;
case KPV_ID_SAVE:
emit(saveURL(item->url()));
break;
case KPV_ID_REMOVE:
emit(removeFromProject(item->projectItem()));
break;
case KPV_ID_INCLUDE :
if(item->text(1) == "*") {
item->setText(1, "");
}
else {
item->setText(1, "*");
}
emit(toggleArchive(item->projectItem()));
break;
case KPV_ID_CLOSE:
emit(closeURL(item->url()));
break; //we can access "item" later as it isn't deleted
case KPV_ID_OPENWITH:
KRun::displayOpenWithDialog(QList() << item->url(), this);
break;
default:
break;
}
}
}
}
void ProjectView::slotProject(int id)
{
ProjectViewItem *item = dynamic_cast(currentItem());
if(item) {
if(item->type() == KileType::Project) {
switch(id) {
case KPV_ID_BUILDTREE:
emit(buildProjectTree(item->url()));
break;
case KPV_ID_OPTIONS:
emit(projectOptions(item->url()));
break;
case KPV_ID_CLOSE:
emit(closeProject(item->url()));
return; //don't access "item" later on
case KPV_ID_ARCHIVE:
emit(projectArchive(item->url()));
break;
case KPV_ID_ADDFILES:
emit(addFiles(item->url()));
break;
case KPV_ID_OPENALLFILES:
emit(openAllFiles(item->url()));
break;
default:
break;
}
}
}
}
void ProjectView::slotRun(int id)
{
ProjectViewItem *itm = dynamic_cast(currentItem());
if(!itm) {
return;
}
if(id == 0) {
KRun::displayOpenWithDialog(QList() << itm->url(), this);
}
else {
KRun::runService(*m_offerList[id-1], QList() << itm->url(), this);
}
itm->setSelected(false);
}
void ProjectView::makeTheConnection(ProjectViewItem *item, KileDocument::TextInfo *textInfo)
{
KILE_DEBUG_MAIN << "\tmakeTheConnection " << item->text(0);
if (item->type() == KileType::Project) {
KileProject *project = m_ki->docManager()->projectFor(item->url());
if (!project) {
qWarning() << "makeTheConnection COULD NOT FIND AN PROJECT OBJECT FOR " << item->url().toLocalFile();
}
else {
connect(project, SIGNAL(nameChanged(QString)), item, SLOT(nameChanged(QString)));
}
}
else {
if(!textInfo) {
textInfo = m_ki->docManager()->textInfoFor(item->url().toLocalFile());
if(!textInfo) {
KILE_DEBUG_MAIN << "\tmakeTheConnection COULD NOT FIND A DOCINFO";
return;
}
}
item->setInfo(textInfo);
connect(textInfo, SIGNAL(urlChanged(KileDocument::Info*,QUrl)), item, SLOT(slotURLChanged(KileDocument::Info*,QUrl)));
connect(textInfo, SIGNAL(isrootChanged(bool)), item, SLOT(isrootChanged(bool)));
//set the pixmap
item->isrootChanged(textInfo->isLaTeXRoot());
}
}
ProjectViewItem* ProjectView::folder(const KileProjectItem *pi, ProjectViewItem *item)
{
ProjectViewItem *parent = parentFor(pi, item);
if(!parent) {
qCritical() << "no parent for " << pi->url().toLocalFile();
return Q_NULLPTR;
}
// we have already found the parent folder
if(parent->type() == KileType::Folder) {
return parent;
}
// we are looking at the children, if there is an existing folder for this type
ProjectViewItem *folder;
// determine the foldername for this type
QString foldername;
switch(pi->type()) {
case (KileProjectItem::ProjectFile):
foldername = i18n("Project File");
break;
case (KileProjectItem::Package):
foldername = i18n("Packages");
break;
case (KileProjectItem::Image):
foldername = i18n("Images");
break;
case (KileProjectItem::Bibliography):
foldername = i18n("Bibliography");
break;
case (KileProjectItem::Other):
default :
foldername = i18n("Other");
break;
}
// if there already a folder for this type on this level?
bool found = false;
QTreeWidgetItemIterator it(parent);
++it; // skip 'parent'
while(*it) {
folder = dynamic_cast(*it);
if(folder && folder->text(0) == foldername) {
found = true;
break;
}
++it;
}
// if no folder was found, we must create a new one
if(!found) {
folder = new ProjectViewItem(parent, foldername);
KILE_DEBUG_MAIN << "new folder: parent=" << parent->url().url()
<< ", foldername=" << foldername;
folder->setFolder(pi->type());
folder->setType(KileType::Folder);
}
return folder;
}
void ProjectView::add(const KileProject *project)
{
ProjectViewItem *parent = new ProjectViewItem(this, project);
parent->setType(KileType::Project);
parent->setURL(project->url());
parent->setExpanded(true);
parent->setIcon(0, QIcon::fromTheme("relation"));
makeTheConnection(parent);
//ProjectViewItem *nonsrc = new ProjectViewItem(parent, i18n("non-source"));
//parent->setNonSrc(nonsrc);
refreshProjectTree(project);
++m_nProjects;
}
ProjectViewItem* ProjectView::projectViewItemFor(const QUrl &url)
{
ProjectViewItem *item = Q_NULLPTR;
//find project view item
QTreeWidgetItemIterator it(this);
while(*it) {
item = dynamic_cast(*it);
if(item && (item->type() == KileType::Project) && (item->url() == url)) {
break;
}
++it;
}
return item;
}
ProjectViewItem* ProjectView::itemFor(const QUrl &url)
{
ProjectViewItem *item = Q_NULLPTR;
QTreeWidgetItemIterator it(this);
while(*it) {
item = static_cast(*it);
if (item->url() == url) {
break;
}
++it;
}
return item;
}
ProjectViewItem* ProjectView::parentFor(const KileProjectItem *projitem, ProjectViewItem *projvi)
{
//find parent projectviewitem of projitem
KileProjectItem *parpi = projitem->parent();
ProjectViewItem *parpvi = projvi, *vi;
if (parpi) {
//find parent viewitem that has an URL parpi->url()
QTreeWidgetItemIterator it(projvi);
KILE_DEBUG_MAIN << "\tlooking for " << parpi->url().toLocalFile();
while(*it) {
vi = static_cast(*it);
KILE_DEBUG_MAIN << "\t\t" << vi->url().toLocalFile();
if (vi->url() == parpi->url()) {
parpvi = vi;
KILE_DEBUG_MAIN << "\t\tfound" <type();
QTreeWidgetItemIterator it(projvi);
++it; // skip projvi
while(*it) {
ProjectViewItem *child = dynamic_cast(*it);
if(child && (child->type() == KileType::Folder) && (child->folder() == projitem->type())) {
KILE_DEBUG_MAIN << "\t\tfound";
parpvi = child;
break;
}
++it;
}
}
return (!parpvi) ? projvi : parpvi;
}
ProjectViewItem* ProjectView::add(KileProjectItem *projitem, ProjectViewItem *projvi /* = Q_NULLPTR */)
{
KILE_DEBUG_MAIN << "\tprojectitem=" << projitem->path()
<< " projvi=" << projvi;
const KileProject *project = projitem->project();
if (!projvi) {
projvi = projectViewItemFor(project->url());
}
KILE_DEBUG_MAIN << "\tparent projectviewitem " << projvi->url().fileName();
ProjectViewItem *item = Q_NULLPTR, *parent = Q_NULLPTR;
switch (projitem->type()) {
case (KileProjectItem::Source):
item = new ProjectViewItem(projvi, projitem);
item->setType(KileType::ProjectItem);
item->setIcon(0, QIcon::fromTheme("projectitem"));
break;
case (KileProjectItem::Package):
parent = folder(projitem, projvi);
item = new ProjectViewItem(parent, projitem);
item->setType(KileType::ProjectItem);
item->setIcon(0, QIcon::fromTheme("projectitem"));
break;
default:
parent = folder(projitem, projvi);
item = new ProjectViewItem(parent, projitem);
item->setType(KileType::ProjectExtra);
if(projitem->type() == KileProjectItem::ProjectFile) {
item->setIcon(0, QIcon::fromTheme("kile"));
}
else if(projitem->type() == KileProjectItem::Bibliography) {
item->setIcon(0, QIcon::fromTheme("viewbib"));
}
else {
item->setIcon(0, QIcon::fromTheme("file"));
}
break;
}
item->setArchiveState(projitem->archive());
item->setURL(projitem->url());
makeTheConnection(item, projitem->getInfo());
projvi->sortChildren(0, Qt::AscendingOrder);
// seems to be necessary to get a correct refreh (Qt 4.4.3)
bool expanded = projvi->isExpanded();
projvi->setExpanded(!expanded);
projvi->setExpanded(expanded);
return item;
}
void ProjectView::addTree(KileProjectItem *projitem, ProjectViewItem *projvi)
{
KILE_DEBUG_MAIN << "projitem=" << projitem
<< "projvi=" << projvi;
ProjectViewItem * item = add(projitem, projvi);
if(projitem->firstChild()) {
addTree(projitem->firstChild(), item);
}
if (projitem->sibling()) {
addTree(projitem->sibling(), projvi);
}
}
void ProjectView::refreshProjectTree(const KileProject *project)
{
KILE_DEBUG_MAIN << "\tProjectView::refreshProjectTree(" << project->name() << ")";
ProjectViewItem *parent= projectViewItemFor(project->url());
//clean the tree
if(parent) {
KILE_DEBUG_MAIN << "\tusing parent projectviewitem " << parent->url().fileName();
parent->setFolder(-1);
QList children = parent->takeChildren();
for(QList::iterator it = children.begin();
it != children.end(); ++it) {
delete(*it);
}
}
else {
return;
}
//create the non-sources dir
//ProjectViewItem *nonsrc = new ProjectViewItem(parent, i18n("non-sources"));
//parent->setNonSrc(nonsrc);
QList list = project->rootItems();
for(QList::iterator it = list.begin(); it != list.end(); ++it) {
addTree(*it, parent);
}
parent->sortChildren(0, Qt::AscendingOrder);
// seems to be necessary to get a correct refreh (Qt 4.4.3)
bool expanded = parent->isExpanded();
parent->setExpanded(!expanded);
parent->setExpanded(expanded);
}
void ProjectView::add(const QUrl &url)
{
KILE_DEBUG_MAIN << "\tProjectView::adding item " << url.toLocalFile();
//check if file is already present
QTreeWidgetItemIterator it(this);
ProjectViewItem *item;
while(*it) {
item = static_cast(*it);
if((item->type() != KileType::Project) && (item->url() == url)) {
return;
}
++it;
}
item = new ProjectViewItem(this, url.fileName());
item->setType(KileType::File);
item->setURL(url);
makeTheConnection(item);
}
void ProjectView::remove(const KileProject *project)
{
for(int i = 0; i < topLevelItemCount(); ++i) {
ProjectViewItem *item = static_cast(topLevelItem(i));
if(item->url() == project->url()) {
item->setParent(Q_NULLPTR);
delete item;
--m_nProjects;
break;
}
}
}
/**
* Removes a file from the projectview, does not remove project-items. Only files without a project.
**/
void ProjectView::remove(const QUrl &url)
{
for(int i = 0; i < topLevelItemCount(); ++i) {
ProjectViewItem *item = dynamic_cast(topLevelItem(i));
if(item && (item->type() == KileType::File) && (item->url() == url)) {
item->setParent(Q_NULLPTR);
delete item;
break;
}
}
}
void ProjectView::removeItem(const KileProjectItem *projitem, bool open)
{
QTreeWidgetItemIterator it(this);
ProjectViewItem *item;
while(*it) {
item = dynamic_cast(*it);
if(item && (item->type() == KileType::ProjectItem) && (item->projectItem() == projitem)) {
KILE_DEBUG_MAIN << "removing projectviewitem";
static_cast(item->parent())->removeChild(item);
delete item;
}
++it;
}
if(open) {
item = new ProjectViewItem(this, projitem->url().fileName());
item->setType(KileType::File);
item->setURL(projitem->url());
makeTheConnection(item);
}
}
void ProjectView::contextMenuEvent(QContextMenuEvent *event)
{
- QSignalMapper signalMapper, serviceSignalMapper;
QMenu popup;
QAction *action = Q_NULLPTR;
QTreeWidgetItem* treeWidgetItem = itemAt(event->pos());
if(!treeWidgetItem) {
return;
}
ProjectViewItem *projectViewItem = dynamic_cast(treeWidgetItem);
if(!projectViewItem) {
return;
}
if(projectViewItem->type() == KileType::Folder) {
return;
}
bool insertsep = false;
bool isKilePrFile = false;
if(projectViewItem->type() != KileType::Project && projectViewItem->projectItem()
&& projectViewItem->projectItem()->project()) {
isKilePrFile = projectViewItem->projectItem()->project()->url() == projectViewItem->url();
}
if(projectViewItem->type() == KileType::ProjectExtra && !isKilePrFile) {
QMenu *servicesMenu = popup.addMenu(QIcon::fromTheme("fork"), i18n("&Open With"));
- connect(&serviceSignalMapper, SIGNAL(mapped(int)), this, SLOT(slotRun(int)));
QMimeDatabase db;
m_offerList = KMimeTypeTrader::self()->query(db.mimeTypeForUrl(projectViewItem->url()).name(), "Application");
for (int i = 0; i < m_offerList.count(); ++i) {
action = new QAction(servicesMenu);
action->setIcon(QIcon::fromTheme(m_offerList[i]->icon()));
action->setText(m_offerList[i]->name());
- connect(action, SIGNAL(triggered()), &serviceSignalMapper, SLOT(map()));
- serviceSignalMapper.setMapping(action, i + 1);
+ connect(action, &QAction::triggered, this, [this, i] { slotRun(i + 1); });
servicesMenu->addAction(action);
}
servicesMenu->addSeparator();
- action = servicesMenu->addAction(i18n("Other..."), &serviceSignalMapper, SLOT(map()));
- serviceSignalMapper.setMapping(action, 0);
+ servicesMenu->addAction(i18n("Other..."), this, [this] { slotRun(0); });
insertsep = true;
}
if (projectViewItem->type() == KileType::File || projectViewItem->type() == KileType::ProjectItem) {
if(!m_ki->isOpen(projectViewItem->url())) {
- action = popup.addAction(QIcon::fromTheme("document-open"), i18n("&Open"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_OPEN);
+ popup.addAction(QIcon::fromTheme("document-open"), i18n("&Open"), this, [this] { slotProjectItem(KPV_ID_OPEN); });
}
else {
- action = popup.addAction(QIcon::fromTheme("document-save"), i18n("&Save"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_SAVE);
+ popup.addAction(QIcon::fromTheme("document-save"), i18n("&Save"), this, [this] { slotProjectItem(KPV_ID_SAVE); });
}
insertsep = true;
}
if(projectViewItem->type() == KileType::File) {
if(m_nProjects > 0) {
if(insertsep) {
popup.addSeparator();
}
- action = popup.addAction(QIcon::fromTheme("project_add"), i18n("&Add to Project"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_ADD);
+ popup.addAction(QIcon::fromTheme("project_add"), i18n("&Add to Project"), this, [this] { slotProjectItem(KPV_ID_ADD); });
insertsep = true;
}
- connect(&signalMapper, SIGNAL(mapped(int)), this, SLOT(slotFile(int)));
}
else if(projectViewItem->type() == KileType::ProjectItem || projectViewItem->type() == KileType::ProjectExtra) {
KileProjectItem *pi = projectViewItem->projectItem();
if(pi) {
if(insertsep) {
popup.addSeparator();
}
- action = popup.addAction(i18n("&Include in Archive"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_INCLUDE);
+ action = popup.addAction(i18n("&Include in Archive"), this, [this] { slotProjectItem(KPV_ID_INCLUDE); });
action->setCheckable(true);
action->setChecked(pi->archive());
insertsep = true;
}
if(!isKilePrFile) {
if(insertsep) {
popup.addSeparator();
}
- action = popup.addAction(QIcon::fromTheme("project_remove"),i18n("&Remove From Project"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_REMOVE);
+ popup.addAction(QIcon::fromTheme("project_remove"),i18n("&Remove From Project"), this, [this] { slotProjectItem(KPV_ID_REMOVE); });
insertsep = true;
}
- connect(&signalMapper, SIGNAL(mapped(int)), this, SLOT(slotProjectItem(int)));
}
else if(projectViewItem->type() == KileType::Project) {
if(insertsep) {
popup.addSeparator();
}
- action = popup.addAction(i18n("A&dd Files..."), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_ADDFILES);
+ popup.addAction(i18n("A&dd Files..."), this, [this] { slotProject(KPV_ID_ADDFILES); });
popup.addSeparator();
- action = popup.addAction(i18n("Open All &Project Files"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_OPENALLFILES);
+ popup.addAction(i18n("Open All &Project Files"), this, [this] { slotProject(KPV_ID_OPENALLFILES); });
popup.addSeparator();
- action = popup.addAction(QIcon::fromTheme("view-refresh"),i18n("Refresh Project &Tree"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_BUILDTREE);
- action = popup.addAction(QIcon::fromTheme("configure"), i18n("Project &Options"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_OPTIONS);
- action = popup.addAction(i18n("&Archive"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_ARCHIVE);
- connect(&signalMapper, SIGNAL(mapped(int)), this, SLOT(slotProject(int)));
+ popup.addAction(QIcon::fromTheme("view-refresh"),i18n("Refresh Project &Tree"), this, [this] { slotProject(KPV_ID_BUILDTREE); });
+ popup.addAction(QIcon::fromTheme("configure"), i18n("Project &Options"), this, [this] { slotProject(KPV_ID_OPTIONS); });
+ popup.addAction(i18n("&Archive"), this, [this] { slotProject(KPV_ID_ARCHIVE); });
insertsep = true;
}
if((projectViewItem->type() == KileType::File) || (projectViewItem->type() == KileType::ProjectItem)
|| (projectViewItem->type()== KileType::Project)) {
if(insertsep) {
popup.addSeparator();
}
- action = popup.addAction(QIcon::fromTheme("view-close"), i18n("&Close"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, KPV_ID_CLOSE);
+ if(projectViewItem->type() == KileType::Project) {
+ popup.addAction(QIcon::fromTheme("view-close"), i18n("&Close"), this, [this] { slotProject(KPV_ID_CLOSE); });
+ }
+ else {
+ popup.addAction(QIcon::fromTheme("view-close"), i18n("&Close"), this, [this] { slotProjectItem(KPV_ID_CLOSE); });
+ }
}
popup.exec(event->globalPos());
m_offerList.clear();
}
void ProjectView::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasUrls()) { // only accept URL drags
event->acceptProposedAction();
}
}
void ProjectView::dragMoveEvent(QDragMoveEvent *event)
{
if(event->mimeData()->hasUrls()) { // only accept URL drags
event->acceptProposedAction();
}
}
void ProjectView::dropEvent(QDropEvent *event)
{
m_ki->docManager()->openDroppedURLs(event);
}
}
diff --git a/src/widgets/structurewidget.cpp b/src/widgets/structurewidget.cpp
index 39e7b7ac..6170d063 100644
--- a/src/widgets/structurewidget.cpp
+++ b/src/widgets/structurewidget.cpp
@@ -1,1092 +1,1038 @@
/*************************************************************************************************
Copyright (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net
2005-2007 by Holger Danielsson (holger.danielsson@versanet.de)
2008-2016 by Michel Ludwig (michel.ludwig@kdemail.net)
*************************************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
// 2005-11-02: dani
// - cleaning up source (local variables etc.)
// - added different QToolTips for each item
// - add more types of KilelistViewItems
// - KileStruct::Sect and KileStruct::BeginFloat will remember assigned labels,
// which are displayed as QToolTips, if these labels are defined in the
// same or the next line
// - Caption for type KileStruct::BeginFloat are displayed in the title
// of this item
// - \includegraphics and float environment items are displayed
// - if an item has a companion label, you can use the context menu (right mouse)
// to insert this label as reference, as a page reference or only the keyword
// into the text or copy it to the clipboard.
// - graphics files have also a context menu to open them with a special program
// 2005-12-08: dani
// - make some items like labels, bibitems, graphics and float environments
// configurable for the user
// 2005-12-16: dani
// - add listview item for undefined references
// 2007-02-15: dani
// - class StructureViewItem gets two new members to
// save the real cursor position of the command
// 2007-03-12 dani
// - use KileDocument::Extensions
// 2007-03-17 dani
// - remember how document structure is collapsed, when structure view is refreshed
// 2007-03-24: dani
// - preliminary minimal support for Beamer class
// - \begin{frame}...\end{frame} and \frame{...} are shown in the structure view
// - if a \frametitle command follows as next LaTeX command, its parameter
// is taken to replace the standard title of this entry in the structure view
// - \begin{block}...\end{block} is taken as child of a frame
// 2007-04-06 dani
// - add TODO/FIXME section to structure view
#include "widgets/structurewidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include "documentinfo.h"
#include "errorhandler.h"
#include "kileconfig.h"
#include "kiledebug.h"
#include "kiledocmanager.h"
#include "kileinfo.h"
#include "kileproject.h"
#include "kiletool_enums.h"
#include "parser/parsermanager.h"
#include "widgets/logwidget.h"
namespace KileWidget
{
////////////////////// StructureViewItem with all info //////////////////////
StructureViewItem::StructureViewItem(QTreeWidgetItem* parent, const QString &title, const QUrl &url, uint line, uint column, int type, int level, uint startline, uint startcol) :
QTreeWidgetItem(parent),
m_title(title), m_url(url), m_line(line), m_column(column), m_type(type), m_level(level),
m_startline(startline), m_startcol(startcol)
{
setItemEntry();
}
StructureViewItem::StructureViewItem(QTreeWidget* parent, const QString& label) :
QTreeWidgetItem(parent, QStringList(label)),
m_title(label), m_url(QUrl()), m_line(0), m_column(0), m_type(KileStruct::None), m_level(0)
{
setToolTip(0, i18n("Click left to jump to the line. A double click will open\n a text file or a graphics file. When a label is assigned\nto this item, it will be shown when the mouse is over\nthis item. Items for a graphics file or an assigned label\nalso offer a context menu (right mouse button)."));
}
StructureViewItem::StructureViewItem(const QString& label, QTreeWidgetItem* parent) :
QTreeWidgetItem(parent, QStringList(label)),
m_title(label), m_url(QUrl()), m_line(0), m_column(0), m_type(KileStruct::None), m_level(0)
{}
void StructureViewItem::setTitle(const QString &title)
{
m_title = title;
setItemEntry();
}
void StructureViewItem::setItemEntry()
{
setText(0, i18nc("structure view entry: title (line)", "%1 (line %2)", m_title, QString::number(m_line)));
setToolTip(0, text(0));
}
void StructureViewItem::setLabel(const QString &label)
{
m_label = label;
if(!m_label.isEmpty()) {
setToolTip(0, i18n("Label: %1", m_label));
}
}
////////////////////// StructureView tree widget //////////////////////
StructureView::StructureView(StructureWidget *stack, KileDocument::Info *docinfo) :
QTreeWidget(stack),
m_stack(stack), m_docinfo(docinfo)
{
stack->addWidget(this);
setColumnCount(1);
QStringList labelList;
labelList << i18n("Structure");
setHeaderLabels(labelList);
header()->hide();
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setAllColumnsShowFocus(true);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
//connect(this, SIGNAL(clicked(QListViewItem*)), m_stack, SLOT(slotClicked(QListViewItem*)));
connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), m_stack, SLOT(slotDoubleClicked(QTreeWidgetItem*)));
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), m_stack, SLOT(slotClicked(QTreeWidgetItem*)));
connect(m_stack, SIGNAL(configChanged()), this, SLOT(slotConfigChanged()));
init();
}
StructureView::~StructureView() {}
void StructureView::init()
{
QString title = (!m_docinfo) ? i18n("No \"structure data\" to display.") : m_docinfo->url().fileName();
m_root = new StructureViewItem(this, title);
if(m_docinfo) {
m_root->setURL(m_docinfo->url());
m_root->setExpanded(true);
m_root->setIcon(0, QIcon::fromTheme("contents"));
connect(m_docinfo, SIGNAL(foundItem(QString,uint,uint,int,int,uint,uint,QString,QString)),
this, SLOT(addItem(QString,uint,uint,int,int,uint,uint,QString,QString)));
}
m_parent[0]=m_parent[1]=m_parent[2]=m_parent[3]=m_parent[4]=m_parent[5]=m_parent[6]=m_root;
m_lastType = KileStruct::None;
m_lastSectioning = Q_NULLPTR;
m_lastFloat = Q_NULLPTR;
m_lastFrame = Q_NULLPTR;
m_lastFrameEnv = Q_NULLPTR;
m_stop = false;
m_folders.clear();
m_references.clear();
if(m_docinfo) {
m_openStructureLabels = m_docinfo->openStructureLabels();
m_openStructureReferences = m_docinfo->openStructureReferences();
m_openStructureBibitems = m_docinfo->openStructureBibitems();
m_openStructureTodo = m_docinfo->openStructureTodo();
m_showStructureLabels = m_docinfo->showStructureLabels();
}
else {
m_openStructureLabels = false;
m_openStructureReferences = false;
m_openStructureBibitems = false;
m_openStructureTodo = false;
m_showStructureLabels = false;
}
}
void StructureView::updateRoot()
{
m_root->setURL( m_docinfo->url() );
m_root->setText(0, m_docinfo->url().fileName() );
}
void StructureView::cleanUp(bool preserveState/* = true */)
{
KILE_DEBUG_MAIN << "==void StructureView::cleanUp()========";
if(preserveState) {
saveState();
}
clear();
if(m_docinfo) {
disconnect(m_docinfo, 0, this, 0);
}
init();
}
void StructureView::slotConfigChanged() {
QWidget *current = m_stack->currentWidget();
if(!current) {
return;
}
cleanUp(false);
m_stack->update(m_docinfo, true);
}
void StructureView::contextMenuEvent(QContextMenuEvent *event)
{
m_stack->viewContextMenuEvent(this, event);
}
void StructureView::saveState()
{
KILE_DEBUG_MAIN << "===void StructureView::saveState()";
m_openByTitle.clear();
m_openByLine.clear();
m_openByFolders.clear();
QTreeWidgetItemIterator it(this);
StructureViewItem *item = Q_NULLPTR;
while(*it) {
item = dynamic_cast(*it);
if(item && item->child(0)) {
//we don't accept duplicate entries in the map, remove this item alltogether
//and rely on the openByLine map instead
if(m_openByTitle.contains(item->title())) {
m_openByTitle.remove(item->title());
}
else {
m_openByTitle[item->title()] = item->isExpanded();
}
m_openByLine[item->line()] = item->isExpanded();
}
++it;
}
if(m_folders.contains("labels")) {
m_openByFolders["labels"] = m_folders["labels"]->isExpanded();
}
if(m_folders.contains("refs")) {
m_openByFolders["refs"] = m_folders["refs"]->isExpanded();
}
if(m_folders.contains("bibs")) {
m_openByFolders["bibs"] = m_folders["bibs"]->isExpanded();
}
if(m_folders.contains("todo")) {
m_openByFolders["todo"] = m_folders["todo"]->isExpanded();
}
if(m_folders.contains("fixme")) {
m_openByFolders["fixme"] = m_folders["fixme"]->isExpanded();
}
}
bool StructureView::shouldBeOpen(StructureViewItem *item, const QString & folder, int level)
{
if(!item->parent()) {
return true;
}
if(folder == "labels") {
if(m_openByFolders.contains("labels")) {
return m_openByFolders["labels"];
}
else {
return m_openStructureLabels;
}
}
else if(folder == "refs") {
if(m_openByFolders.contains("refs")) {
return m_openByFolders["refs"];
}
else {
return m_openStructureReferences;
}
}
else if(folder == "bibs") {
if(m_openByFolders.contains("bibs")) {
return m_openByFolders["bibs"];
}
else {
return m_openStructureBibitems;
}
}
else if(folder=="todo" || folder=="fixme") {
if(m_openByFolders.contains(folder)) {
return m_openByFolders[folder];
}
else {
return m_openStructureTodo;
}
}
if(m_openByTitle.contains(item->title())) {
return m_openByTitle[item->title()];
}
else if(m_openByLine.contains(item->line())) {
return m_openByLine[item->line()]; //TODO check surrounding lines as well
}
else {
return ((folder == "root") && level <= m_stack->level());
}
}
StructureViewItem* StructureView::createFolder(const QString &folder)
{
StructureViewItem *fldr = new StructureViewItem(folder);
// add it as a top-level child
m_root->insertChild(0, fldr);
fldr->setExpanded(false);
if(folder == "labels") {
fldr->setText(0, i18n("Labels"));
fldr->setIcon(0, QIcon::fromTheme("label"));
}
else if(folder == "bibs") {
fldr->setText(0, i18n("BibTeX References"));
fldr->setIcon(0, QIcon::fromTheme("viewbib"));
}
else if(folder == "refs") {
fldr->setText(0, i18n("Undefined References"));
fldr->setIcon(0, QIcon::fromTheme("dialog-error"));
}
else if(folder == "todo") {
fldr->setText(0, i18n("TODO"));
fldr->setIcon(0, QIcon::fromTheme("bookmarks"));
}
else if(folder == "fixme") {
fldr->setText(0, i18n("FIXME"));
fldr->setIcon(0, QIcon::fromTheme("bookmarks"));
}
m_folders[folder] = fldr;
return m_folders[folder];
}
StructureViewItem* StructureView::folder(const QString &folder)
{
StructureViewItem *item = m_folders[folder];
if(!item) {
item = createFolder(folder);
}
return item;
}
void StructureView::activate()
{
if(m_stack->indexOf(this) >= 0) {
m_stack->setCurrentWidget(this);
}
}
StructureViewItem *StructureView::parentFor(int lev, const QString & fldr)
{
StructureViewItem *par = Q_NULLPTR;
if(fldr == "root") {
switch(lev) {
case KileStruct::Object:
case KileStruct::File:
par = (!m_lastSectioning) ? m_root : m_lastSectioning;
break;
case 0:
case 1:
par = m_root;
break;
default:
par = m_parent[lev - 2];
break;
}
}
else {
par = folder(fldr);
}
return par;
}
////////////////////// add a new item to the tree widget //////////////////////
/* some items have a special action:
- KileStruct::Sect:
The new item is saved in m_lastSectioning, so that all following entries
can be inserted as children. \part will drop back to level 0 of the Listview,
all other sectioning commands will be children of the last sectioning item.
If a \label command follows in the same or the next line, it is assigned
to this item.
- KileStruct::BeginFloat:
The new item is saved in m_lastFloat. If a \caption command follows before
the floating environment is closed, it is inserted into the title of this item.
If a \label command follows, it is assigned to this float item.
- KileStruct::EndFloat
Reset m_lastFloat to Q_NULLPTR to close this environment. No more \caption or \label
commands are assigned to this float after this.
- KileStruct::Caption
If a float environment is opened, the caption is assigned to the float item.
A caption item has hidden attribute, so that no other action is performed and
function addItem() will return immediately.
- KileStruct::Label
If we are inside a float, this label is assigned to this environment. If the last
type was a sectioning command on the current line or the line before, the label is
assigned to this sectioning item. Assigning means that a popup menu will open,
when the mouse is over this item.
- KileStruct::BeamerBeginFrame
The new item is saved in m_lastFrameEnv. If a \frametitle command follows before
the frame environment is closed, it is inserted into the title of this item.
If a \label command follows, it is assigned to this float item.
- KileStruct::BeamerEndFrame
Reset m_lastFloatEnv to Q_NULLPTR to close this environment. No more \frametitle
or \label commands are assigned to this frame after this.
- KileStruct::BeamerBeginBlock
Inside a beamer frame this environment is taken as child of this frame
- KileStruct::BeamerFrame
The new item is saved in m_lastFrame. If a \frametitle command follows
immediately as next command, it is inserted into the title of this item.
*/
void StructureView::addItem(const QString &title, uint line, uint column, int type, int lev,
uint startline, uint startcol,
const QString &pix, const QString &fldr /* = "root" */)
{
// KILE_DEBUG_MAIN << "\t\taddItem: " << title << ", with type " << type;
if(m_stop) {
return;
}
// some types need a special action
if(type == KileStruct::Reference) {
m_references.prepend(KileReferenceData(title, line, column));
}
else if(type==KileStruct::Caption && m_lastFloat) {
QString floattitle = m_lastFloat->title();
if(floattitle == "figure" || floattitle == "table") {
m_lastFloat->setTitle(floattitle+": "+title);
}
}
else if(type == KileStruct::EndFloat) {
m_lastFloat = Q_NULLPTR;
}
else if(type == KileStruct::BeamerFrametitle) {
if(m_lastFrameEnv) {
m_lastFrameEnv->setTitle(title);
}
else if(m_lastFrame) {
m_lastFrame->setTitle(title);
}
}
else if(type == KileStruct::BeamerEndFrame) {
m_lastFrameEnv = Q_NULLPTR;
}
m_lastFrame = Q_NULLPTR;
// that's all for hidden types: we must immediately return
if(lev == KileStruct::Hidden) {
//KILE_DEBUG_MAIN << "\t\thidden item: not created";
return;
}
//KILE_DEBUG_MAIN << "\t\tcreate new item";
// check if we have to update a label before loosing this item
if(type==KileStruct::Label) {
if(m_lastFloat) {
m_lastFloat->setLabel(title);
}
else if(m_lastType == KileStruct::Sect) {
// check if this is a follow up label for the last sectioning item
if(m_lastSectioning && (m_lastLine == line-1 || m_lastLine==line)) {
m_lastSectioning->setLabel(title);
}
}
else if(m_lastType == KileStruct::BeamerBeginFrame && m_lastFrameEnv) {
m_lastFrameEnv->setLabel(title);
}
if(!m_showStructureLabels) { // if we don't want to have it displayed return here
return;
}
}
// remember current type and line for the next call of addItem()
m_lastType = type;
m_lastLine = line;
//find the parent for the new element
StructureViewItem *parentItem = (type == KileStruct::BeamerBeginBlock && m_lastFrameEnv) ? m_lastFrameEnv : parentFor(lev, fldr);
if(!parentItem) {
KMessageBox::error(m_stack->info()->mainWindow(), i18n("Cannot create a list view item: no parent found."));
return;
}
// create a new item
StructureViewItem *newChild = new StructureViewItem(parentItem, title, m_docinfo->url(), line, column, type, lev, startline, startcol);
if(!pix.isEmpty()) {
newChild->setIcon(0, QIcon::fromTheme(pix));
}
//m_stop = true;
//if the level is not greater than the defaultLevel
//open the parentItem to make this item visible
parentItem->setExpanded(shouldBeOpen(parentItem, fldr, lev));
//update the m_parent levels, such that section etc. get inserted at the correct level
//m_current = newChild;
if(lev > 0) {
m_parent[lev - 1] = newChild;
for(int l = lev; l < 7; ++l) {
m_parent[l] = newChild;
}
}
else if(lev == 0) {
m_lastSectioning = Q_NULLPTR;
for(int l = 0; l < 7; ++l) {
m_parent[l] = m_root;
}
}
// check if we have to remember the new item for setting a label or caption
if(type == KileStruct::Sect) {
m_lastSectioning = newChild;
}
else if(type == KileStruct::BeginFloat) {
m_lastFloat = newChild;
}
else if(type == KileStruct::BeamerBeginFrame) {
m_lastFrameEnv = newChild;
}
else if(type == KileStruct::BeamerFrame) {
m_lastFrame = newChild;
}
}
void StructureView::showReferences(KileInfo *ki)
{
// remove old listview item for references, if it exists
if(m_folders.contains("refs")) {
StructureViewItem *refitem = m_folders["refs"];
m_root->removeChild(refitem);
delete refitem;
m_folders.remove("refs");
}
//KILE_DEBUG_MAIN << "==void StructureView::showReferences()========";
//KILE_DEBUG_MAIN << "\tfound " << m_references.count() << " references";
if(m_references.count() == 0) {
return;
}
// read list with all labels
QStringList list = ki->allLabels();
//KILE_DEBUG_MAIN << "\tfound " << list.count() << " labels";
QMap labelmap;
for (QStringList::const_iterator itmap = list.constBegin(); itmap != list.constEnd(); ++itmap) {
labelmap[(*itmap)] = true;
}
// now check if there are unsolved references
for (QList::const_iterator it = m_references.constBegin(); it!=m_references.constEnd(); ++it) {
if(!labelmap.contains((*it).name())) {
StructureViewItem *refitem = folder("refs");
refitem->setExpanded(shouldBeOpen(refitem, "refs", 0));
new StructureViewItem(refitem, (*it).name(), m_docinfo->url(), (*it).line(), (*it).column(), KileStruct::Reference, KileStruct::NotSpecified, 0, 0);
}
}
}
////////////////////// StructureWidget: QWidgetStack //////////////////////
StructureWidget::StructureWidget(KileInfo *ki, QWidget * parent, const char* name) :
QStackedWidget(parent),
m_ki(ki),
m_docinfo(Q_NULLPTR),
m_showingContextMenu(Q_NULLPTR)
{
setObjectName(name);
KILE_DEBUG_MAIN << "==KileWidget::StructureWidget::StructureWidget()===========";
setLineWidth(0);
setMidLineWidth(0);
setContentsMargins(0, 0, 0, 0);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
m_default = new StructureView(this, Q_NULLPTR);
m_default->activate();
connect(m_ki->parserManager(), SIGNAL(documentParsingStarted()), this, SLOT(handleDocumentParsingStarted()));
connect(m_ki->parserManager(), SIGNAL(documentParsingComplete()), this, SLOT(handleDocumentParsingCompleted()));
}
StructureWidget::~StructureWidget()
{
}
int StructureWidget::level()
{
return KileConfig::defaultLevel();
}
void StructureWidget::addDocumentInfo(KileDocument::Info *docinfo)
{
StructureView *view = new StructureView(this, docinfo);
addWidget(view);
m_map.insert(docinfo, view);
}
void StructureWidget::slotClicked(QTreeWidgetItem * itm)
{
KILE_DEBUG_MAIN << "\tStructureWidget::slotClicked";
StructureViewItem *item = dynamic_cast(itm);
//return if user didn't click on an item
if(!item) {
return;
}
if(!(item->type() & KileStruct::None)) {
emit(setCursor(item->url(), item->line()-1, item->column()));
}
else if(!item->parent()) { //root item
emit(setCursor(item->url(), 0, 0));
}
}
void StructureWidget::slotDoubleClicked(QTreeWidgetItem * itm)
{
KILE_DEBUG_MAIN << "\tStructureWidget::slotDoubleClicked";
StructureViewItem *item = dynamic_cast(itm);
static QRegExp suffix("\\.[\\d\\w]*$");
if (!item) {
return;
}
KILE_DEBUG_MAIN <<"item->url() is " << item->url() << ", item->title() is " << item->title();
if(item->type() & (KileStruct::Input | KileStruct::Bibliography | KileStruct::Graphics)) {
QString fname = item->title();
if(fname.indexOf(suffix) != -1) { // check if we have a suffix, if not add standard suffixes
KILE_DEBUG_MAIN << "Suffix found: " << suffix.cap(0);
}
else {
// filename in structureview entry has no extension: this shouldn't happen anymore,
// because all have got one in function updateStruct(). But who knows?
if(item->type() == KileStruct::Input) {
fname += m_ki->extensions()->latexDocumentDefault();
}
else if(item->type() == KileStruct::Bibliography) {
fname += m_ki->extensions()->bibtexDefault();
}
else if(item->type() == KileStruct::Graphics) {
KileProjectItem *kiItem = m_ki->docManager()->itemFor(item->url());
KileProject *proj;
QString extToAdd;
bool fromProject = true;
if(kiItem && (proj = kiItem->project())) {
extToAdd = proj->defaultGraphicExt();
}
if(extToAdd.isEmpty()) {
extToAdd = KileConfig::svDefaultGraphicExt();
fromProject = false;
}
m_ki->errorHandler()->printMessage(KileTool::Info,
(fromProject ?
i18n("No extension specified for graphic file. Using .%1 from Project settings.", extToAdd) :
i18n("No extension specified for graphic file. Using .%1 from global Structure View settings.", extToAdd)),
i18n("File extension not specified"));
fname += '.' + extToAdd;
}
else {
KILE_DEBUG_MAIN << "Suffixless item with unknown type found";
}
}
if(QDir::isRelativePath(fname)) { // no absolute path
QString fn = m_ki->getCompileName();
fname= QFileInfo(fn).path() + QDir::separator() + fname;
}
QFileInfo fi(fname);
if(fi.isReadable()) {
QUrl url = QUrl::fromLocalFile(fname);
if(item->type() == KileStruct::Graphics) {
QMimeDatabase db;
QMimeType pMime = db.mimeTypeForUrl(url);
KRun::runUrl(url, pMime.name(), this, KRun::RunFlags());
}
else {
emit(fileOpen(url, QString()));
}
}
else {
QString otherFilename;
if(item->type() == KileStruct::Bibliography) {
otherFilename = m_ki->checkOtherPaths(fi.path(), fi.fileName(), KileInfo::bibinputs);
}
else if(item->type() == KileStruct::Input) {
otherFilename = m_ki->checkOtherPaths(fi.path(), fi.fileName(), KileInfo::texinputs);
}
fi.setFile(otherFilename);
if(fi.isReadable()) {
emit(fileOpen(QUrl::fromLocalFile(otherFilename), QString()));
}
else {
if(KMessageBox::warningYesNo(this, i18n("Cannot find the included file. The file does not exist, is not readable or Kile is unable to determine the correct path to it. The filename causing this error was: %1.\nDo you want to create this file?", fname), i18n("Cannot Find File"))
== KMessageBox::Yes) {
emit(fileNew(QUrl::fromLocalFile(fname)));
}
}
}
}
}
// all popup items get different id's, so that we can see, what item is activated
// - label: 1 - 6
// - sectioning: 10 - 16
// - graphics: 100ff
void StructureWidget::viewContextMenuEvent(StructureView *view, QContextMenuEvent *event)
{
KILE_DEBUG_MAIN << "\tcalled";
- QSignalMapper signalMapper;
- connect(&signalMapper, SIGNAL(mapped(int)), this, SLOT(slotPopupActivated(int)));
QMenu popup;
- QAction *action = Q_NULLPTR;
m_showingContextMenu = Q_NULLPTR;
m_popupItem = dynamic_cast(view->itemAt(event->pos()));
if(!m_popupItem) {
KILE_DEBUG_MAIN << "not a pointer to a StructureViewItem object.";
return;
}
bool hasLabel = !(m_popupItem->label().isEmpty());
if(m_popupItem->type() == KileStruct::Sect) {
if(hasLabel) {
popup.addSection(i18n("Sectioning"));
}
- action = popup.addAction(i18n("Cu&t"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningCut);
- action = popup.addAction(i18n("&Copy"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningCopy);
- action = popup.addAction(i18n("&Paste below"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningPaste);
+ popup.addAction(i18n("Cu&t"), this, [this] { slotPopupSectioning(SectioningCut); });
+ popup.addAction(i18n("&Copy"), this, [this] { slotPopupSectioning(SectioningCopy); });
+ popup.addAction(i18n("&Paste below"), this, [this] { slotPopupSectioning(SectioningPaste); });
popup.addSeparator();
- action = popup.addAction(i18n("&Select"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningSelect);
- action = popup.addAction(i18n("&Delete"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningDelete);
+ popup.addAction(i18n("&Select"), this, [this] { slotPopupSectioning(SectioningSelect); });
+ popup.addAction(i18n("&Delete"), this, [this] { slotPopupSectioning(SectioningDelete); });
popup.addSeparator();
- action = popup.addAction(i18n("C&omment"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningComment);
+ popup.addAction(i18n("C&omment"), this, [this] { slotPopupSectioning(SectioningComment); });
popup.addSeparator();
- action = popup.addAction(i18n("Run QuickPreview"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningPreview);
+ popup.addAction(i18n("Run QuickPreview"), this, [this] { slotPopupSectioning(SectioningPreview); });
}
else if(m_popupItem->type() == KileStruct::Graphics) {
m_popupInfo = m_popupItem->title();
if(!QDir::isAbsolutePath(m_popupInfo)) {
QString fn = m_ki->getCompileName();
m_popupInfo = QFileInfo(fn).path() + '/' + m_popupInfo;
}
QFileInfo fi(m_popupInfo);
if(fi.isReadable()) {
QUrl url;
url.setPath(m_popupInfo);
QMimeDatabase db;
m_offerList = KMimeTypeTrader::self()->query(db.mimeTypeForUrl(url).name(), "Application");
for(int i = 0; i < m_offerList.count(); ++i) {
- action = popup.addAction(QIcon::fromTheme(m_offerList[i]->icon()), m_offerList[i]->name(),
- &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, i + SectioningGraphicsOfferlist);
+ popup.addAction(QIcon::fromTheme(m_offerList[i]->icon()), m_offerList[i]->name(),
+ this, [this, i] { slotPopupGraphics(i + SectioningGraphicsOfferlist); });
}
popup.addSeparator();
- action = popup.addAction(i18n("Other..."), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, SectioningGraphicsOther);
+ popup.addAction(i18n("Other..."), this, [this] { slotPopupGraphics(SectioningGraphicsOther); });
}
}
if(hasLabel) {
popup.addSection(i18n("Insert Label"));
- action = popup.addAction(i18n("As &reference"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 1);
- action = popup.addAction(i18n("As &page reference"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 2);
- action = popup.addAction(i18n("Only the &label"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 3);
+ popup.addAction(i18n("As &reference"), this, [this] { emit(sendText("\\ref{" + m_popupItem->label() + '}')); });
+ popup.addAction(i18n("As &page reference"), this, [this] { emit(sendText("\\pageref{" + m_popupItem->label() + '}')); });
+ popup.addAction(i18n("Only the &label"), this, [this] { emit(sendText(m_popupItem->label())); });
popup.addSeparator();
popup.addSection(i18n("Copy Label to Clipboard"));
- action = popup.addAction(i18n("As reference"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 4);
- action = popup.addAction(i18n("As page reference"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 5);
- action = popup.addAction(i18n("Only the label"), &signalMapper, SLOT(map()));
- signalMapper.setMapping(action, 6);
+ popup.addAction(i18n("As reference"), this, [this] { QApplication::clipboard()->setText("\\ref{" + m_popupItem->label() + '}'); });
+ popup.addAction(i18n("As page reference"), this, [this] { QApplication::clipboard()->setText("\\pageref{" + m_popupItem->label() + '}'); });
+ popup.addAction(i18n("Only the label"), this, [this] { QApplication::clipboard()->setText(m_popupItem->label()); });
}
if(!popup.isEmpty()) {
m_showingContextMenu = &popup;
popup.exec(event->globalPos());
m_showingContextMenu = Q_NULLPTR;
}
}
-void StructureWidget::slotPopupActivated(int id)
-{
- KILE_DEBUG_MAIN << "id: " << id;
- if(id >= 1 && id <= 6) {
- slotPopupLabel(id);
- }
- else if(id >= SectioningCut && id <= SectioningPreview) {
- slotPopupSectioning(id);
- }
- else if(id >= SectioningGraphicsOther && id <= SectioningGraphicsOfferlist + m_offerList.count()) {
- slotPopupGraphics(id);
- }
-}
-
-// id's 1..6 (already checked)
-void StructureWidget::slotPopupLabel(int id)
-{
- KILE_DEBUG_MAIN << "\tStructureWidget::slotPopupLabel (" << id << ")"<< endl;
-
- QString s = m_popupItem->label();
- if(id == 1 || id == 4) {
- s = "\\ref{" + s + '}';
- }
- else if(id == 2 || id == 5) {
- s = "\\pageref{" + s + '}';
- }
-
- if(id <= 3) {
- emit(sendText(s));
- }
- else {
- QApplication::clipboard()->setText(s);
- }
-}
-
// id's 10..16 (already checked)
void StructureWidget::slotPopupSectioning(int id)
{
KILE_DEBUG_MAIN << "\tStructureWidget::slotPopupSectioning (" << id << ")"<< endl;
if(m_popupItem->level() >= 1 && m_popupItem->level() <= 7) {
emit(sectioningPopup(m_popupItem, id));
}
}
// id's 100ff (already checked)
void StructureWidget::slotPopupGraphics(int id)
{
KILE_DEBUG_MAIN << "\tStructureWidget::slotPopupGraphics (" << id << ")"<< endl;
QUrl url;
url.setPath(m_popupInfo);
if(id == SectioningGraphicsOther) {
KRun::displayOpenWithDialog(QList() << url, this);
}
else {
KRun::runService(*m_offerList[id-SectioningGraphicsOfferlist], QList() << url, this);
}
}
StructureView* StructureWidget::viewFor(KileDocument::Info *info)
{
if(!info) {
return Q_NULLPTR;
}
if(!viewExistsFor(info)) {
m_map.insert(info, new StructureView(this, info));
}
return m_map[info];
}
bool StructureWidget::viewExistsFor(KileDocument::Info *info)
{
if(!info) {
return false;
}
else {
return m_map.contains(info);
}
}
void StructureWidget::closeDocumentInfo(KileDocument::Info *docinfo)
{
m_docinfo = Q_NULLPTR;
if(m_map.contains(docinfo)) {
StructureView *data = m_map[docinfo];
m_map.remove(docinfo);
delete data;
}
if(m_map.isEmpty()) {
m_default->activate();
}
}
void StructureWidget::clear()
{
QMap::iterator it;
QMap::iterator itend(m_map.end());
for (it = m_map.begin(); it != itend; ++it) {
if(it.value()) {
delete it.value();
}
}
m_map.clear();
m_docinfo = Q_NULLPTR;
m_default->activate();
}
void StructureWidget::updateUrl(KileDocument::Info *docinfo)
{
StructureView *view = viewFor(docinfo);
if(view) {
view->updateRoot();
}
}
void StructureWidget::update(KileDocument::Info *docinfo)
{
update(docinfo, false);
}
void StructureWidget::update(KileDocument::Info *docinfo, bool forceParsing)
{
KILE_DEBUG_MAIN << "==KileWidget::StructureWidget::update(" << docinfo << ")=============";
if(!docinfo) {
m_default->activate();
return;
}
m_docinfo = docinfo;
bool needParsing = forceParsing || m_docinfo->isDirty() || !viewExistsFor(docinfo);
//find structview-item for this docinfo
StructureView *view = viewFor(m_docinfo);
if(!view) {
m_default->activate();
return;
}
if(needParsing) { //need to reparse the doc
m_docinfo->updateStruct();
}
KILE_DEBUG_MAIN << "activating view";
view->activate();
}
void StructureWidget::updateAfterParsing(KileDocument::Info *info, const QLinkedList& items)
{
KILE_DEBUG_MAIN;
StructureView *view = viewFor(info);
if(!view) {
m_default->activate();
return;
}
int xtop = view->horizontalScrollBar()->value();
int ytop = view->verticalScrollBar()->value();
// avoid flickering when parsing
view->setUpdatesEnabled(false);
view->cleanUp();
Q_FOREACH( KileParser::StructureViewItem *item, items) {
view->addItem(item->title, item->line, item->column, item->type, item->level, item->startline, item->startcol, item->pix, item->folder);
}
view->setUpdatesEnabled(true);
view->showReferences(m_ki);
view->horizontalScrollBar()->setValue(xtop);
view->verticalScrollBar()->setValue(ytop);
}
void StructureWidget::clean(KileDocument::Info *docinfo)
{
KILE_DEBUG_MAIN << "==void StructureWidget::clean()========";
StructureView *view = viewFor(docinfo);
if(view) {
view->cleanUp();
}
}
void StructureWidget::updateReferences(KileDocument::Info *docinfo)
{
KILE_DEBUG_MAIN << "==void StructureView::updateReferences()========";
StructureView *view = viewFor(docinfo);
if(view) {
view->showReferences(m_ki);
}
}
////////////////////// StructureWidget: find sectioning //////////////////////
bool StructureWidget::findSectioning(StructureViewItem *refItem, KTextEditor::Document *doc, int row, int col, bool backwards, bool checkLevel, int §Row, int §Col)
{
KileDocument::TextInfo *docinfo = m_ki->docManager()->textInfoFor(doc);
if(!docinfo) {
return false;
}
if( checkLevel && !refItem ) { // only allow a refItem == Q_NULLPTR if checkLevel is false
return false;
}
bool found = false;
int foundRow, foundCol;
StructureView *structurelist = viewFor(docinfo);
QTreeWidgetItemIterator it(structurelist);
while(*it) {
StructureViewItem *item = dynamic_cast(*it);
if (item && item->type() == KileStruct::Sect && (!checkLevel || item->level() <= refItem->level())) {
foundRow = item->startline() - 1;
foundCol = item->startcol() - 1;
if(backwards) {
if(foundRow < row || (foundRow==row && foundCol < col)) {
sectRow = foundRow;
sectCol = foundCol;
found = true;
}
else {
return found;
}
}
else if(!backwards && (foundRow > row || (foundRow == row && foundCol > col))) {
sectRow = foundRow;
sectCol = foundCol;
return true;
}
}
++it;
}
return found;
}
void StructureWidget::handleDocumentParsingStarted()
{
setEnabled(false);
// if a context menu is showing, we better close it
// as the StructureViewItems it operates on will be deleted
if(m_showingContextMenu) {
m_showingContextMenu->close();
}
}
void StructureWidget::handleDocumentParsingCompleted()
{
setEnabled(true);
}
}
diff --git a/src/widgets/structurewidget.h b/src/widgets/structurewidget.h
index ab3d88c7..d867d1a2 100644
--- a/src/widgets/structurewidget.h
+++ b/src/widgets/structurewidget.h
@@ -1,269 +1,267 @@
/**************************************************************************************************
begin : Sun Dec 28 2003
copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net)
2005-2007 by Holger Danielsson (holger.danielsson@versanet.de)
2008-2012 by Michel Ludwig (michel.ludwig@kdemail.net)
**************************************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef STRUCTUREWIDGET_H
#define STRUCTUREWIDGET_H
#include
#include
#include
#include
#include
#include
#include
#include "documentinfo.h"
#include "parser/latexparser.h"
//2007-02-15: dani
// - class StructureViewItem not only saves the cursor position of the parameter,
// but also the real cursor position of the command
class KileInfo;
/**
* ListView items that can hold some additional information appropriate for the Structure View. The
* additional information is: line number, title string.
**/
namespace KileWidget
{
class StructureViewItem : public QTreeWidgetItem
{
public:
StructureViewItem(QTreeWidgetItem *parent, const QString &title, const QUrl &url, uint line, uint m_column, int type, int level, uint startline, uint startcol);
StructureViewItem(QTreeWidget *parent, const QString &label);
explicit StructureViewItem(const QString &label, QTreeWidgetItem *parent = Q_NULLPTR);
/** @returns the title of this element (for a label it return the label), without the (line ...) part **/
const QString& title() const {
return m_title;
}
/** @returns the line number of the structure element. **/
uint line() const {
return m_line;
}
/** @returns the column number of the structure element, right after the { **/
uint column() const {
return m_column;
}
/** @returns the type of element, see @ref KileStruct **/
int type() const {
return m_type;
}
uint startline() const {
return m_startline;
}
uint startcol() const {
return m_startcol;
}
/**@returns the file in which this item was found*/
const QUrl &url() const {
return m_url;
}
void setURL(const QUrl &url) {
m_url = url;
}
int level() const {
return m_level;
}
const QString &label() const {
return m_label;
}
void setTitle(const QString &title);
void setLabel(const QString &label);
private:
QString m_title;
QUrl m_url;
uint m_line;
uint m_column;
int m_type, m_level;
uint m_startline;
uint m_startcol;
QString m_label;
void setItemEntry();
};
class KileReferenceData
{
public:
KileReferenceData() {}
KileReferenceData(const QString &name, uint line, uint column) : m_name(name), m_line(line), m_column(column) {}
~KileReferenceData() {}
const QString &name() const {
return m_name;
}
uint line() const {
return m_line;
}
uint column() const {
return m_column;
}
private:
QString m_name;
uint m_line;
uint m_column;
};
class StructureWidget; //forward declaration
class StructureView : public QTreeWidget
{
Q_OBJECT
public:
StructureView(StructureWidget *stack, KileDocument::Info *docinfo);
~StructureView();
void activate();
void cleanUp(bool preserveState = true);
void showReferences(KileInfo *ki);
QUrl url() const {
return m_docinfo->url();
}
void updateRoot();
public Q_SLOTS:
void addItem(const QString &title, uint line, uint column, int type, int level, uint startline, uint startcol,
const QString &pix, const QString &folder = "root");
void slotConfigChanged();
protected:
virtual void contextMenuEvent(QContextMenuEvent *event) override;
private:
StructureViewItem* parentFor(int lev, const QString &fldr);
void init();
StructureViewItem* createFolder(const QString &folder);
StructureViewItem* folder(const QString &folder);
void saveState();
bool shouldBeOpen(StructureViewItem *item, const QString &folder, int level);
private:
StructureWidget *m_stack;
KileDocument::Info *m_docinfo;
QMap m_folders;
QMap m_openByTitle;
QMap m_openByLine;
QMap m_openByFolders;
StructureViewItem *m_parent[7], *m_root;
QList m_references;
bool m_openStructureLabels;
bool m_openStructureReferences;
bool m_openStructureBibitems;
bool m_openStructureTodo;
bool m_showStructureLabels;
int m_lastType;
uint m_lastLine;
StructureViewItem *m_lastSectioning;
StructureViewItem *m_lastFloat;
StructureViewItem *m_lastFrame;
StructureViewItem *m_lastFrameEnv;
bool m_stop;
};
class StructureWidget : public QStackedWidget
{
friend class StructureView;
Q_OBJECT
public:
StructureWidget(KileInfo*, QWidget *parent, const char *name = Q_NULLPTR);
~StructureWidget();
int level();
KileInfo *info() {
return m_ki;
}
bool findSectioning(StructureViewItem *item, KTextEditor::Document *doc, int row,
int col, bool backwards, bool checkLevel, int §Row, int §Col);
void updateUrl(KileDocument::Info *docinfo);
void updateAfterParsing(KileDocument::Info *info, const QLinkedList& items);
enum { SectioningCut = 10, SectioningCopy = 11, SectioningPaste = 12,
SectioningSelect = 13, SectioningDelete = 14,
SectioningComment = 15,
SectioningPreview = 16,
SectioningGraphicsOther = 100, SectioningGraphicsOfferlist = 101
};
public Q_SLOTS:
void slotClicked(QTreeWidgetItem *);
void slotDoubleClicked(QTreeWidgetItem *);
- void slotPopupActivated(int id);
void addDocumentInfo(KileDocument::Info *);
void closeDocumentInfo(KileDocument::Info *);
void update(KileDocument::Info *);
void update(KileDocument::Info *, bool);
void clean(KileDocument::Info *);
void updateReferences(KileDocument::Info *);
/**
* Clears the structure widget and empties the map between KileDocument::Info objects and their structure trees (QListViewItem).
**/
void clear();
Q_SIGNALS:
void sendText(const QString&);
void setCursor(const QUrl&, int, int);
void fileOpen(const QUrl&, const QString&);
void fileNew(const QUrl&);
void configChanged();
void sectioningPopup(KileWidget::StructureViewItem *item, int id);
protected:
void viewContextMenuEvent(StructureView *view, QContextMenuEvent *event);
private:
KileInfo *m_ki;
KileDocument::Info *m_docinfo;
QMap m_map;
StructureView *m_default;
StructureViewItem *m_popupItem;
QMenu *m_showingContextMenu;
QString m_popupInfo;
KService::List m_offerList;
StructureView* viewFor(KileDocument::Info *info);
bool viewExistsFor(KileDocument::Info *info);
- void slotPopupLabel(int id);
void slotPopupSectioning(int id);
void slotPopupGraphics(int id);
private Q_SLOTS:
void handleDocumentParsingStarted();
void handleDocumentParsingCompleted();
};
}
#endif