Compare commits

..

21 Commits

Author SHA1 Message Date
678bdbab47 Merge branch 'release/0.2.0' 2026-01-14 10:51:21 +01:00
b059379518 Version 0.2.0. With project description README.md and added CHANGELOG.md. 2026-01-14 10:51:01 +01:00
c9441d7eca Search dialog to select row(s). Closes #15. 2026-01-12 15:03:15 +01:00
bc5070a1a5 TableView can now be sorted by column (using QSortFilterProxyModel). Closes #8. 2026-01-12 10:21:49 +01:00
d22c0e466c Added two CSV files to test import and export capabilities. 2026-01-11 13:17:30 +01:00
1c3bb6da30 Merged CSV feature branch of GenericCore into develop. 2026-01-06 10:21:51 +01:00
fb57727286 Saving changed items before starting the updater. 2026-01-06 10:18:43 +01:00
85836dfda0 Simple import/export from/to CSV files. Closes #7. 2026-01-06 10:08:55 +01:00
b2bc725eff Refactoring: Gathered model meta data (role name, data types) in a central location. Closes #16. 2026-01-01 10:33:41 +01:00
9c4c77ef07 Items can be saved in the standard location as "items.json" and are loaded automatically on startup (if file exists). Closes #9. 2025-12-23 14:05:46 +01:00
01f8ff01fc Creating, editing and deleting model items can now be un-/redone. A Save/Discard/Cancel dialog is shown if the undo stack is unclean (No saving to file functionality yet). Closes #10. 2025-12-22 12:21:30 +01:00
eedd15b960 Model items can be created, edited and deleted. Closes #13, Closes #11 2025-12-08 15:14:15 +01:00
5a7e2637ff Displaying a basic read-only table model. Closes #12 2025-12-03 11:11:31 +01:00
daae7e8405 Disabled GUI translations, added "About" dialogs & updated umbrella project version to 0.1.0 2025-11-04 21:25:54 +01:00
a159181074 Merge branch 'feature/installer' into develop 2025-11-01 11:20:29 +01:00
a826dc2478 Added menu item "Help/Check for update" to ask the QtMaintenanceTool if an update is available and show a dialog to trigger the update from within the application. 2025-11-01 10:56:50 +01:00
fc083f527a Installer works on Linux via command line script build.sh. Based on legacy projects needs refactoring. (./build.sh 0.0.3 linux GenericQtClient org.working_copy.genericQtClient) 2025-10-29 11:49:14 +01:00
0acc36454c Added application icon (and other icons) and little source code formatting. 2025-10-27 11:13:00 +01:00
7fad2ec1d5 Updated the core submodule and make the tests pass (in a very crude way). 2025-10-03 11:17:03 +02:00
28477732f1 Make QString pretty printable in test results. 2025-10-03 11:16:03 +02:00
588414be83 Umbrella project for an GenericWidgets client using the GenericCore library (Using submodules). With a GoogleTest project testing GenericCore::toString() method. 2025-10-02 20:28:38 +02:00
29 changed files with 600 additions and 0 deletions

10
.clang-format Normal file
View File

@ -0,0 +1,10 @@
BasedOnStyle: Chromium
ColumnLimit: 100
AllowShortLoopsOnASingleLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
BreakConstructorInitializersBeforeComma: true
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: true
BraceWrapping:
AfterControlStatement: Always
InsertBraces: true

84
.gitignore vendored Normal file
View File

