diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst
index e3a76d546549b6bc29d7ad97e5634ebc7b210b12..c902098b84287bea3c8b6eb6f0815145a226aa01 100644
--- a/extension/Documentation/Manual.rst
+++ b/extension/Documentation/Manual.rst
@@ -472,6 +472,9 @@ config.qfq.php
 | LDAP_1_RDN                    | LDAP_1_RDN='ou=Admin,ou=example,dc=com'               | Credentials for non-anonymous LDAP access. At the moment only one set of   |
 | LDAP_1_PASSWORD               | LDAP_1_PASSWORD=mySecurePassword                      |                                                                            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
+| T3_DB_NAME                    | T3_DB_NAME=specialt3dbname                            | Only necessary for inline report editing if the t3 database is not         |
+|                               |                                                       | anologous to the Data db name (but ending in _t3) - see `inline-report`_.  |
++-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 
 
 
@@ -503,11 +506,11 @@ Example: *typo3conf/config.qfq.php*: ::
 
 After parsing the configuration, the following variables will be set automatically in STORE_SYSTEM:
 
-+----------------+-----------------------------------------------------------------------------------+
-| _dbNameData    | Can be used to dynamically access the current selected database: {{dbNameData:Y}} |
-+----------------+-----------------------------------------------------------------------------------+
-| _dbNameQfq     | Can be used to dynamically access the current selected database: {{dbNameQfq:Y}}  |
-+----------------+-----------------------------------------------------------------------------------+
++----------------+------------------------------------------------------------------------------------+
+| _dbNameData    | Can be used to dynamically access the current selected database: {{_dbNameData:Y}} |
++----------------+------------------------------------------------------------------------------------+
+| _dbNameQfq     | Can be used to dynamically access the current selected database: {{_dbNameQfq:Y}}  |
++----------------+------------------------------------------------------------------------------------+
 
 .. _`CustomVariables`:
 
