Added: #1307 Merge options for translation files from local directory and from FTP server
This commit is contained in:
parent
9bb3c88b10
commit
b38e17f80f
7 changed files with 132 additions and 201 deletions
|
@ -1,117 +0,0 @@
|
|||
// Object Viewer Qt - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||
// Copyright (C) 2010 Winch Gate Property Limited
|
||||
// Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CORE_CONSTANTS_H
|
||||
#define CORE_CONSTANTS_H
|
||||
|
||||
namespace Core
|
||||
{
|
||||
namespace Constants
|
||||
{
|
||||
|
||||
const char * const OVQT_VERSION_LONG = "0.1";
|
||||
const char * const OVQT_VENDOR = "Ryzom Core";
|
||||
const char * const OVQT_YEAR = "2010, 2011";
|
||||
const char * const OVQT_CORE_PLUGIN = "Core";
|
||||
|
||||
//mainwindow
|
||||
const char * const MAIN_WINDOW = "ObjectViewerQt.MainWindow";
|
||||
|
||||
//menubar
|
||||
const char * const MENU_BAR = "ObjectViewerQt.MenuBar";
|
||||
|
||||
//menus
|
||||
const char * const M_FILE = "ObjectViewerQt.Menu.File";
|
||||
const char * const M_EDIT = "ObjectViewerQt.Menu.Edit";
|
||||
const char * const M_VIEW = "ObjectViewerQt.Menu.View";
|
||||
const char * const M_SCENE = "ObjectViewerQt.Menu.Scene";
|
||||
const char * const M_TOOLS = "ObjectViewerQt.Menu.Tools";
|
||||
const char * const M_WINDOW = "ObjectViewerQt.Menu.Window";
|
||||
const char * const M_HELP = "ObjectViewerQt.Menu.Help";
|
||||
|
||||
const char * const M_FILE_RECENTFILES = "ObjectViewerQt.Menu.File.RecentFiles";
|
||||
const char * const M_SHEET = "ObjectViewerQt.Menu.Sheet";
|
||||
|
||||
//actions
|
||||
const char * const NEW = "ObjectViewerQt.New";
|
||||
const char * const OPEN = "ObjectViewerQt.Open";
|
||||
const char * const SAVE = "ObjectViewerQt.Save";
|
||||
const char * const SAVE_AS = "ObjectViewerQt.SaveAs";
|
||||
const char * const SAVE_ALL = "ObjectViewerQt.SaveAll";
|
||||
const char * const EXIT = "ObjectViewerQt.Exit";
|
||||
|
||||
const char * const UNDO = "ObjectViewerQt.Undo";
|
||||
const char * const REDO = "ObjectViewerQt.Redo";
|
||||
const char * const CUT = "ObjectViewerQt.Cut";
|
||||
const char * const COPY = "ObjectViewerQt.Copy";
|
||||
const char * const PASTE = "ObjectViewerQt.Paste";
|
||||
const char * const DEL = "ObjectViewerQt.Del";
|
||||
const char * const FIND = "ObjectViewerQt.Find";
|
||||
const char * const SELECT_ALL = "ObjectViewerQt.SelectAll";
|
||||
const char * const GOTO_POS = "ObjectViewerQt.Goto";
|
||||
|
||||
const char * const SETTINGS = "ObjectViewerQt.Settings";
|
||||
const char * const TOGGLE_FULLSCREEN = "ObjectViewerQt.ToggleFullScreen";
|
||||
|
||||
const char * const CLOSE = "ObjectViewerQt.Close";
|
||||
const char * const CLOSEALL = "ObjectViewerQt.CloseAll";
|
||||
const char * const CLOSEOTHERS = "ObjectViewerQt.CloseOthers";
|
||||
const char * const ABOUT = "ObjectViewerQt.About";
|
||||
const char * const ABOUT_PLUGINS = "ObjectViewerQt.AboutPlugins";
|
||||
const char * const ABOUT_QT = "ObjectViewerQt.AboutQt";
|
||||
|
||||
//settings
|
||||
const char * const SETTINGS_CATEGORY_GENERAL = "general";
|
||||
const char * const SETTINGS_CATEGORY_GENERAL_ICON = ":/icons/ic_nel_generic_settings.png";
|
||||
const char * const SETTINGS_TR_CATEGORY_GENERAL = QT_TR_NOOP("General");
|
||||
|
||||
const char * const MAIN_WINDOW_SECTION = "MainWindow";
|
||||
const char * const MAIN_WINDOW_STATE = "WindowState";
|
||||
const char * const MAIN_WINDOW_GEOMETRY = "WindowGeometry";
|
||||
const char * const QT_STYLE = "QtStyle";
|
||||
const char * const QT_PALETTE = "QtPalette";
|
||||
|
||||
const char * const LANGUAGE = "Language";
|
||||
const char * const PLUGINS_PATH = "PluginPath";
|
||||
const char * const DATA_PATH_SECTION = "DataPath";
|
||||
const char * const SEARCH_PATHS = "SearchPaths";
|
||||
const char * const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes";
|
||||
const char * const LEVELDESIGN_PATH = "LevelDesignPath";
|
||||
const char * const ASSETS_PATH = "AssetsPath";
|
||||
const char * const REMAP_EXTENSIONS = "RemapExtensions";
|
||||
|
||||
const char * const LOG_SECTION = "LogSettings";
|
||||
const char * const LOG_ERROR = "LogError";
|
||||
const char * const LOG_WARNING = "LogWarning";
|
||||
const char * const LOG_DEBUG = "LogDebug";
|
||||
const char * const LOG_ASSERT = "LogAssert";
|
||||
const char * const LOG_INFO = "LogInfo";
|
||||
|
||||
//resources
|
||||
const char * const ICON_NEL = ":/core/images/nel.png";
|
||||
const char * const ICON_SETTINGS = ":/core/images/preferences.png";
|
||||
const char * const ICON_PILL = ":/core/icons/ic_nel_pill.png";
|
||||
const char * const ICON_OPEN = ":/core/icons/ic_nel_open.png";
|
||||
const char * const ICON_NEW = ":/core/icons/ic_nel_new.png";
|
||||
const char * const ICON_SAVE = ":/core/icons/ic_nel_save.png";
|
||||
const char * const ICON_SAVE_AS = ":/core/icons/ic_nel_save_as.png";
|
||||
const char * const ICON_CRASH = ":/core/icons/ic_nel_crash.png";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Core
|
||||
|
||||
#endif // CORE_CONSTANTS_H
|
|
@ -13,15 +13,20 @@ SET(OVQT_PLUG_TRANSLATION_MANAGER_HDR translation_manager_plugin.h
|
|||
translation_manager_main_window.h
|
||||
translation_manager_settings_page.h
|
||||
translation_manager_editor.h
|
||||
source_selection.h
|
||||
ftp_selection.h
|
||||
editor_worksheet.h
|
||||
extract_new_sheet_names.h
|
||||
extract_bot_names.h)
|
||||
|
||||
SET(OVQT_PLUG_TRANSLATION_MANAGER_UIS translation_manager_settings_page.ui
|
||||
translation_manager_main_window.ui)
|
||||
translation_manager_main_window.ui
|
||||
source_selection.ui
|
||||
ftp_selection.ui)
|
||||
|
||||
SET(QT_USE_QTGUI TRUE)
|
||||
SET(QT_USE_QTOPENGL TRUE)
|
||||
SET(QT_USE_QTNETWORK TRUE)
|
||||
|
||||
QT4_WRAP_CPP(OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC ${OVQT_PLUG_TRANSLATION_MANAGER_HDR})
|
||||
QT4_WRAP_UI(OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS ${OVQT_PLUG_TRANSLATION_MANAGER_UIS})
|
||||
|
@ -34,7 +39,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC})
|
|||
|
||||
ADD_LIBRARY(ovqt_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS})
|
||||
|
||||
TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nel3d nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nel3d nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} )
|
||||
|
||||
NL_DEFAULT_PROPS(ovqt_plugin_translation_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: Translation Manager")
|
||||
NL_ADD_RUNTIME_FLAGS(ovqt_plugin_translation_manager)
|
||||
|
|
|
@ -139,14 +139,14 @@ void CEditorWorksheet::save()
|
|||
colname = wk_file.getData(0, j + colIdx);
|
||||
|
||||
rowIdf = uint(i + 1);
|
||||
if(wk_file.findRow(j + colIdx, colname, rowIdf))
|
||||
if(wk_file.findRow(j + colIdx, colname, rowIdf)) // search for the row
|
||||
{
|
||||
if(wk_file.getData(i + 1, j + colIdx) != tvalue)
|
||||
if(wk_file.getData(i + 1, j + colIdx) != tvalue) // verify the current value
|
||||
{
|
||||
wk_file.setData(i + 1, j + colIdx, tvalue);
|
||||
wk_file.setData(i + 1, j + colIdx, tvalue); // change the value
|
||||
}
|
||||
} else {
|
||||
wk_file.setData(i + 1, j + colIdx, tvalue);
|
||||
wk_file.setData(i + 1, j + colIdx, tvalue); // insert the value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,67 +382,74 @@ void CEditorWorksheet::extractWords(QString filename, QString columnId, IWordLis
|
|||
}
|
||||
}
|
||||
|
||||
bool CEditorWorksheet::compareWorksheetFile(QString filename)
|
||||
{
|
||||
STRING_MANAGER::TWorksheet wk_file;
|
||||
int colIndex = 0;
|
||||
if(loadExcelSheet(filename.toStdString(), wk_file, true) == true)
|
||||
{
|
||||
if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE"))
|
||||
{
|
||||
colIndex = 1;
|
||||
}
|
||||
if(wk_file.ColCount - colIndex != table_editor->columnCount())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for(int i = 0; i < table_editor->columnCount(); i++)
|
||||
{
|
||||
QString item = table_editor->horizontalHeaderItem(i)->text();
|
||||
ucstring itemC = wk_file.getData(0, i+ colIndex);
|
||||
if(item.toStdString() != itemC.toString())
|
||||
{
|
||||
nlwarning(item.toStdString().c_str());
|
||||
nlwarning(itemC.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEditorWorksheet::mergeWorksheetFile(QString filename)
|
||||
{
|
||||
STRING_MANAGER::TWorksheet wk_file;
|
||||
if(loadExcelSheet(filename.toStdString(), wk_file, true) == true)
|
||||
{
|
||||
bool hasHashValue = false;
|
||||
bool hasHashValue = false;
|
||||
int colIndex = 0;
|
||||
if(wk_file.getData(0, 0) == ucstring("*HASH_VALUE"))
|
||||
{
|
||||
table_editor->setColumnCount(wk_file.ColCount - 1);
|
||||
hasHashValue = true;
|
||||
} else {
|
||||
table_editor->setColumnCount(wk_file.ColCount);
|
||||
}
|
||||
table_editor->setRowCount(wk_file.size() - 1);
|
||||
|
||||
// read columns name
|
||||
for(unsigned int i = 0; i < wk_file.ColCount; i++)
|
||||
{
|
||||
if(hasHashValue && i == 0)
|
||||
{
|
||||
// we don't show the column with hash value
|
||||
} else {
|
||||
QTableWidgetItem *col = new QTableWidgetItem();
|
||||
ucstring col_name = wk_file.getData(0, i);
|
||||
col->setText(tr(col_name.toString().c_str()));
|
||||
if(hasHashValue)
|
||||
{
|
||||
table_editor->setHorizontalHeaderItem(i - 1, col);
|
||||
} else {
|
||||
table_editor->setHorizontalHeaderItem(i, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colIndex = 1;
|
||||
}
|
||||
// read rows
|
||||
for(unsigned int i = 1; i < wk_file.size(); i++)
|
||||
{
|
||||
for(unsigned int j = 0; j < wk_file.ColCount; j++)
|
||||
// search with the first column
|
||||
ucstring rowId = wk_file.getData(i,colIndex);
|
||||
QList<QTableWidgetItem*> search_results = table_editor->findItems(tr(rowId.toString().c_str()), Qt::MatchExactly);
|
||||
if(search_results.size() == 0)
|
||||
{
|
||||
if(hasHashValue && j == 0)
|
||||
{
|
||||
// we don't show the column with hash value
|
||||
} else {
|
||||
QTableWidgetItem *row = new QTableWidgetItem();
|
||||
ucstring row_value = wk_file.getData(i, j);
|
||||
row->setText(tr(row_value.toString().c_str()));
|
||||
if(hasHashValue)
|
||||
{
|
||||
table_editor->setItem(i - 1, j - 1, row);
|
||||
} else {
|
||||
table_editor->setItem(i - 1, j, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QErrorMessage error;
|
||||
error.showMessage("This file is not a worksheet file.");
|
||||
error.exec();
|
||||
}
|
||||
|
||||
const int lastRow = table_editor->rowCount();
|
||||
table_editor->setRowCount(lastRow + 1);
|
||||
for(unsigned int j = 0; j < table_editor->columnCount(); j++)
|
||||
{
|
||||
ucstring rowValue = wk_file.getData(i, j + colIndex); // get the value
|
||||
QTableWidgetItem *row = new QTableWidgetItem();
|
||||
row->setText(QString(rowValue.toString().c_str())); // set the value in table item
|
||||
table_editor->setItem(lastRow, j, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QErrorMessage error;
|
||||
error.showMessage("This file is not a worksheet file.");
|
||||
error.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void CEditorWorksheet::setCurrentFile(QString filename)
|
||||
|
@ -514,11 +521,7 @@ bool CEditorWorksheet::isSheetTable(QString type)
|
|||
column_name = "sphrase ID";
|
||||
} else if(type.toAscii() == Constants::WK_PLACE) {
|
||||
column_name = "placeId";
|
||||
} else if(type.toAscii() == Constants::WK_CONTINENT) {
|
||||
column_name = "placeId";
|
||||
} else if(type.toAscii() == Constants::WK_STABLE) {
|
||||
column_name = "placeId";
|
||||
}
|
||||
}
|
||||
bool status = true;
|
||||
if(table_editor->horizontalHeaderItem(0)->text() != column_name
|
||||
|| table_editor->horizontalHeaderItem(1)->text() != "name")
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
void saveAs(QString filename);
|
||||
void activateWindow();
|
||||
void mergeWorksheetFile(QString filename);
|
||||
bool compareWorksheetFile(QString filename);
|
||||
void extractBotNames(list<string> filters, string level_design_path, NLLIGO::CLigoConfig ligoConfig);
|
||||
void extractWords(QString filename, QString columnId, IWordListBuilder &wordListBuilder);
|
||||
bool isBotNamesTable();
|
||||
|
|
|
@ -141,7 +141,6 @@ bool CRegionPrimWordListBuilder::buildWordList(std::vector<string> &allWords, st
|
|||
// avoid duplicate
|
||||
if(allWordSet.insert(primName).second)
|
||||
{
|
||||
nlinfo(primName.c_str()); //TODO: delete
|
||||
allWords.push_back(primName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "translation_manager_main_window.h"
|
||||
#include "translation_manager_constants.h"
|
||||
#include "editor_worksheet.h"
|
||||
#include "ftp_selection.h"
|
||||
|
||||
// Project system includes
|
||||
#include "../core/icore.h"
|
||||
|
@ -114,20 +115,15 @@ void CMainWindow::createToolbar()
|
|||
connect(extractSphraseWordsAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
|
||||
wordsExtractionMapper->setMapping(extractSphraseWordsAct, tr(Constants::WK_SPHRASE));
|
||||
// extract place and region names
|
||||
QAction *extractPlaceNamesAct = wordsExtractionMenu->addAction("&Extract place and region names...");
|
||||
extractPlaceNamesAct->setStatusTip(tr("Extract place and region names"));
|
||||
QAction *extractPlaceNamesAct = wordsExtractionMenu->addAction("&Extract place names...");
|
||||
extractPlaceNamesAct->setStatusTip(tr("Extract place names from primitives"));
|
||||
connect(extractPlaceNamesAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
|
||||
wordsExtractionMapper->setMapping(extractPlaceNamesAct, tr(Constants::WK_PLACE));
|
||||
// extract continent names
|
||||
QAction *extractContinentNamesAct = wordsExtractionMenu->addAction("&Extract continent names...");
|
||||
extractContinentNamesAct->setStatusTip(tr("Extract continent names"));
|
||||
connect(extractContinentNamesAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
|
||||
wordsExtractionMapper->setMapping(extractContinentNamesAct, tr(Constants::WK_CONTINENT));
|
||||
// extract stable names
|
||||
QAction *extractStableNamesAct = wordsExtractionMenu->addAction("&Extract stable names...");
|
||||
extractStableNamesAct->setStatusTip(tr("Extract stable names"));
|
||||
connect(extractStableNamesAct, SIGNAL(triggered()), wordsExtractionMapper, SLOT(map()));
|
||||
wordsExtractionMapper->setMapping(extractStableNamesAct, tr(Constants::WK_STABLE));
|
||||
// Merge options
|
||||
// -----------------------------
|
||||
QAction *mergeSingleFileAct = wordsExtractionMenu->addAction("&Merge worksheet file...");
|
||||
mergeSingleFileAct->setStatusTip(tr("Merge worksheet file from local or remote directory"));
|
||||
connect(mergeSingleFileAct, SIGNAL(triggered()), this, SLOT(mergeSingleFile()));
|
||||
// Windows menu
|
||||
windowMenu = new QMenu(tr("&Windows..."), _ui.toolBar);
|
||||
windowMenu->setIcon(QIcon(Core::Constants::ICON_PILL));
|
||||
|
@ -375,16 +371,6 @@ void CMainWindow::extractWords(QString typeq)
|
|||
builderP.PrimFilter.push_back("region_*.primitive");
|
||||
builderP.PrimFilter.push_back("indoors_*.primitive");
|
||||
isSheet = false;
|
||||
} else if(typeq.toAscii() == Constants::WK_CONTINENT) {
|
||||
column_name = "placeId";
|
||||
builderP.PrimPath = primitives_path;
|
||||
builderP.PrimFilter.push_back("continent_*.primitive");
|
||||
isSheet = false;
|
||||
} else if(typeq.toAscii() == Constants::WK_STABLE) {
|
||||
column_name = "placeId";
|
||||
builderP.PrimPath = primitives_path;
|
||||
builderP.PrimFilter.push_back("stable_*.primitive");
|
||||
isSheet = false;
|
||||
}
|
||||
|
||||
if(isSheet)
|
||||
|
@ -454,6 +440,58 @@ void CMainWindow::extractBotNames()
|
|||
}
|
||||
}
|
||||
|
||||
void CMainWindow::mergeSingleFile()
|
||||
{
|
||||
CEditor* editor_window = qobject_cast<CEditor*>(_ui.mdiArea->currentSubWindow());
|
||||
CSourceDialog *dialog = new CSourceDialog(this);
|
||||
map<QListWidgetItem*, int> methods;
|
||||
// create items
|
||||
QListWidgetItem* local_item = new QListWidgetItem();
|
||||
local_item->setText("Local directory");
|
||||
methods[local_item] = 0;
|
||||
QListWidgetItem* ftp_item = new QListWidgetItem();
|
||||
ftp_item->setText("From a FTP server");
|
||||
methods[ftp_item] = 1;
|
||||
|
||||
dialog->setSourceOptions(methods);
|
||||
dialog->show();
|
||||
dialog->exec();
|
||||
if(dialog->selected_item == local_item) // Local directory
|
||||
{
|
||||
QString file_name;
|
||||
if (_ui.mdiArea->subWindowList().size() > 0)
|
||||
{
|
||||
file_name = QFileDialog::getOpenFileName(this);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if(QString(editor_window->widget()->metaObject()->className()) == "QTableWidget") // Sheet Editor
|
||||
{
|
||||
editor_window->activateWindow();
|
||||
CEditorWorksheet* current_window = qobject_cast<CEditorWorksheet*>(editor_window);
|
||||
if(current_window->windowFilePath() == file_name)
|
||||
return;
|
||||
if(current_window->compareWorksheetFile(file_name))
|
||||
{
|
||||
current_window->mergeWorksheetFile(file_name);
|
||||
} else {
|
||||
QErrorMessage error;
|
||||
error.showMessage(QString("The file: %1 has different columns from the current file in editor.").arg(file_name));
|
||||
error.exec();
|
||||
}
|
||||
}
|
||||
} else if(dialog->selected_item == ftp_item) { // Ftp directory
|
||||
CFtpSelection* ftp_dialog = new CFtpSelection(this);
|
||||
ftp_dialog->show();
|
||||
ftp_dialog->exec();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CMainWindow::readSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
|
|
|
@ -38,9 +38,11 @@
|
|||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QMdiSubWindow>
|
||||
#include <QtCore/QSignalMapper>
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
|
||||
#include "translation_manager_editor.h"
|
||||
#include "source_selection.h"
|
||||
#include "ui_translation_manager_main_window.h"
|
||||
#include <set>
|
||||
|
||||
|
@ -86,7 +88,7 @@ private Q_SLOTS:
|
|||
void activeSubWindowChanged();
|
||||
void setActiveSubWindow(QWidget *window);
|
||||
void updateWindowsList();
|
||||
|
||||
void mergeSingleFile();
|
||||
void debug(QString text); // TODO
|
||||
private:
|
||||
void openWorkFile(QString file);
|
||||
|
|
Loading…
Reference in a new issue