@ -0,0 +1,84 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
*.qbs.user*
CMakeLists.txt.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe
# Directories with generated files
.moc/
.obj/
.pch/
.rcc/
.uic/
/build*/
_build*/
_output/*

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "libs/GenericCore"]
path = libs/GenericCore
url = ssh://wococo1@git.working-copy.org:46100/bent/GenericQtClientCore.git
[submodule "UIs/GenericWidgets"]
path = UIs/GenericWidgets
url = ssh://wococo1@git.working-copy.org:46100/bent/GenericQtClientWidgets.git
[submodule "libs/3rdParty/rapidcsv"]
path = libs/3rdParty/rapidcsv
url = https://github.com/d99kris/rapidcsv.git

2
ApplicationConfig.h.in Normal file
View File

@ -0,0 +1,2 @@
#define APPLICATION_NAME "${PROJECT_NAME}"
#define APPLICATION_VERSION "${PROJECT_VERSION}"

15
CHANGELOG.md Normal file
View File

@ -0,0 +1,15 @@
# Changelog
## 0.2 - 2026-01-14
### Added
- Displaying editable table model (sortable by column)
- Modifying model data can be un-/redone
- Data is stored in JSON file and automatically loaded on application start
- Data can be imported/exported from/into CSV file
- Model rows containing specific data can be selected via "Find item(s)" dialog
## 0.1 - 2025-11-01
A simple Qt application separated into an UI frontend and backend core. With installer (for Linux for now) and option to trigger updater from within the application.

51
CMakeLists.txt Normal file
View File

@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.16)
set(TARGET_APP "GenericQtClient")
project(${TARGET_APP} VERSION 0.2.0 LANGUAGES CXX)
enable_testing()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(libs/GenericCore)
set (CORE_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/GenericCore)
configure_file(ApplicationConfig.h.in ApplicationConfig.h)
#Frontend applications
add_subdirectory(UIs/GenericWidgets)
### Tests
add_subdirectory(tests/GenericCoreTests)
### Qt installer
set(PACKAGE_FOLDER "genericQtClient")
set(TARGET_PACKAGE "org.working_copy.${PACKAGE_FOLDER}")
set(CONFIG_REPO_URL ".../${PACKAGE_FOLDER}")
set(PUSH_REPO_URL ".../${PACKAGE_FOLDER}")
string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(PLATFORM "linux")
set(BASH_COMMAND)
### quick fix for config.xml.in and installscript.qs.in:
set(ApplicationsDir @ApplicationsDir@)
set(TargetDir @TargetDir@)
set(DesktopDir @DesktopDir@)
set(HomeDir @HomeDir@)
### end of quick fix
configure_file(installer/config/config.xml.in installer/config/config.xml)
configure_file(installer/packages/defaultPackage/meta/package.xml.in installer/packages/${TARGET_PACKAGE}/meta/package.xml)
configure_file(installer/packages/defaultPackage/meta/installscript.qs.in installer/packages/${TARGET_PACKAGE}/meta/installscript.qs)
# configure_file(installer/packages/defaultPackage/meta/license.txt.in installer/packages/${TARGET_PACKAGE}/meta/license.txt)
# add_custom_command(
# OUTPUT installer/config/config.xml
# COMMAND ${BASH_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/installer/script.sh ${PROJECT_VERSION} linux ${TARGET_APP} ${TARGET_PACKAGE}
# )
# add_custom_target(installer ALL
# DEPENDS installer/config/config.xml
# )

View File

@ -1,2 +1,19 @@
# GenericQtClient
This is a Qt application which can be used as a starting point for new software projects.
Common features most Qt software clients need will be already implemented and can be easily configured for the specific needs.
## Implemented features:
- Separated UI frontend and backend core (in its own git submodules)
- Using Qt model/view framework with QT undo framework
- Saving/Loading JSON files
- CSV import/export
- installable and updateable via Qt updater framework
- only linux for now
- Qt 6 libraries must be installed on the machine to run
## Coming features:
- REST client
- Extensive use of sorting and filtering models to display data in different ways
- ...

1
UIs/GenericWidgets Submodule

Submodule UIs/GenericWidgets added at c83ba2da9d

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
assets/icons/feature.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

7
assets/icons/icons.qrc Normal file
View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>software-application.png</file>
<file>feature.png</file>
<file>no-picture-taking.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

5
assets/icons/urls.txt Normal file
View File

@ -0,0 +1,5 @@
software-application.png:
https://www.flaticon.com/free-icon/software-application_5063917
feature.png:
https://www.flaticon.com/free-icon/feature_1085784

4
installer/.env Normal file
View File

@ -0,0 +1,4 @@
# ssh url of the packages directory of the repo
PROJECT_FOLDER=""
export CONFIG_REPO_URL="/${PROJECT_FOLDER}"
export PUSH_REPO_URL="/${PROJECT_FOLDER}"

52
installer/build.sh Executable file
View File

@ -0,0 +1,52 @@
#!/bin/bash
echo amount of arguments: $#
if [[ $# -ne 4 ]]; then
echo "Build script has to be called with exactly two arguments."
echo "The version number (Major.Minor.Patch) as its first argument."
echo "... and the OS (linux, windows or macos) as the second argument"
echo "TODO: DOCUMENT ARGUMENTS 3 & 4!!!"
echo "Aborting..."
exit 1
fi
VERSION=$1
regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'
if [[ $VERSION =~ $regex ]]; then
echo "Version accepted: $VERSION"
else
echo "Version '$VERSION' is not acceptable. Aborting..."
exit 1
fi
PLATFORM=$2
# TODO refactor this to use something like PLATFORMS.contains(PLATFORM)
if [[ $PLATFORM == linux ]]; then
echo "OS: $PLATFORM"
elif [[ $PLATFORM == windows ]]; then
echo "OS: $PLATFORM"
elif [[ $PLATFORM == macos ]]; then
echo "OS: $PLATFORM"
else
echo "Platform '$PLATFORM' is not acceptable. Aborting..."
exit 1
fi
#if [[ ! -e .env ]]; then
# echo "File .env not found. Aborting..."
# exit 1
#fi
#echo "Sourcing .env file..."
#source .env
echo "calling the compile-executable.sh..."
./compile-executable.sh $1 $2 $3 $4
echo "calling the create-installer.sh..."
./create-installer.sh $1 $2 $3 $4
echo "calling the deployToRepo.sh..."
./deployToRepo.sh $1 $2 $3 $4
cd ${OLD_PWD}

59
installer/compile-executable.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/bash
echo amount of arguments: $#
if [[ $# -ne 4 ]]; then
echo "Build script has to be called with exactly two arguments."
echo "The version number (Major.Minor.Patch) as its first argument."
echo "... and the OS (linux, windows or macos) as the second argument"
echo "TODO: DOCUMENT ARGUMENTS 3 & 4!!!"
echo "Aborting..."
exit 1
fi
VERSION=$1
regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'
if [[ $VERSION =~ $regex ]]; then
echo "Version accepted: $VERSION"
else
echo "Version '$VERSION' is not acceptable. Aborting..."
exit 1
fi
PLATFORM=$2
# TODO refactor this to use something like PLATFORMS.contains(PLATFORM)
if [[ $PLATFORM == linux ]]; then
echo "OS: $PLATFORM"
#QMAKE_EXE="qmake"
COMPILER_EXE="make"
elif [[ $PLATFORM == windows ]]; then
echo "OS: $PLATFORM"
#QMAKE_EXE="$QMAKE_LOCATION/qmake"
#COMPILER_EXE="$MINGWROOT/bin/mingw32-make"
elif [[ $PLATFORM == macos ]]; then
echo "OS: $PLATFORM"
#QMAKE_EXE="qmake"
COMPILER_EXE="make"
else
echo "Platform '$PLATFORM' is not acceptable. Aborting..."
exit 1
fi
echo "Starting build ..."
OLD_PWD=$(pwd)
BUILD_DIR="_build"
echo "starting in: ${OLD_PWD}"
# if [[ -e $BUILD_DIR/$TARGET ]]; then
# echo "old build dir has old content, cleaning the build directory..."
# rm -r $BUILD_DIR/*
# fi
cd $BUILD_DIR
echo "Building in $(pwd) ..."
echo "Building whole project..."
echo "Running CMake..."
cmake -DCMAKE_BUILD_TYPE=Release ../../
echo "Compiling..."
$COMPILER_EXE

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Installer>
<Name>${PROJECT_NAME}</Name>
<Version>1.0.0</Version>
<Title>${PROJECT_NAME} Installer</Title>
<Publisher>Working-Copy Collective</Publisher>
<StartMenuDir>Utilities</StartMenuDir>
<TargetDir>@ApplicationsDir@/${PROJECT_NAME}</TargetDir>
<RemoteRepositories>
<Repository>
<Url>${CONFIG_REPO_URL}/${PLATFORM}/packages</Url>
<Enabled>1</Enabled>
<DisplayName>The ${PROJECT_NAME} repository</DisplayName>
</Repository>
</RemoteRepositories>
</Installer>

112
installer/create-installer.sh Executable file
View File

@ -0,0 +1,112 @@
#!/bin/bash
if [[ $# -ne 4 ]]; then
echo "Build script has to be called with exactly two arguments."
echo "The version number (Major.Minor.Patch) as its first argument."
echo "... and the OS (linux, windows or macos) as the second argument"
echo "TODO: DOCUMENT ARGUMENTS 3 & 4!!!"
echo "Aborting..."
exit 1
fi
VERSION=$1
regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'
if [[ $VERSION =~ $regex ]]; then
echo "Version accepted: $VERSION"
else
echo "Version '$VERSION' is not acceptable. Aborting..."
exit 1
fi
PLATFORM=$2
TARGET=$3
EXECUTABLE="$TARGET-Widgets"
BUILD_PREFIX="_build/UIs/GenericWidgets"
# TODO refactor this to use PLATFORMS.contains(PLATFORM)
if [[ $PLATFORM == linux ]]; then
echo "OS: $PLATFORM"
BUILD_DIR=$BUILD_PREFIX
elif [[ $PLATFORM == windows ]]; then
echo "OS: $PLATFORM"
BUILD_DIR="$BUILD_PREFIX/release"
elif [[ $PLATFORM == macos ]]; then
echo "OS: $PLATFORM"
BUILD_DIR=$BUILD_PREFIX
else
echo "Version '$PLATFORM' is not acceptable. Aborting..."
exit 1
fi
#if [[ ! -e .env ]]; then
# echo "File .env not found. Aborting..."
# exit 1
#fi
#echo "Sourcing .env file..."
#source .env
PACKAGENAME=$4
INSTALLER_DIR="_build/installer"
PKG_DATA_DIR="$INSTALLER_DIR/packages/$PACKAGENAME/data"
PKG_META_DIR="$INSTALLER_DIR/packages/$PACKAGENAME/meta"
ASSET_DIR="../assets/icons"
OUTPUT_DIR="../_output/installer"
if [[ -e $PKG_DATA_DIR/$TARGET ]]; then
echo "old $TARGET exe exists, cleaning the package data directory..."
rm -r $PKG_DATA_DIR/*
fi
if [[ ! -d $PKG_DATA_DIR ]]; then
echo "creating package data folder..."
mkdir -p $PKG_DATA_DIR
fi
mv $INSTALLER_DIR/packages/meta $PKG_META_DIR
echo "copying executable..."
if [[ $PLATFORM == macos ]]; then
cp -r $BUILD_DIR/$EXECUTABLE.app $PKG_DATA_DIR/$TARGET.app
else
cp $BUILD_DIR/$EXECUTABLE $PKG_DATA_DIR/$TARGET
fi
echo "copying assets..."
cp $ASSET_DIR/$TARGET.png $PKG_DATA_DIR/$TARGET.png
echo "copying license..."
cp ../LICENSE $PKG_META_DIR/license.txt
### Platform dependencies
echo "Applying platform dependencies..."
INSTALLER_APPENDIX="installer"
if [[ $PLATFORM == linux ]]; then
echo "Linux..."
# echo "Patching the config.xml"
# sed -i "s/<PLATFORM>/$PLATFORM/g" config/config.xml
elif [[ $PLATFORM == windows ]]; then
echo "Windows..."
cd $PKG_DATA_DIR
echo "Copying OpenSSL dlls..."
cp /c/Qt/Tools/OpenSSL/Win_x64/bin/libcrypto-1_1-x64.dll .
cp /c/Qt/Tools/OpenSSL/Win_x64/bin/libssl-1_1-x64.dll .
echo "Calling windeployqt..."
$QMAKE_LOCATION/windeployqt $TARGET.exe
cd -
# echo "Patching the config.xml"
# sed -i "s/<PLATFORM>/$PLATFORM/g" config/config.xml
elif [[ $PLATFORM == macos ]]; then
echo "MacOS..."
echo "Calling macdeployqt..."
INSTALLER_APPENDIX="installer.dmg"
cd $PKG_DATA_DIR
macdeployqt $TARGET.app
cd -
# echo "Patching the config.xml..."
# sed -i '' "s/<PLATFORM>/$PLATFORM/g" config/config.xml
fi
echo "running binarycreator..."
#echo "$QIF_LOCATION/binarycreator"
binarycreator -n -c $INSTALLER_DIR/config/config.xml -p $INSTALLER_DIR/packages $OUTPUT_DIR/$TARGET-$PLATFORM-$VERSION-$INSTALLER_APPENDIX-online
binarycreator -f -c $INSTALLER_DIR/config/config.xml -p $INSTALLER_DIR/packages $OUTPUT_DIR/$TARGET-$PLATFORM-$VERSION-$INSTALLER_APPENDIX-offline

44
installer/deployToRepo.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
echo amount of arguments: $#
if [[ $# -ne 4 ]]; then
echo "Build script has to be called with exactly two arguments."
echo "The version number (Major.Minor.Patch) as its first argument."
echo "... and the OS (linux, windows or macos) as the second argument"
echo "TODO: DOCUMENT ARGUMENTS 3 & 4!!!"
echo "Aborting..."
exit 1
fi
VERSION=$1
regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'
if [[ $VERSION =~ $regex ]]; then
echo "Version accepted: $VERSION"
else
echo "Version '$VERSION' is not acceptable. Aborting..."
exit 1
fi
if [[ ! -e .env ]]; then
exit 1
fi
echo "Sourcing .env file..."
source .env
PACKAGENAME=$4
PLATFORM=$2
PACKAGE_DIR="_build/installer/packages"
OUTPUT_DIR="../_output/repository"
echo "executing repo-gen..."
repogen --update -p $PACKAGE_DIR $OUTPUT_DIR
if [[ $PUSH_REPO_URL != "" ]]; then
echo "pushing package data to repo..."
echo "PUSH_REPO_URL: $PUSH_REPO_URL"
scp -r $OUTPUT_DIR/* $PUSH_REPO_URL/$PLATFORM/packages/
fi
cd ${OLD_PWD}

View File

@ -0,0 +1,24 @@
function Component() {}
Component.prototype.isDefault = function() {
return true;
}
Component.prototype.createOperations = function() {
try {
component.createOperations();
} catch (e) {
print(e);
}
if (installer.value("os") === "win")
{
component.addOperation("CreateShortcut", "@TargetDir@/${PROJECT_NAME}.exe", "@DesktopDir@/${PROJECT_NAME}.lnk");
}
if (installer.value("os") === "x11")
{
component.addOperation("CreateDesktopEntry", "/usr/share/applications/${PROJECT_NAME}.desktop", "Version=1.0\nType=Application\nTerminal=false\nCategories=Utility\nExec=@TargetDir@/${PROJECT_NAME}\nName=${PROJECT_NAME}\nIcon=@TargetDir@/${PROJECT_NAME}.png\nName[en_US]=${PROJECT_NAME}");
//component.addElevatedOperation("Copy", "/usr/share/applications/${PROJECT_NAME}.desktop", "@HomeDir@/Desktop/${PROJECT_NAME}.desktop");
}
}

View File

@ -0,0 +1 @@
The fantastic license, have you heard of the Tea Public License Agreement yet?

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<DisplayName>The application itself</DisplayName>
<Description>Installs the ${PROJECT_NAME} executable.</Description>
<Version>${PROJECT_VERSION}</Version>
<ReleaseDate>${CURRENT_DATE}</ReleaseDate>
<Licenses>
<License name="GNU General Public License Agreement" file="license.txt" />
</Licenses>
<ForcedInstallation>true</ForcedInstallation>
<Default>script</Default>
<Script>installscript.qs</Script>
</Package>

1
libs/3rdParty/rapidcsv vendored Submodule

Submodule libs/3rdParty/rapidcsv added at 03133b59e1

1
libs/GenericCore Submodule

Submodule libs/GenericCore added at c15e5425a7

View File

@ -0,0 +1,30 @@
include(FetchContent)
set(TARGET_APP "core_test")
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.17.0
)
FetchContent_MakeAvailable(googletest)
add_library(GTest::GTest INTERFACE IMPORTED)
target_link_libraries(GTest::GTest INTERFACE gtest_main)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core LinguistTools)
add_executable(${TARGET_APP} core_test.cpp)
target_include_directories(${TARGET_APP} PRIVATE ${CORE_LIB_DIR}/include)
target_link_libraries(${TARGET_APP}
PRIVATE
GTest::GTest
GenericCore)
target_link_libraries(${TARGET_APP} PUBLIC Qt${QT_VERSION_MAJOR}::Core)
add_test(core_gtests ${TARGET_APP})

View File

@ -0,0 +1,26 @@
#include <gtest/gtest.h>
#include <QString>
#include "../../libs/GenericCore/genericcore.h"
QT_BEGIN_NAMESPACE
inline void PrintTo(const QString& qString, ::std::ostream* os) { *os << qUtf8Printable(qString); }
QT_END_NAMESPACE
TEST(CoreTests, TestEqualString) {
const QString coreName("GenericCore");
const QString coreVersion("0.2.0");
const auto expected = QString("%1 (Version %2)").arg(coreName).arg(coreVersion);
auto core = std::make_unique<GenericCore>();
const auto actual = core->toString();
// const auto actual = multiply(1, 1);
ASSERT_EQ(expected, actual);
}
TEST(CoreTests, TestNotEqualString) {
const QString expected = QString("Hello from the Core!");
auto core = std::make_unique<GenericCore>();
const QString actual = core->toString();
ASSERT_NE(expected, actual);
}

View File

@ -0,0 +1,8 @@
Name,Description,Info,Factor
Item 0,This is item 0,Info of item 0,0
Item 1,This is item 1,Info of item 1,1
Item 2,This is item 2,Info of item 2,2
Item 3,This is item 3,Info of item 3,3
Item 4,This is item 4,Info of item 4,4
Item 5,This is item 5,Info of item 5,5
Item 6,This is item 6,Info of item 6,6
1 Name Description Info Factor
2 Item 0 This is item 0 Info of item 0 0
3 Item 1 This is item 1 Info of item 1 1
4 Item 2 This is item 2 Info of item 2 2
5 Item 3 This is item 3 Info of item 3 3
6 Item 4 This is item 4 Info of item 4 4
7 Item 5 This is item 5 Info of item 5 5
8 Item 6 This is item 6 Info of item 6 6

View File

@ -0,0 +1,8 @@
Name,Description,Info,Amount,Factor
Item 0,This is item 0,Info of item 0,0,0
Item 1,This is item 1,Info of item 1,1,1
Item 2,This is item 2,Info of item 2,2,2
Item 3,This is item 3,Info of item 3,3,3
Item 4,This is item 4,Info of item 4,4,4
Item 5,This is item 5,Info of item 5,5,5
Item 6,This is item 6,Info of item 6,6,6
1 Name Description Info Amount Factor
2 Item 0 This is item 0 Info of item 0 0 0
3 Item 1 This is item 1 Info of item 1 1 1
4 Item 2 This is item 2 Info of item 2 2 2
5 Item 3 This is item 3 Info of item 3 3 3
6 Item 4 This is item 4 Info of item 4 4 4
7 Item 5 This is item 5 Info of item 5 5 5
8 Item 6 This is item 6 Info of item 6 6 6