@@ -4992,6 +4995,29 @@ The parsed bodytext could be displayed by activating 'showDebugInfo' (:ref:`debu
 A small symbol with a tooltip will be shown, where the content record will be displayed on the webpage.
 Note: :ref:`debug` information will only be shown with *showDebugInfo: yes* in configuration_.
 
+
+.. _`inline-report`:
+
+Inline Report editing
+---------------------
+
+For quick changes it can be bothersome to go to the TYPO3 backend to update the page content and reload the page.
+For this reason, QFQ offers an inline report editing feature whenever there is a TYPO3 BE user logged in. A small
+link symbol will appear on the right-hand side of each report record. Please note that the TYPO3 Frontend cache
+is also deleted upon each inline report save.
+
+In order for the inline report editing to work, QFQ needs to be able to access the T3 database. By default this database
+is assumed to be accessible with the same credentials as specified with indexData and is assumed to be named similarly to
+the indexData db name, but ending in _t3 instead of _db (e.g., mydb_db and mydb_t3).
+For a standard installation and db setup, this should be the case.
+
+You can however specify a custom T3 db name in config-qfq-php_:
+
+::
+
+    T3_DB_NAME = customT3DbName
+
+
 Structure
 ---------
 
diff --git a/extension/qfq/api/save.php b/extension/qfq/api/save.php
index 71fcac1370f6e54d5946b24df78a543eada87cfb..054c54120a3bd9d9728e11d1478dd6cfa097f320 100644
--- a/extension/qfq/api/save.php
+++ b/extension/qfq/api/save.php
@@ -59,6 +59,11 @@ try {
 
         $data = $qfq->saveForm();
 
+        if (isset($data[REPORT_SAVE])) {
+            // Redirect to previous page
+            header("Location: {$_SERVER['HTTP_REFERER']}");
+        }
+
         $arr = $qfq->getForwardMode();
         $answer[API_REDIRECT] = $arr[API_REDIRECT];
         $answer[API_REDIRECT_URL] = $arr[API_REDIRECT_URL];
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index 05c2315b18be00814296767ac2a3515d477ad83f..09e7ca56ef951315f040836e0bd41634a463bb5c 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -45,6 +45,8 @@ const FORM_BUTTON_DELETE = 'delete';
 const FORM_BUTTON_CLOSE = 'close';
 const FORM_BUTTON_SAVE = 'save';
 
+const REPORT_SAVE = 'reportSave';
+
 const F_BS_COLUMNS = 'bsColumns';
 
 const F_BS_LABEL_COLUMNS = 'bsLabelColumns';
@@ -409,6 +411,8 @@ const SYSTEM_DB_1_SERVER = 'DB_1_SERVER';
 const SYSTEM_DB_1_PASSWORD = 'DB_1_PASSWORD';
 const SYSTEM_DB_1_NAME = 'DB_1_NAME';
 
+const SYSTEM_T3_DB_NAME = 'T3_DB_NAME';
+
 const SYSTEM_DB_INIT = 'init';
 
 const SYSTEM_DB_INDEX_DATA = "indexData";
@@ -1205,7 +1209,10 @@ const INDEX_PHP = 'index.php';
 
 // QuickFormQuery.php
 const T3DATA_BODYTEXT = 'bodytext';
+const T3DATA_BODYTEXT_RAW = 'bodytext-raw';
 const T3DATA_UID = 'uid';
+const T3DATA_HEADER = 'header';
+const REPORT_INLINE_BODYTEXT = 'bodytext';
 
 // Special Column to check for uploads
 const COLUMN_PATH_FILE_NAME = 'pathFileName';
diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php
index 762801973cf06c2dfd7ac11344ae5cb2d95e7cb2..e514a04ccb08b6d152b728dfef19d941e208442d 100644
--- a/extension/qfq/qfq/QuickFormQuery.php
+++ b/extension/qfq/qfq/QuickFormQuery.php
@@ -23,6 +23,7 @@ use qfq;
 
 
 require_once(__DIR__ . '/store/Store.php');
+require_once(__DIR__ . '/store/Sip.php');
 require_once(__DIR__ . '/store/FillStoreForm.php');
 require_once(__DIR__ . '/store/Session.php');
 require_once(__DIR__ . '/Constants.php');
@@ -151,6 +152,7 @@ class QuickFormQuery {
         }
 
         $btp = new BodytextParser();
+        $t3data[T3DATA_BODYTEXT_RAW] = $t3data[T3DATA_BODYTEXT];
         $t3data[T3DATA_BODYTEXT] = $btp->process($t3data[T3DATA_BODYTEXT]);
 
         $this->t3data = $t3data;
@@ -1306,7 +1308,7 @@ class QuickFormQuery {
     /**
      * Load record $id from $table and saves them in $store
      *
-     * @param string $table tablename from where to load record wiht $recordId
+     * @param array $table tablename
      * @param string $recordId record ID of current record
      * @param string $store name of store where to save the record
      *
@@ -1362,12 +1364,95 @@ class QuickFormQuery {
     private function doReport() {
 
         $report = new Report($this->t3data, $this->eval, $this->phpUnit);
+        $html = '';
 
-        $html = $report->process($this->t3data['bodytext']);
+        if ($this->store->getVar(TYPO3_BE_USER, STORE_TYPO3, SANITIZE_ALLOW_ALNUMX)) {
+            $html .= $this->buildInlineReport();
+        }
+        $html .= $report->process($this->t3data[T3DATA_BODYTEXT]);
 
         return $html;
     }
 
+    /** Constructs a form to directly edit qfq content elements inline.
+     *
+     * @return string - the html code
+     * @throws CodeException
+     * @throws DbException
+     * @throws DownloadException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    private function buildInlineReport() {
+        $uid = $this->t3data[T3DATA_UID];
+        $bodytext = $this->t3data[T3DATA_BODYTEXT_RAW];
+        $header = $this->t3data[T3DATA_HEADER];
+
+        $icon = Support::renderGlyphIcon(GLYPH_ICON_TASKS);
+        $showFormJs = '$("#tt-content-edit-' . $uid . '").toggleClass("hidden")';
+        $toggleBtn = Support::wrapTag("<a href='#' onclick='$showFormJs' style='float:right;'>", $icon);
+
+        $saveBtnAttributes = Support::doAttribute('class', 'btn btn-default') .
+            Support::doAttribute('id', "tt-content-save-$uid") .
+            Support::doAttribute('type', 'submit') .
+            Support::doAttribute('style', 'float:right; margin:-5px;') .
+            Support::doAttribute('title', 'Save & Reload');
+        $saveBtnIcon = Support::renderGlyphIcon(GLYPH_ICON_CHECK);
+        $saveBtn = Support::wrapTag("<button $saveBtnAttributes>", $saveBtnIcon);
+        $header = "QFQ Page Content '$header'";
+        $headerBar = Support::wrapTag("<div class='col-md-12 qfq-form-title'>", $header . $saveBtn);
+
+        $ttContentCode = Support::htmlEntityEncodeDecode(MODE_ENCODE, $bodytext);
+        $codeBoxAttributes = Support::doAttribute('style', "width:100%;") .
+            Support::doAttribute('id', "tt-content-code-$uid") .
+            Support::doAttribute('rows',20) .
+            Support::doAttribute('name', REPORT_INLINE_BODYTEXT);
+        $codeBox = Support::wrapTag("<textarea $codeBoxAttributes>", $ttContentCode);
+
+        $form = join(' ', [$headerBar, $codeBox]);
+        $sipObj = new Sip;
+        $action = $sipObj->queryStringToSip(API_DIR . "/save.php?uid=$uid&" . REPORT_SAVE . "=1");
+        $formAttributes = Support::doAttribute('id', "tt-content-edit-$uid") .
+            Support::doAttribute('class', 'hidden') .
+            Support::doAttribute('method', 'post') .
+            Support::doAttribute('action', $action);
+        $form = Support::wrapTag("<form $formAttributes>", $form);
+
+        return $toggleBtn . $form;
+    }
+
+    /**
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     */
+    public function saveReport() {
+        $uid = $this->store->getVar(T3DATA_UID, STORE_SIP . STORE_ZERO, SANITIZE_ALLOW_DIGIT);
+        if ($uid == 0) {
+            // Check if it was called with a SIP (containing a uid)
+            // If not, this might be an attack => cancel.
+            return;
+        }
+
+        $bodytext = Support::htmlEntityEncodeDecode(MODE_DECODE, $_POST[REPORT_INLINE_BODYTEXT]);
+        $dbT3 = $this->store->getVar(SYSTEM_T3_DB_NAME, STORE_SYSTEM . STORE_EMPTY, SANITIZE_ALLOW_ALNUMX);
+        if ($dbT3 == '') {
+            $dbData = $this->store->getVar(SYSTEM_DB_NAME_DATA, STORE_SYSTEM, SANITIZE_ALLOW_ALNUMX);
+            $dbT3 = substr($dbData, 0, strrpos($dbData, "_") + 1) . 't3';
+        }
+
+        // Update bodytext
+        $sql = "UPDATE $dbT3.tt_content SET bodytext = ?, tstamp = UNIX_TIMESTAMP(NOW()) WHERE uid = ?";
+        $this->dbArray[$this->dbIndexData]->sql($sql, ROW_REGULAR, [$bodytext, $uid]);
+
+        // Clear cache
+        // Need to truncate cf_cache_pages because it is used to restore page-specific cache
+        $sql = "DELETE FROM $dbT3.cf_cache_pages WHERE 1";
+        $this->dbArray[$this->dbIndexData]->sql($sql);
+
+        $this->formSpec[F_FORWARD_MODE] = 'auto';
+    }
+
     /**
      * Save the current form.
      *
@@ -1379,8 +1464,13 @@ class QuickFormQuery {
      * @throws UserReportException
      */
     public function saveForm() {
-
-        $json = $this->doForm(FORM_SAVE);
+        if ($this->store->getVar(REPORT_SAVE, STORE_SIP . STORE_ZERO) == '1') {
+            $this->saveReport();
+            $json = array();
+            $json[REPORT_SAVE] = 1;
+        } else {
+            $json = $this->doForm(FORM_SAVE);
+        }
 
         return $json;
     }
diff --git a/extension/qfq/qfq/Save.php b/extension/qfq/qfq/Save.php
index a2beebf72a57d385261483f1a21463fdeda359d0..826fee366406c722892a5302736bf6998e9bce20 100644
--- a/extension/qfq/qfq/Save.php
+++ b/extension/qfq/qfq/Save.php
@@ -309,7 +309,7 @@ class Save {
             $sql .= '`' . $column . '` = ?, ';
         }
 
-        $sql = substr($sql, 0, strlen($sql) - 2) . ' WHERE id = ?';
+        $sql = substr($sql, 0, strlen($sql) - 2) . " WHERE id = ?";
         $values[] = $recordId;
 
         $rc = $this->db->sql($sql, ROW_REGULAR, array_values($values));
diff --git a/extension/qfq/qfq/form/Dirty.php b/extension/qfq/qfq/form/Dirty.php
index 52b6c317653d193cef9d9e002ff1ed1ea50b43cc..07be2e27512cf8173df7cd873f8efb631cc04673 100644
--- a/extension/qfq/qfq/form/Dirty.php
+++ b/extension/qfq/qfq/form/Dirty.php
@@ -152,26 +152,25 @@ class Dirty {
         $formDirtyMode = $tableVars[F_DIRTY_MODE];
         $rcMd5 = '';
 
-        // Check for changed record. Compute $rcMd5
-        $flagModified = $this->isRecordModified($tableName, $recordId, $recordHashMd5, $rcMd5);
-        if (($recordHashMd5 != '') && $flagModified) {
-            return [API_STATUS => API_ANSWER_STATUS_CONFLICT, API_MESSAGE => 'The record has been modified in the meantime. Please reload the form, edit and save again.'];
-        }
-
-        $feUser = $this->session->get(SESSION_FE_USER);
+        if ($formDirtyMode == DIRTY_MODE_NONE) {
+            $answer = [API_STATUS => 'success', API_MESSAGE => ''];
+        } else {
+            // Check for changed record. Compute $rcMd5
+            $flagModified = $this->isRecordModified($tableName, $recordId, $recordHashMd5, $rcMd5);
+            if (($recordHashMd5 != '') && $flagModified) {
+                return [API_STATUS => API_ANSWER_STATUS_CONFLICT, API_MESSAGE => 'The record has been modified in the meantime. Please reload the form, edit and save again.'];
+            }
 
-        // Look for already existing dirty record.
-        $recordDirty = $this->getRecordDirty($tableName, $recordId);
+            // Look for already existing dirty record.
+            $recordDirty = $this->getRecordDirty($tableName, $recordId);
 
-        if (count($recordDirty) == 0) {
-            if ($formDirtyMode == DIRTY_MODE_NONE) {
-                $answer = [API_STATUS => 'success', API_MESSAGE => ''];
-            } else {
+            if (count($recordDirty) == 0) {
                 // No dirty record found.
+                $feUser = $this->session->get(SESSION_FE_USER);
                 $answer = $this->writeDirty($this->client[SIP_SIP], $recordId, $tableVars, $feUser, $rcMd5);
+            } else {
+                $answer = $this->conflict($recordDirty, $formDirtyMode);
             }
-        } else {
-            $answer = $this->conflict($recordDirty, $formDirtyMode);
         }
 
         return $answer;
@@ -277,8 +276,9 @@ class Dirty {
      * @param string $tableName
      * @param int $recordId
      * @param string $recordHashMd5 - timestamp e.g. '2017-07-27 14:06:56'
-     *
      * @param $rcMd5
+     * @param string $tableId
+     *
      * @return bool true if $recordHashMd5 is different from current record md5 hash.
      */
     private function isRecordModified($tableName, $recordId, $recordHashMd5, &$rcMd5) {
@@ -359,8 +359,9 @@ class Dirty {
 
         $answer = [API_STATUS => API_ANSWER_STATUS_SUCCESS, API_MESSAGE => ''];
 
-        if ($recordId == 0) {
-            return $answer; // New records never have a recordDirty nor a conflict.
+        if ($recordId == 0 || // New records never have a recordDirty nor a conflict.
+            $dirtyMode == DIRTY_MODE_NONE) { // mode none -> no lock checking
+            return $answer;
         }
 
         // Check if the record has changed in the meantime.
@@ -371,13 +372,9 @@ class Dirty {
         $lockStatus = $this->getCheckDirty($tableName, $recordId, $rcRecordDirty, $rcMsg);
 
         if (empty($rcRecordDirty)) {
-            if ($dirtyMode == DIRTY_MODE_NONE) {
-                return $answer; // only situation where it's ok that there is no dirtyRecord.
-            }
             if ($formMode == FORM_DELETE) {
                 return $answer;
             }
-
             // This is pessimistic, but secure.
 //            throw new UserFormException("Missing record lock: please reload the form, edit and save again.", ERROR_DIRTY_MISSING_LOCK);
 
diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php
index ab94a4fded1821c1501ea1ac039aed0a15298208..bb040cd78af7440ddcfe28c9b3a1310b74fbbb23 100644
--- a/extension/qfq/qfq/helper/Support.php
+++ b/extension/qfq/qfq/helper/Support.php
@@ -146,6 +146,10 @@ class Support {
         return $tag . $value . $closing;
     }
 
+    public static function renderGlyphIcon($glyphIcon, $value = '') {
+        return Support::wrapTag("<span class='" . GLYPH_ICON . " $glyphIcon'>", $value);
+    }
+
     /**
      * Removes '$tag' and closing $tag from $value, if they are the outermost.
      * E.g.  unWrapTag('<p>', '<p>Hello World</p>')    returns  'Hello World'