diff --git a/src/cantor_part.h b/src/cantor_part.h --- a/src/cantor_part.h +++ b/src/cantor_part.h @@ -22,6 +22,7 @@ #define CANTORPART_H #include +#include #include #include @@ -103,6 +104,8 @@ void loadAssistants(); void adjustGuiToSession(); + void setReadOnly(); + protected Q_SLOTS: void fileSaveAs(); void fileSavePlain(); @@ -163,6 +166,10 @@ bool m_showProgressDlg; QAction * m_evaluate; QAction * m_save; + QAction * m_paste; + QAction * m_cut; + QAction * m_undo; + QAction * m_redo; QAction * m_findNext; QAction * m_findPrev; KToggleAction* m_typeset; @@ -174,6 +181,8 @@ QString m_cachedStatusMessage; bool m_statusBarBlocked; + + QVector m_editActions; }; #endif // CANTORPART_H diff --git a/src/cantor_part.cpp b/src/cantor_part.cpp --- a/src/cantor_part.cpp +++ b/src/cantor_part.cpp @@ -177,46 +177,41 @@ savePlain->setIcon(QIcon::fromTheme(QLatin1String("document-save"))); connect(savePlain, SIGNAL(triggered()), this, SLOT(fileSavePlain())); - QAction * undo=KStandardAction::undo(m_worksheet, SIGNAL(undo()), - actionCollection()); - undo->setPriority(QAction::LowPriority); - connect(m_worksheet, SIGNAL(undoAvailable(bool)), - undo, SLOT(setEnabled(bool))); - QAction * redo=KStandardAction::redo(m_worksheet, SIGNAL(redo()), - actionCollection()); - redo->setPriority(QAction::LowPriority); - connect(m_worksheet, SIGNAL(redoAvailable(bool)), - redo, SLOT(setEnabled(bool))); - - QAction * cut=KStandardAction::cut(m_worksheet, SIGNAL(cut()), - actionCollection()); - cut->setPriority(QAction::LowPriority); - connect(m_worksheet, SIGNAL(cutAvailable(bool)), - cut, SLOT(setEnabled(bool))); - QAction * copy=KStandardAction::copy(m_worksheet, SIGNAL(copy()), - actionCollection()); + m_undo=KStandardAction::undo(m_worksheet, SIGNAL(undo()), actionCollection()); + m_undo->setPriority(QAction::LowPriority); + connect(m_worksheet, SIGNAL(undoAvailable(bool)), m_undo, SLOT(setEnabled(bool))); + m_editActions.push_back(m_undo); + + m_redo=KStandardAction::redo(m_worksheet, SIGNAL(redo()), actionCollection()); + m_redo->setPriority(QAction::LowPriority); + connect(m_worksheet, SIGNAL(redoAvailable(bool)), m_redo, SLOT(setEnabled(bool))); + m_editActions.push_back(m_redo); + + m_cut=KStandardAction::cut(m_worksheet, SIGNAL(cut()), actionCollection()); + m_cut->setPriority(QAction::LowPriority); + connect(m_worksheet, SIGNAL(cutAvailable(bool)), m_cut, SLOT(setEnabled(bool))); + m_editActions.push_back(m_cut); + + QAction * copy=KStandardAction::copy(m_worksheet, SIGNAL(copy()), actionCollection()); copy->setPriority(QAction::LowPriority); - connect(m_worksheet, SIGNAL(copyAvailable(bool)), - copy, SLOT(setEnabled(bool))); - QAction * paste=KStandardAction::paste(m_worksheet, SIGNAL(paste()), - actionCollection()); - paste->setPriority(QAction::LowPriority); - connect(m_worksheet, SIGNAL(pasteAvailable(bool)), - paste, SLOT(setEnabled(bool))); - - QAction * find=KStandardAction::find(this, SLOT(showSearchBar()), - actionCollection()); + connect(m_worksheet, SIGNAL(copyAvailable(bool)), copy, SLOT(setEnabled(bool))); + + m_paste=KStandardAction::paste(m_worksheet, SIGNAL(paste()), actionCollection()); + m_paste->setPriority(QAction::LowPriority); + connect(m_worksheet, SIGNAL(pasteAvailable(bool)), m_paste, SLOT(setEnabled(bool))); + m_editActions.push_back(m_paste); + + QAction * find=KStandardAction::find(this, SLOT(showSearchBar()), actionCollection()); find->setPriority(QAction::LowPriority); - QAction * replace=KStandardAction::replace(this, SLOT(showExtendedSearchBar()), - actionCollection()); + QAction * replace=KStandardAction::replace(this, SLOT(showExtendedSearchBar()), actionCollection()); replace->setPriority(QAction::LowPriority); + m_editActions.push_back(replace); - m_findNext = KStandardAction::findNext(this, SLOT(findNext()), - actionCollection()); + m_findNext = KStandardAction::findNext(this, SLOT(findNext()),actionCollection()); m_findNext->setEnabled(false); - m_findPrev = KStandardAction::findPrev(this, SLOT(findPrev()), - actionCollection()); + + m_findPrev = KStandardAction::findPrev(this, SLOT(findPrev()), actionCollection()); m_findPrev->setEnabled(false); QAction * latexExport=new QAction(i18n("Export to LaTeX"), actionCollection()); @@ -238,6 +233,7 @@ m_evaluate->setIcon(QIcon::fromTheme(QLatin1String("system-run"))); actionCollection()->setDefaultShortcut(m_evaluate, Qt::CTRL+Qt::Key_E); connect(m_evaluate, SIGNAL(triggered()), this, SLOT(evaluateOrInterrupt())); + m_editActions.push_back(m_evaluate); m_typeset=new KToggleAction(i18n("Typeset using LaTeX"), actionCollection()); m_typeset->setChecked(Settings::self()->typesetDefault()); @@ -268,36 +264,46 @@ actionCollection()->addAction(QLatin1String("restart_backend"), restart); restart->setIcon(QIcon::fromTheme(QLatin1String("system-reboot"))); connect(restart, SIGNAL(triggered()), this, SLOT(restartBackend())); + m_editActions.push_back(restart); QAction * evaluateCurrent=new QAction(i18n("Evaluate Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("evaluate_current"), evaluateCurrent); actionCollection()->setDefaultShortcut(evaluateCurrent, Qt::SHIFT + Qt::Key_Return); connect(evaluateCurrent, SIGNAL(triggered()), m_worksheet, SLOT(evaluateCurrentEntry())); + m_editActions.push_back(evaluateCurrent); QAction * insertCommandEntry=new QAction(i18n("Insert Command Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_command_entry"), insertCommandEntry); actionCollection()->setDefaultShortcut(insertCommandEntry, Qt::CTRL + Qt::Key_Return); connect(insertCommandEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertCommandEntry())); + m_editActions.push_back(insertCommandEntry); QAction * insertTextEntry=new QAction(i18n("Insert Text Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_text_entry"), insertTextEntry); connect(insertTextEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertTextEntry())); + m_editActions.push_back(insertTextEntry); + #ifdef Discount_FOUND QAction * insertMarkdownEntry=new QAction(i18n("Insert Markdown Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_markdown_entry"), insertMarkdownEntry); connect(insertMarkdownEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertMarkdownEntry())); + m_editActions.push_back(insertMarkdownEntry); #endif + QAction * insertLatexEntry=new QAction(i18n("Insert Latex Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_latex_entry"), insertLatexEntry); connect(insertLatexEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertLatexEntry())); + m_editActions.push_back(insertLatexEntry); QAction * insertPageBreakEntry=new QAction(i18n("Insert Page Break"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_page_break_entry"), insertPageBreakEntry); connect(insertPageBreakEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertPageBreakEntry())); + m_editActions.push_back(insertPageBreakEntry); QAction * insertImageEntry=new QAction(i18n("Insert Image"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_image_entry"), insertImageEntry); connect(insertImageEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertImageEntry())); + m_editActions.push_back(insertImageEntry); /* @@ -325,6 +331,7 @@ actionCollection()->addAction(QLatin1String("remove_current"), removeCurrent); actionCollection()->setDefaultShortcut(removeCurrent, Qt::ShiftModifier + Qt::Key_Delete); connect(removeCurrent, SIGNAL(triggered()), m_worksheet, SLOT(removeCurrentEntry())); + m_editActions.push_back(removeCurrent); m_showBackendHelp=new QAction(i18n("Show %1 Help", b->name()) , actionCollection()); m_showBackendHelp->setIcon(QIcon::fromTheme(QLatin1String("help-contents"))); @@ -348,6 +355,7 @@ showCompletionShortcuts << Qt::Key_Tab << Qt::CTRL + Qt::Key_Space; actionCollection()->setDefaultShortcuts(showCompletion, showCompletionShortcuts); connect(showCompletion, SIGNAL(triggered()), m_worksheet, SLOT(showCompletion())); + m_editActions.push_back(showCompletion); // set our XML-UI resource file setXMLFile(QLatin1String("cantor_part.rc")); @@ -380,6 +388,23 @@ ReadWritePart::setReadWrite(rw); } +void CantorPart::setReadOnly() +{ + for (QAction* action : m_editActions) + action->setEnabled(false); + + disconnect(m_worksheet, SIGNAL(pasteAvailable(bool)), m_paste, SLOT(setEnabled(bool))); + disconnect(m_worksheet, SIGNAL(undoAvailable(bool)), m_undo, SLOT(setEnabled(bool))); + disconnect(m_worksheet, SIGNAL(redoAvailable(bool)), m_redo, SLOT(setEnabled(bool))); + disconnect(m_worksheet, SIGNAL(cutAvailable(bool)), m_cut, SLOT(setEnabled(bool))); + + if (m_showBackendHelp) + { + m_showBackendHelp->setEnabled(false); + m_showBackendHelp->setVisible(false); + } +} + void CantorPart::setModified(bool modified) { // get a handle on our Save action and make sure it is valid @@ -461,12 +486,15 @@ QString worksheetFilter = i18n("Cantor Worksheet (*.cws)"); QString filter = worksheetFilter; - //if the backend supports scripts, also append their scriptFile endings to the filter - Cantor::Backend * const backend=m_worksheet->session()->backend(); - if (backend->extensions().contains(QLatin1String("ScriptExtension"))) + if (!m_worksheet->isReadOnly()) { - Cantor::ScriptExtension* e=dynamic_cast(backend->extension(QLatin1String("ScriptExtension"))); - filter+=QLatin1String(";;")+e->scriptFileFilter(); + //if the backend supports scripts, also append their scriptFile endings to the filter + Cantor::Backend * const backend=m_worksheet->session()->backend(); + if (backend->extensions().contains(QLatin1String("ScriptExtension"))) + { + Cantor::ScriptExtension* e=dynamic_cast(backend->extension(QLatin1String("ScriptExtension"))); + filter+=QLatin1String(";;")+e->scriptFileFilter(); + } } QString selectedFilter; @@ -563,17 +591,22 @@ void CantorPart::initialized() { - connect(m_worksheet->session(), SIGNAL(statusChanged(Cantor::Session::Status)), this, SLOT(worksheetStatusChanged(Cantor::Session::Status))); - connect(m_worksheet->session(), SIGNAL(loginStarted()),this, SLOT(worksheetSessionLoginStarted())); - connect(m_worksheet->session(), SIGNAL(loginDone()),this, SLOT(worksheetSessionLoginDone())); - connect(m_worksheet->session(), SIGNAL(error(QString)), this, SLOT(showSessionError(QString))); + if (!m_worksheet->isReadOnly()) + { + connect(m_worksheet->session(), SIGNAL(statusChanged(Cantor::Session::Status)), this, SLOT(worksheetStatusChanged(Cantor::Session::Status))); + connect(m_worksheet->session(), SIGNAL(loginStarted()),this, SLOT(worksheetSessionLoginStarted())); + connect(m_worksheet->session(), SIGNAL(loginDone()),this, SLOT(worksheetSessionLoginDone())); + connect(m_worksheet->session(), SIGNAL(error(QString)), this, SLOT(showSessionError(QString))); - loadAssistants(); - m_panelHandler->setSession(m_worksheet->session()); - adjustGuiToSession(); + loadAssistants(); + m_panelHandler->setSession(m_worksheet->session()); + adjustGuiToSession(); - if (m_worksheet->isEmpty()) - m_worksheet->appendCommandEntry(); + if (m_worksheet->isEmpty()) + m_worksheet->appendCommandEntry(); + } + else + setReadOnly(); m_worksheetview->setEnabled(true); m_worksheetview->setFocus(); @@ -620,7 +653,10 @@ if (filename.isEmpty()) filename=i18n("Unnamed"); - emit setCaption(filename, QIcon::fromTheme(m_worksheet->session()->backend()->icon())); + if (!m_worksheet->isReadOnly()) + emit setCaption(filename, QIcon::fromTheme(m_worksheet->session()->backend()->icon())); + else + emit setCaption(filename+QLatin1Char(' ')+i18n("[read-only]"), QIcon()); } void CantorPart::pluginsChanged() diff --git a/src/lib/expression.cpp b/src/lib/expression.cpp --- a/src/lib/expression.cpp +++ b/src/lib/expression.cpp @@ -74,7 +74,7 @@ { d->session=session; d->internal = internal; - if (!internal) + if (!internal && session) d->id=session->nextExpressionId(); else d->id = -1; @@ -119,7 +119,8 @@ qDebug()<<"setting result to a type "<type()<<" result"; #ifdef WITH_EPS //If it's text, and latex typesetting is enabled, render it - if ( session()->isTypesettingEnabled()&& + if ( session() && + session()->isTypesettingEnabled()&& result->type()==TextResult::Type && dynamic_cast(result)->format()==TextResult::LatexFormat && !result->toHtml().trimmed().isEmpty() && diff --git a/src/worksheet.h b/src/worksheet.h --- a/src/worksheet.h +++ b/src/worksheet.h @@ -63,6 +63,7 @@ Cantor::Session* session(); bool isRunning(); + bool isReadOnly(); bool showExpressionIds(); bool animationsEnabled(); @@ -220,6 +221,7 @@ protected: void contextMenuEvent(QGraphicsSceneContextMenuEvent*) override; void mousePressEvent(QGraphicsSceneMouseEvent*) override; + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event) override; void dragEnterEvent(QGraphicsSceneDragDropEvent*) override; void dragLeaveEvent(QGraphicsSceneDragDropEvent*) override; @@ -293,7 +295,9 @@ bool m_loginDone; bool m_isPrinting; bool m_isLoadingFromFile; + bool m_readOnly; + QString m_backendName; }; #endif // WORKSHEET_H diff --git a/src/worksheet.cpp b/src/worksheet.cpp --- a/src/worksheet.cpp +++ b/src/worksheet.cpp @@ -88,6 +88,7 @@ m_isPrinting = false; m_loginDone = false; + m_readOnly = false; m_isLoadingFromFile = false; enableHighlighting(Settings::self()->highlightDefault()); @@ -421,6 +422,9 @@ void Worksheet::startDrag(WorksheetEntry* entry, QDrag* drag) { + if (m_readOnly) + return; + resetEntryCursor(); m_dragEntry = entry; WorksheetEntry* prev = entry->previous(); @@ -474,7 +478,7 @@ void Worksheet::evaluate() { qDebug()<<"evaluate worksheet"; - if (!m_loginDone) + if (!m_loginDone && !m_readOnly) loginToSession(); firstEntry()->evaluate(WorksheetEntry::EvaluateNext); @@ -484,7 +488,7 @@ void Worksheet::evaluateCurrentEntry() { - if (!m_loginDone) + if (!m_loginDone && !m_readOnly) loginToSession(); WorksheetEntry* entry = currentEntry(); @@ -519,7 +523,10 @@ setLastEntry(entry); updateLayout(); makeVisible(entry); - focusEntry(entry); + if (m_readOnly) + entry->setAcceptHoverEvents(false); + else + focusEntry(entry); } return entry; } @@ -799,7 +806,11 @@ if(m_highlighter) m_highlighter->deleteLater(); - m_highlighter=session()->syntaxHighlighter(this); + if (!m_readOnly) + m_highlighter=session()->syntaxHighlighter(this); + else + m_highlighter=nullptr; + if(!m_highlighter) m_highlighter=new Cantor::DefaultHighlighter(this); @@ -827,7 +838,12 @@ bool Worksheet::isRunning() { - return m_session->status()==Cantor::Session::Running; + return m_session && m_session->status()==Cantor::Session::Running; +} + +bool Worksheet::isReadOnly() +{ + return m_readOnly; } bool Worksheet::showExpressionIds() @@ -855,7 +871,7 @@ { QDomDocument doc( QLatin1String("CantorWorksheet") ); QDomElement root=doc.createElement( QLatin1String("Worksheet") ); - root.setAttribute(QLatin1String("backend"), m_session->backend()->name()); + root.setAttribute(QLatin1String("backend"), (m_session ? m_session->backend()->name(): m_backendName)); doc.appendChild(root); for( WorksheetEntry* entry = firstEntry(); entry; entry = entry->next()) @@ -923,14 +939,19 @@ QString commentStartingSeq = QLatin1String(""); QString commentEndingSeq = QLatin1String(""); - Cantor::Backend * const backend=session()->backend(); - if (backend->extensions().contains(QLatin1String("ScriptExtension"))) + if (!m_readOnly) { - Cantor::ScriptExtension* e=dynamic_cast(backend->extension(QLatin1String(("ScriptExtension")))); - cmdSep=e->commandSeparator(); - commentStartingSeq = e->commentStartingSequence(); - commentEndingSeq = e->commentEndingSequence(); + Cantor::Backend * const backend=session()->backend(); + if (backend->extensions().contains(QLatin1String("ScriptExtension"))) + { + Cantor::ScriptExtension* e=dynamic_cast(backend->extension(QLatin1String(("ScriptExtension")))); + cmdSep=e->commandSeparator(); + commentStartingSeq = e->commentStartingSequence(); + commentEndingSeq = e->commentEndingSequence(); + } } + else + KMessageBox::information(worksheetView(), i18n("In read-only mode Cantor couldn't guarantee, that the export will be valid for %1", m_backendName), i18n("Cantor")); QTextStream stream(&file); @@ -986,7 +1007,7 @@ } bool rc = load(&file); - if (rc) + if (rc && !m_readOnly) m_session->setWorksheetPath(filename); return rc; @@ -1027,24 +1048,31 @@ QDomElement root=doc.documentElement(); // qDebug()<isEnabled()) + if(!m_readOnly && !b->isEnabled()) { QApplication::restoreOverrideCursor(); KMessageBox::information(worksheetView(), i18n("There are some problems with the %1 backend,\n"\ "please check your configuration or install the needed packages.\n" - "You will only be able to view this worksheet.", backendName), i18n("Cantor")); - + "You will only be able to view this worksheet.", m_backendName), i18n("Cantor")); + m_readOnly = true; } + if (m_readOnly) + // TODO: Handle this here? + for (QAction* action : m_richTextActionList) + action->setEnabled(false); + m_isLoadingFromFile = true; //cleanup the worksheet and all it contains @@ -1060,7 +1088,8 @@ } - m_session=b->createSession(); + if (!m_readOnly) + m_session=b->createSession(); qDebug()<<"loading entries"; QDomElement expressionChild = root.firstChildElement(); @@ -1213,6 +1242,9 @@ void Worksheet::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + if (m_readOnly) + return; + // forward the event to the items QGraphicsScene::contextMenuEvent(event); @@ -1233,12 +1265,23 @@ event->scenePos().y() > lastEntry()->y() + lastEntry()->size().height()) lastEntry()->focusEntry(WorksheetTextItem::BottomRight); */ + if (!m_readOnly) + updateEntryCursor(event); +} - updateEntryCursor(event); +void Worksheet::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) +{ + if (m_readOnly) + return; + + QGraphicsScene::mouseDoubleClickEvent(event); } void Worksheet::keyPressEvent(QKeyEvent *keyEvent) { + if (m_readOnly) + return; + // If we choose entry by entry cursor and press text button (not modifiers, for example, like Control) if ((m_choosenCursorEntry || m_isCursorEntryAfterLastEntry) && !keyEvent->text().isEmpty()) addEntryFromEntryCursor(); @@ -1514,9 +1557,11 @@ void Worksheet::setAcceptRichText(bool b) { - foreach(QAction * action, m_richTextActionList) { - action->setEnabled(b); - } + if (!m_readOnly) + foreach(QAction * action, m_richTextActionList) { + action->setEnabled(b); + } + /* foreach(QWidget* widget, m_fontAction->createdWidgets()) {