Browse Source

Create section: undo, redo action

Kandrashin Denis 13 years ago
parent
commit
3f1648290b

+ 4 - 2
fb2edit.pro

@@ -52,10 +52,12 @@ OTHER_FILES += \
     source/js/export.js \
     source/js/set_cursor.js \
     source/js/get_status.js \
-    source/js/get_location.js \
     source/js/insert_title.js \
     CMakeLists.txt \
-    source/js/new_section.js
+    source/js/new_section1.js \
+    source/js/section_get.js \
+    source/js/section_new.js \
+    source/js/location.js
 
 if (unix) {
 

+ 31 - 2
source/fb2html.cpp

@@ -183,8 +183,7 @@ FbTextElement FbTextElement::insertInside(const QString &style, const QString &h
 
 QString FbTextElement::location()
 {
-    static const QString javascript = FB2::read(":/js/get_location.js").prepend("var element=this;");
-    return evaluateJavaScript(javascript).toString();
+    return evaluateJavaScript("location(this)").toString();
 }
 
 void FbTextElement::select()
@@ -264,6 +263,36 @@ void FbInsertCmd::undo()
     m_element.takeFromDocument();
 }
 
+//---------------------------------------------------------------------------
+//  FbReplaceCmd
+//---------------------------------------------------------------------------
+
+FbReplaceCmd::FbReplaceCmd(const FbTextElement &original, const FbTextElement &element)
+    : QUndoCommand()
+    , m_original(original)
+    , m_element(element)
+    , m_update(false)
+{
+}
+
+void FbReplaceCmd::redo()
+{
+    if (m_update) {
+        m_original.prependOutside(m_element);
+        m_original.takeFromDocument();
+        m_element.select();
+    } else {
+        m_update = true;
+    }
+}
+
+void FbReplaceCmd::undo()
+{
+    m_element.prependOutside(m_original);
+    m_element.takeFromDocument();
+    m_original.select();
+}
+
 //---------------------------------------------------------------------------
 //  FbDeleteCmd
 //---------------------------------------------------------------------------

+ 12 - 0
source/fb2html.h

@@ -102,6 +102,18 @@ private:
     bool m_inner;
 };
 
+class FbReplaceCmd : public QUndoCommand
+{
+public:
+    explicit FbReplaceCmd(const FbTextElement &original, const FbTextElement &element);
+    virtual void undo();
+    virtual void redo();
+private:
+    FbTextElement m_original;
+    FbTextElement m_element;
+    bool m_update;
+};
+
 class FbDeleteCmd : public QUndoCommand
 {
 public:

+ 11 - 6
source/fb2read.cpp

@@ -408,14 +408,10 @@ FbReadHandler::FbReadHandler(FbReadThread &thread, QXmlStreamWriter &writer)
 {
     m_writer.setAutoFormatting(true);
     m_writer.setAutoFormattingIndent(2);
-
     m_writer.writeStartElement("html");
     m_writer.writeStartElement("head");
-    m_writer.writeStartElement("script");
-    m_writer.writeAttribute("type", "text/javascript");
-    m_writer.writeAttribute("src", "qrc:/js/jquery.js");
-    m_writer.writeCharacters(" ");
-    m_writer.writeEndElement();
+    writeScript("qrc:/js/jquery.js");
+    writeScript("qrc:/js/location.js");
     m_writer.writeEndElement();
 }
 
@@ -424,6 +420,15 @@ FbReadHandler::~FbReadHandler()
     m_writer.writeEndElement();
 }
 
