xwicked |
Дата 8.11.2014, 21:34 |
|
Цитата(Гость @ 5.11.2014, 9:26) если сделаешь возможность компиляции в exe, цены тебе не будет) На самом деле в этом нет ничего сложного. Но есть небольшие но. Я определил стратегию развития проекта на максимальную переносимость, то есть не использовать платформенно-зависимый код. Так как я прислушиваюсь к каждому совету, то я могу переопределить основные и второстепенные планы совершенствования ввиду постепенно нарастающей популярности проекта. |
Гость |
Дата 5.11.2014, 8:26 |
|
если сделаешь возможность компиляции в exe, цены тебе не будет) |
xwicked |
Дата 3.11.2013, 20:58 |
|
По-тихоньку идёт совершенствование программы. И сейчас от основного кода был отделён модуль Тестирование.
Пршу протестировать на наличие ошибок первую бета-версию: 1.6.2.0. Для полноценной проверки может потребоваться прошлая версия 1.5.2.
Благодарю за ответы! |
xwicked |
Дата 17.11.2012, 18:42 |
|
1.5.2 - скачать Цитата - Теперь сохранение свойств программы происходит при каждом их изменении; - Убрана чувствительность регистра ответа в вопросе типа "Ввод слова(предложения)"; - Исправлена ошибка ограничения количества вопросов в режиме редактирования; - Добавлено новое поле статистики "Количество заданных вопросов из общего числа"; - Исправлена ошибка, когда нельзя было ввести вариант ответа, при увеличении и обратном уменьшении изображения, в вопросе "Ввод слова(предложения)"; - Изменено и отлажено автоматическое определение пропущенных вопросов, при тестировании; - Добавлена дополнительная детализация к статистике протестировавшихся; В следующей версии я хочу прикрутить веб-интрефейс тестируемого. Собираюсь использовать JavaScript(или Java? а возможно C++?) + свой простейший веб-сервер(на C++ для AJAX). Какие вопросы / проблемы меня могут поджидать?
Благодарю за ответы! |
xwicked |
Дата 19.2.2012, 1:22 |
|
Новая и последняя на данный момент версия 1.0.0. Здесь я постарался конкретно. Изменения: Цитата - Добавились новые возможности: проверка наличия новой версии через интернет; печать теста; печать статистики; экспорт тестов в HTML, RTF, PDF, PostScript, простой текстовый формат; - Добавлено использование системных временных каталогов для размещения временных файлов; - Изменилось расположение файла статистики по-умолчанию на домашний каталог пользователя; - Изменилась кодировка файла статистики на UTF-8: - Изменилась кодировка импортируемого текстового файла на UTF-8; //Новые константы //Типы вопросов для определения содержимого переменной QVariant #define V_TYPE_ONE_ANSWER QVariant::Int #define V_TYPE_MANY_ANSWERS QVariant::ByteArray #define V_TYPE_ENTER_WORD QVariant::String #define V_TYPE_ENTER_NUMBER QVariant::Double #define V_TYPE_INSTALLATION_SEQUENCE QVariant::StringList
//Перевод слов в rtf-unicode QString ShelkTest::WordToUnicode(QString sWord) { QString sTemp, sNum; sTemp.clear(); for (int i = 0; i < sWord.length(); i++) { sNum.setNum(sWord.at(i).unicode()); sTemp.append("\\u" + sNum + "?"); } return sTemp; }
Далее, задействовал webkit:private: QWebView *wvUpdate;//Для обновления и печати :) , так как QTextEdit и QTextBrowser не могут отображать элементы ввода(текст, переключатель, флажок), для формирования правильной html-ки. Раз уж было принято решение добавить новую зависимость от библиотеки QtWebkit, то на его же основе я сделал проверку наличия новой версии через интернет, смотрим:void ShelkTest::slotCheckForUpdates() { connect(wvUpdate, SIGNAL(loadFinished(bool)), SLOT(slotMakeCheckUpdates(bool))); wvUpdate->load(QUrl("http://labfreetech.org/shelk_1.0.0.html")); }
void ShelkTest::slotMakeCheckUpdates(bool bError) { if (bError && wvUpdate->page()->findText("new_version")) QMessageBox::information(0, tr("Information"), tr("On the official website available a new version!")); else QMessageBox::information(0, tr("Information"), tr("You have the latest version!")); disconnect(wvUpdate, SIGNAL(loadFinished(bool)), 0, 0); } Как видно - всё просто. Если текст "new_version" найден в загруженной html-ке, то есть новая версия Чтобы сделать всё так, как я задумал - пришлось использовать новый метод disconnect, который я ранее не использовал и всё получилось.
Теперь за кодом можно наблюдать не дожидаясь релиза. В git создана новая ветка current. Скачать. |
xwicked |
Дата 14.2.2012, 23:03 |
|
Здравствуйте! Представляю новую версию программы 0.4.7. Добавился файл с константами://const.h //Определение путей констант, в соответствии с системой #if defined(Q_WS_WIN)
#define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwst" #define PATH_SHARE_DOC QApplication::applicationDirPath() #define PATH_SHARE_APP QApplication::applicationDirPath() #define PATH_TMP QApplication::applicationDirPath()
#elif defined(Q_WS_X11)
#define PATH_TMP_SET "/tmp/shelk-test-0.4.7/settings.xwst" #define PATH_SHARE_DOC "/usr/share/doc/shelk-test-0.4.7" #define PATH_SHARE_APP "/usr/share/shelk-test-0.4.7" #define PATH_TMP "/tmp/shelk-test-0.4.7"
#elif defined(Q_WS_MAC)
#define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwst" #define PATH_SHARE_DOC QApplication::applicationDirPath() #define PATH_SHARE_APP QApplication::applicationDirPath() #define PATH_TMP QApplication::applicationDirPath()
#endif
#define MODE_VIEW true #define MODE_EDIT false
#define LANGUAGE_RUSSIAN true #define LANGUAGE_ENGLISH false
#define TOOLBAR_SHOW true #define TOOLBAR_HIDE false
#define STATISTICS_FIELD_SHOW true #define STATISTICS_FIELD_HIDE false
#define VIEW_RUSSIAN 0 #define VIEW_ENGLISH 1 #define EDIT_RUSSIAN 2 #define EDIT_ENGLISH 3
//Типы вопросов #define TYPE_ONE_ANSWER "1" #define TYPE_MANY_ANSWERS "2" #define TYPE_ENTER_WORD "3" #define TYPE_ENTER_NUMBER "4" #define TYPE_INSTALLATION_SEQUENCE "5"
Добавилась новая структура, но в коде она пока не задействована://Структура показа полей статистики struct TStateFieldStatistics { bool bUserName,//Имя пользователя bNameTest,//Название теста bTotalQuestions,//Всего вопросов bCorrectAnswers,//Правильных ответов bWrongAnswers,//Неправильных ответов bTotalPoints,//Всего баллов bScore,//Оценка bDate,//Дата bTimeBegin,//Время начала bTimeEnd,//Время окончания bElapsedTime;//Прошедшее время }; Оптимизирована функция изменения шрифта(была 195 строк): bool Accept; QFont TextFont; TextFont = TextQuestion->textCursor().charFormat().font(); TextFont = QFontDialog::getFont(&Accept, TextFont);
if(Accept) { QTextCharFormat tcf; tcf.setFont(TextFont); TextQuestion->textCursor().setCharFormat(tcf); cbFont.setCurrentFont(TextFont); } else return 1; Скачать |
Алексей1153 |
Дата 6.2.2012, 13:48 |
|
xwicked, да не, начинай уже осваивать ) Потом же исправлять и глюки вылавливать придётся.
Открою маленький секрет: для компилятора C++ нет разницы, class это, struct или union - у них всех всё одинаково работает, они имеют конструктор и деструктор. Тонкости в различии : union и struct по умолчанию устанавливают доступ public своему содержимому, а class - private. Ну и в union у объединённых переменных вроде не может быть явного конструктора/деструктора, но это уже к нашему случаю не относится, так как это внутренние данные, а не сама структура. |
xwicked |
Дата 6.2.2012, 13:24 |
|
Алексей1153, благодарю, но конструкторы я буду осваивать для классов, с приходом полного ООП в эту программу |
Алексей1153 |
Дата 6.2.2012, 8:24 |
|
Цитата(xwicked @ 26.1.2012, 23:15) 0.4.4. Исправлено 15 ошибок(!). Появились 2-е структуры: //Структура файла свойств struct sFileSettings { bool gRegimeViewing,//true - Режим просмотра, false - Режим редактирования LanguageProgram,//Язык программы bStandardPanel,//Состояние показа стандартной панели bEditPanel,//Состояние показа панели редактирования bFormatPanel,//Состояние показа панели форматирования bTimePanel,//Состояние показа панели времени bPointPanel,//Состояние показа панели баллов bLimitTime,//Ограничение времени bAutoStartTest;//Автоматический запуск QString RegimePassword;//Пароль режима };
ой ой! Исправлено 15 ошибок, а добавлено ещё 15
Совсем-совсем не советую так оформлять структуры. Более того - не только структуры, а даже просто так объявлять переменные!
Правильно так:
struct sFileSettings { bool gRegimeViewing;//true - Режим просмотра, false - Режим редактирования bool LanguageProgram;//Язык программы bool bStandardPanel;//Состояние показа стандартной панели bool bEditPanel;//Состояние показа панели редактирования bool bFormatPanel;//Состояние показа панели форматирования bool bTimePanel;//Состояние показа панели времени bool bPointPanel;//Состояние показа панели баллов bool bLimitTime;//Ограничение времени bool bAutoStartTest;//Автоматический запуск QString RegimePassword;//Пароль режима
//КОНСТРУКТОР ОБЯЗАТЕЛЬНО sFileSettings() { gRegimeViewing=false; LanguageProgram=false; bStandardPanel=false; bEditPanel=false; bFormatPanel=false; bTimePanel=false; bPointPanel=false; bLimitTime=false; bAutoStartTest=false; }
};
Но у меня это всё выглядело бы так (не из стремления экономить, а для удобства обнуления флагов):
struct sFileSettings { union { UINT32 m_AllFlags; struct { UINT32 gRegimeViewing :1;//true - Режим просмотра, false - Режим редактирования UINT32 LanguageProgram :1;//Язык программы UINT32 bStandardPanel :1;//Состояние показа стандартной панели UINT32 bEditPanel :1;//Состояние показа панели редактирования UINT32 bFormatPanel :1;//Состояние показа панели форматирования UINT32 bTimePanel :1;//Состояние показа панели времени UINT32 bPointPanel :1;//Состояние показа панели баллов UINT32 bLimitTime :1;//Ограничение времени UINT32 bAutoStartTest :1;//Автоматический запуск UINT32 :23;//резерв }; };
QString RegimePassword;//Пароль режима
sFileSettings() { m_AllFlags=0; } };
Цитата(xwicked @ 26.1.2012, 23:15) QString str1, str2; QByteArray ba1, ba2;
- та же мигня! Что экономишь то ?
а в структуре sShelkTestVar у тебя не инициализированные в конструкторе указатели - это вообще ахтунг ) |
xwicked |
Дата 6.2.2012, 1:54 |
|
0.4.4. Исправлено 15 ошибок(!). Появились 2-е структуры://Структура файла свойств struct sFileSettings { bool gRegimeViewing,//true - Режим просмотра, false - Режим редактирования LanguageProgram,//Язык программы bStandardPanel,//Состояние показа стандартной панели bEditPanel,//Состояние показа панели редактирования bFormatPanel,//Состояние показа панели форматирования bTimePanel,//Состояние показа панели времени bPointPanel,//Состояние показа панели баллов bLimitTime,//Ограничение времени bAutoStartTest;//Автоматический запуск QString RegimePassword;//Пароль режима };
//Структура теста struct sShelkTestVar { QString sNameTest,//Название теста sAllPoint,//Все баллы строкой sMidPoint,//Средний балл строкой sCurrentPoint,//Текущий балл строкой sTypeQuestion,//Тип вопроса TestPassword,//Пароль теста StatNameTest,//Имя пользователя в статистике sQuestion,//Текст вопроса sTimeStart;//Время начала
int CountQuestion,//Количество вопросов iNumberQuestion,//Номер вопроса iNumberTest,//Номер теста AllPoint,//Общий балл MidPoint,//Средний балл CurrentPoint,//Текущий балл AllPointCheck,//Общий балл для проверки AllTime,//Общее время MidTime,//Среднее время CurrentTime,//Текущее время i5First;//Номер прошлого выделенного ответа (установка последовательности)
QVector<double> *iRangeFirst,//Начальное значение диапазона (ввод числа) *iRangeLast;//Конечное значение диапазона (ввод числа)
QStringList ListQuestions,//Список вопросов slTableNumber,//Список номеров таблиц в базе тестов slQuestionType,//Список типов вопросов slPoint,//Список баллов slTime;//Список времени
QVector<QVariant> *ListRightAnswer,//Список правильных ответов *ListCheckRightAnswer;//Список правильных ответов для проверки
QVector<QStringList> *ListAnswers;//Список ответов QVector<QByteArray> *ListImages;//Список изображений QVector<QFont> *ListFonts;//Список шрифтов QSqlDatabase db;//База данных тестов
QTimer TimerTest, TimerTestLabel; QTime TimeTestCurrent, TimeTestAll; }; Их было решено использовать сразу, после выхода кроссворда за предел стека Введение вектора типа QVariant позволило функцию проверки ответов максимально упростить и вынести отдельно:bool ShelkTest::MakeCheckRightAnswer(int iIndex) { int iTypeR; QString str1, str2; QByteArray ba1, ba2;
iTypeR = vShelkTestVar->ListRightAnswer->at(iIndex).type();
if(iTypeR == QVariant::Int) { if(vShelkTestVar->ListRightAnswer->at(iIndex).toInt() == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toInt()) return true; else return false; }
if(iTypeR == QVariant::Double) { if(vShelkTestVar->ListRightAnswer->at(iIndex).toDouble() == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toDouble()) return true; else return false; }
if(iTypeR == QVariant::String) { if(vShelkTestVar->ListRightAnswer->at(iIndex).toString() == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toString()) return true; else return false; }
if(iTypeR == QVariant::ByteArray) { ba1.append(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray()); ba2.append(vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray()); str1.append(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray()); str2.append(vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray());
if(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray() == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray()) return true; else return false; }
if(iTypeR == QVariant::StringList) { if(vShelkTestVar->ListRightAnswer->at(iIndex).toStringList() == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toStringList()) return true; else return false; } return false; } Несмотря на то, что QVariant не рекомендуется использовать из за большого потребления памяти, так как он позволяет хранить даже контейнеры(!), я решил сделать это. Использование один раз в масштабах простой программы для создания тестов показала свою рентабельность. Скачать |
Просмотр темы полностью (откроется в новом окне) |
|