+void FbReadHandler::writeScript(const QString &src)
+{
+    m_writer.writeStartElement("script");
+    m_writer.writeAttribute("type", "text/javascript");
+    m_writer.writeAttribute("src", src);
+    m_writer.writeCharacters(" ");
+    m_writer.writeEndElement();
+}
+
 FbXmlHandler::NodeHandler * FbReadHandler::CreateRoot(const QString &name, const QXmlAttributes &atts)
 {
     Q_UNUSED(atts);

+ 1 - 0
source/fb2read.hpp

@@ -200,6 +200,7 @@ protected:
 
 private:
     void addFile(const QString &name, const QByteArray &data);
+    void writeScript(const QString &src);
 
 private:
     typedef QHash<QString, QString> StringHash;

+ 18 - 4
source/fb2text.cpp

@@ -279,8 +279,21 @@ void FbTextPage::insertDate()
 
 void FbTextPage::createSection()
 {
-    static const QString javascript = FB2::read(":/js/new_section.js");
-    mainFrame()->evaluateJavaScript(javascript);
+    // $(document).children("html").children("body").children("div.body").children("div.section").get(0)
+    static const QString js1 = FB2::read(":/js/section_get.js");
+    QString result = mainFrame()->evaluateJavaScript(js1).toString();
+    int pos = result.indexOf("|");
+    if (pos == 0) return;
+    const QString location = result.left(pos);
+    const QString position = result.mid(pos + 1);
+    FbTextElement original = element(location);
+    FbTextElement section = original.clone();
+    original.appendOutside(section);
+    original.takeFromDocument();
+    static const QString js2 = FB2::read(":/js/section_new.js") + ";f(this,%1)";
+    section.evaluateJavaScript(js2.arg(position));
+    QUndoCommand * command = new FbReplaceCmd(original, section);
+    push(command, tr("Create section"));
 }
 
 void FbTextPage::deleteSection()
@@ -314,7 +327,8 @@ FbTextElement FbTextPage::current()
 
 FbTextElement FbTextPage::element(const QString &location)
 {
-    QStringList list = location.split(",");
+    if (location.isEmpty()) return FbTextElement();
+    QStringList list = location.split(",", QString::SkipEmptyParts);
     QStringListIterator iterator(list);
     QWebElement result = doc();
     while (iterator.hasNext()) {
@@ -331,7 +345,7 @@ FbTextElement FbTextPage::element(const QString &location)
 
 QString FbTextPage::location()
 {
-    static const QString javascript = FB2::read(":/js/get_location.js").prepend("var element=document.getSelection().anchorNode;");
+    const QString javascript = "location(document.getSelection().anchorNode)";
     return mainFrame()->evaluateJavaScript(javascript).toString();
 }
 

+ 0 - 9
source/js/get_location.js

@@ -1,9 +0,0 @@
-// create a reverse function for jQuery
-$.fn.reverse = [].reverse; 
-var hierarchy = $(element).parents().reverse().add($(element));
-hierarchy.map(function () { 
-    var parent = $(this).parent();
-    if (undefined !== parent.get( 0 ).tagName) {
-        return parent.get(0).tagName + "=" + parent.children().index(this);
-    }
-}).get().join(",");

+ 1 - 1
source/js/get_status.js

@@ -6,4 +6,4 @@ if (baseNode === null) ''; else {
 		if (tag === 'DIV') tag = node.getAttribute('CLASS');
 		return f(node.parentNode) + '/' + tag;
 	})(baseNode.parentNode);
-}
+}

+ 3 - 2
source/js/javascript.qrc

@@ -3,9 +3,10 @@
         <file alias="jquery.js">../../3rdparty/jQuery/jquery.js</file>
         <file>export.js</file>
         <file>get_status.js</file>
-        <file>get_location.js</file>
         <file>set_cursor.js</file>
         <file>insert_title.js</file>
-        <file>new_section.js</file>
+        <file>location.js</file>
+        <file>section_get.js</file>
+        <file>section_new.js</file>
     </qresource>
 </RCC>

+ 11 - 0
source/js/location.js

@@ -0,0 +1,11 @@
+function location(e){
+$.fn.reverse = [].reverse;
+var h=$(e).parents().reverse().add($(e));
+var f=function(){
+ var p=$(this).parent();
+ var t=p.get(0).tagName;
+ if(t===undefined)return;
+ return t+"="+p.children().index(this);
+};
+return h.map(f).get().join(",");
+};

+ 6 - 14
source/js/new_section.js → source/js/section_get.js

@@ -1,15 +1,15 @@
-(function(){
-if(window.getSelection().rangeCount===0)return;
+(f=function(){
 var selection=window.getSelection();
+if(selection.rangeCount===0)return;
 var range=selection.getRangeAt(0);
 var root=range.commonAncestorContainer;
 var start=range.startContainer;
 var end=range.endContainer;
 while (true) {
  if(root===null)return;
- tag=root.nodeName.toLowerCase();
- if(tag==="body")return;
- if(tag==="div"){
+ tag=root.tagName;
+ if(tag==="BODY")return;
+ if(tag==="DIV"){
   type=root.className.toLowerCase();
   if(type==="body"||type==="section")break;
  }
@@ -23,13 +23,5 @@ while(end.parentNode!==root) {
  if(end===null)return;
  end=end.parentNode;
 }
-range=document.createRange();
-range.setStartBefore(start);
-range.setEndAfter(end);
-var newNode=document.createElement("div");
-newNode.className="section";
-range.surroundContents(newNode);
-range.setEndBefore(start);
-selection.removeAllRanges();
-selection.addRange(range);
+return location(root) + "|" + $(root).children().index(start) + "," + $(root).children().index(end);
 })()

+ 14 - 0
source/js/section_new.js

@@ -0,0 +1,14 @@
+f=function(elem,start, end){
+start=$(elem).children().get(start);
+end=$(elem).children().get(end);
+var range=document.createRange();
+range.setStartBefore(start);
+range.setEndAfter(end);
+var newNode=document.createElement("div");
+newNode.className="section";
+range.surroundContents(newNode);
+range.setEndBefore(start);
+var selection=window.getSelection();
+selection.removeAllRanges();
+selection.addRange(range);
+};