From b07d793f78dea3eb3f055dd9a8aaf00fa893ffb4 Mon Sep 17 00:00:00 2001 From: Oleg Shchelykalnov Date: Thu, 17 Feb 2011 22:15:13 +0300 Subject: [PATCH] Change UI --- Makefile.am | 2 +- configure.ac | 1 + po/POTFILES.in | 1 + po/ru.po | 92 ++++++++++----- src/Makefile.am | 10 +- src/db/db.cpp | 7 ++ src/db/db.h | 23 ++++ src/ga/Makefile.am | 4 + src/ga/fitness.h | 26 +++++ src/ga/ga.cpp | 223 ++++++++++++++++++++++++++++++++++--- src/ga/ga.h | 16 ++- src/ga/individual.cpp | 26 ++++- src/ga/individual.h | 55 +++++++-- src/logbuf.cpp | 10 +- src/main.cpp | 46 ++++---- src/main_window.cpp | 51 +++++++-- src/main_window.h | 17 +-- ui/Makefile.am | 3 + ui/main_window.glade | 253 ++++++++++++++++++++++++++++++++++++++++++ 19 files changed, 759 insertions(+), 107 deletions(-) create mode 100644 src/ga/Makefile.am create mode 100644 ui/Makefile.am create mode 100644 ui/main_window.glade diff --git a/Makefile.am b/Makefile.am index 8397578..42bbfa1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = docs po src win32 +SUBDIRS = docs po src ui win32 @INTLTOOL_DESKTOP_RULE@ diff --git a/configure.ac b/configure.ac index a9cb1d2..e07cbdf 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,7 @@ AC_CONFIG_FILES([ src/orm/Makefile po/Makefile.in win32/Makefile + ui/Makefile ]) AC_OUTPUT diff --git a/po/POTFILES.in b/po/POTFILES.in index 6e98320..4ed7d80 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -14,4 +14,5 @@ src/notebook_label_widget.cpp src/table_frame.cpp src/teachers_frame.cpp src/time_frame.cpp +ui/main_window.glade diff --git a/po/ru.po b/po/ru.po index 269e5ce..aee310c 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7,15 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: Table 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-07-12 08:56+0400\n" -"PO-Revision-Date: 2010-06-04 09:24+0300\n" +"POT-Creation-Date: 2011-02-17 22:00+0300\n" +"PO-Revision-Date: 2011-02-17 22:00+0300\n" "Last-Translator: Oleg Shchelykal'nov \n" "Language-Team: Russian\n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" -"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #. Glib::RefPtr model = m_ListBox.get_model(); #. Glib::RefPtr list_model = Glib::RefPtr::cast_dynamic(model); @@ -36,58 +37,95 @@ msgstr "Редактировать" msgid "Edit order" msgstr "Редактировать порядок" -#: ../src/main_window.cpp:17 ../src/main_window.cpp:183 -msgid "Table" -msgstr "Расписание" - -#: ../src/main_window.cpp:20 +#: ../src/main_window.cpp:48 msgid "File" msgstr "Файл" -#: ../src/main_window.cpp:27 +#: ../src/main_window.cpp:55 msgid "Run" msgstr "Запуск" -#: ../src/main_window.cpp:32 +#: ../src/main_window.cpp:60 msgid "Help" msgstr "Помощь" -#: ../src/main_window.cpp:117 +#: ../src/main_window.cpp:141 msgid "Choose file for saving database:" msgstr "Выберите файл для хранения базы данных:" -#: ../src/main_window.cpp:140 +#: ../src/main_window.cpp:159 msgid "Choose file for opening database:" msgstr "Выберите файл содержащий базу данных:" -#: ../src/main_window.cpp:189 +#: ../src/main_window.cpp:203 msgid "Time" msgstr "Время" -#: ../src/main_window.cpp:190 +#: ../src/main_window.cpp:204 msgid "Auditoruiums" msgstr "Аудитории" -#: ../src/main_window.cpp:191 +#: ../src/main_window.cpp:205 msgid "Teachers" msgstr "Преподаватели" -#: ../src/main_window.cpp:192 +#: ../src/main_window.cpp:206 msgid "Lessons" msgstr "Занятия" -#: ../src/main_window.cpp:193 +#: ../src/main_window.cpp:207 msgid "Groups" msgstr "Группы" -#: ../src/table_frame.cpp:12 -msgid "Choose" -msgstr "Выбрать" +#: ../ui/main_window.glade.h:1 +msgid "Hours" +msgstr "Часы" + +#: ../ui/main_window.glade.h:2 +msgid "Lists" +msgstr "Списки" + +#: ../ui/main_window.glade.h:3 +msgid "Loading" +msgstr "Нагрузки" + +#: ../ui/main_window.glade.h:4 +msgid "Schedule" +msgstr "Расписание" + +#: ../ui/main_window.glade.h:5 +msgid "Table" +msgstr "Расписание" + +#: ../ui/main_window.glade.h:6 +msgid "_File" +msgstr "_Файл" + +#: ../ui/main_window.glade.h:7 +msgid "_Help" +msgstr "_Помощь" + +#: ../ui/main_window.glade.h:8 +msgid "_Schedule" +msgstr "_Расписание" + +#: ../ui/main_window.glade.h:9 +msgid "toolbutton1" +msgstr "toolbutton1" + +#: ../ui/main_window.glade.h:10 +msgid "toolbutton2" +msgstr "toolbutton2" + +#: ../ui/main_window.glade.h:11 +msgid "toolbutton3" +msgstr "toolbutton3" + +#~ msgid "Choose" +#~ msgstr "Выбрать" -#: ../src/table_frame.cpp:13 -msgid "Set" -msgstr "Разместить" +#~ msgid "Set" +#~ msgstr "Разместить" -#: ../src/table_frame.cpp:14 -msgid "Drop" -msgstr "Убрать" +#~ msgid "Drop" +#~ msgstr "Убрать" diff --git a/src/Makefile.am b/src/Makefile.am index 22e78c4..66bc773 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,12 @@ table_SOURCES = auditorium_frame.cpp \ ga/fitness.cpp \ ga/ga.cpp \ ga/individual.cpp \ - groups_frame.cpp lessons_widget.cpp lessons_frame.cpp link_list_widget.cpp logbuf.cpp main.cpp main_window.cpp notebook_label_widget.cpp order_dialog.cpp table_frame.cpp teachers_frame.cpp time_frame.cpp + groups_frame.cpp \ + lessons_widget.cpp \ + lessons_frame.cpp \ + link_list_widget.cpp \ + logbuf.cpp \ + main.cpp main_window.cpp notebook_label_widget.cpp order_dialog.cpp table_frame.cpp teachers_frame.cpp time_frame.cpp noinst_HEADERS = auditorium_frame.h \ combobox_dialog.h entities_list_widget.h entry_text_dialog.h groups_frame.h lessons_widget.h lessons_frame.h link_list_widget.h logbuf.h main_window.h notebook_label_widget.h shared.h order_dialog.h table_frame.h teachers_frame.h time_frame.h @@ -13,7 +18,8 @@ AM_CXXFLAGS = \ -I$(top_srcdir) \ -DTABLE_LOCALEDIR=\"${TABLE_LOCALEDIR}\" \ -DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\" \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + -DUIDIR=\"$(pkgdatadir)/ui/\" table_CXXFLAGS = $(AM_CXXFLAGS) table_LDADD = \ $(INTLLIBS) \ diff --git a/src/db/db.cpp b/src/db/db.cpp index 41abd31..fb46b92 100755 --- a/src/db/db.cpp +++ b/src/db/db.cpp @@ -220,6 +220,13 @@ size_t DataBase::GetEntitiesIDs(const DB::Entity& ent, std::vector *arra return SQLExecArray(Glib::ustring::compose("SELECT id FROM %1 ORDER BY id", ent.m_TableName), array); } +Glib::ustring DataBase::GetEntityName(const Entity& ent, int id) +{ + Glib::ustring res; + SQLExecString(Glib::ustring::compose("SELECT name FROM %1 WHERE id = %2", ent.m_TableName, id), &res); + return res; +} + bool DataBase::IsLinkBetween(const DB::Link_N2N &link, size_t id_a, size_t id_l) { size_t res; diff --git a/src/db/db.h b/src/db/db.h index 5fe0bbc..db90cd9 100755 --- a/src/db/db.h +++ b/src/db/db.h @@ -24,6 +24,7 @@ namespace DB void ListEntity(const Entity& ent, Glib::RefPtr &list_store); void DeleteEntity(const Entity& ent, int id); void EditEntityName(const Entity& ent, int id, const Glib::ustring &new_name); + Glib::ustring GetEntityName(const Entity& ent, int id); void EditMultithr(const Entity& ent, int id, bool multithr); void ListEntityAud(const Entity& ent, Glib::RefPtr &list_store); @@ -83,6 +84,28 @@ namespace DB return 0; } + void SQLExecString(const Glib::ustring& sql, Glib::ustring *result) + { + m_Connection.SQLExecOwn(sql, CallbackString, reinterpret_cast(result)); + } + + static int CallbackString(void *result, int argc, char **argv, char **col_name) + { + if(! result) + { + throw Glib::Error(1, 0, "Null poiter to result at DB::Callback."); + } + if(argc != 1) + { + throw Glib::Error(1, 0, "Not 1 columns at DB::Callback."); + } + Glib::ustring &res = *reinterpret_cast(result); + std::clog << " [" << col_name[0] << "]=" << argv[0] << std::endl; + res = argv[0]; + return 0; + } + + template size_t SQLExecArray(const Glib::ustring& sql, std::vector *array) { std::pair*> res; diff --git a/src/ga/Makefile.am b/src/ga/Makefile.am new file mode 100644 index 0000000..f5d67e1 --- /dev/null +++ b/src/ga/Makefile.am @@ -0,0 +1,4 @@ +noinst_HEADERS = fitness.h \ + ga.h \ + individual.h + diff --git a/src/ga/fitness.h b/src/ga/fitness.h index 6b2408d..db76fba 100644 --- a/src/ga/fitness.h +++ b/src/ga/fitness.h @@ -9,8 +9,34 @@ struct Fitness :ind(ind_), errors(errors_), quality(quality_) { } + + bool operator<(const Fitness& other) const + { + if(errors < other.errors) + { + return true; + } + else + { + if(errors > other.errors) + { + return false; + } + } + return quality < other.quality; + } + + const Individual& GetIndividual() const + { + return *ind; + } + std::vector::const_iterator GetIter() const + { + return ind; + } private: std::vector::const_iterator ind; +public: size_t errors; size_t quality; }; diff --git a/src/ga/ga.cpp b/src/ga/ga.cpp index aa4d489..4918e72 100644 --- a/src/ga/ga.cpp +++ b/src/ga/ga.cpp @@ -1,20 +1,31 @@ +#include #include "ga.h" #include "../db/models.h" #include "fitness.h" +#include "individual.h" + +// коэффициенты качества +const size_t GROUP_WINDOW = 5; //"окна" в расписании групп +const size_t TEACHER_DAY = 10; //рабочие дни у преподавателей + +const size_t POPULATION_SIZE = 75; +const size_t MAX_STABLE_LOOPS = 200; + +size_t GA::A, GA::D, GA::H, GA::G, GA::T, GA::L; // База расписания (занятие в количестве проводимых часов для размещения времени и аудитории -struct TableBase +/*struct TableBase { const Task &task; //занятие - -}; +};*/ long inline db2index(const std::vector& ids, long db_index) { return std::lower_bound(ids.begin(), ids.end(), db_index) - ids.begin(); } -GA::GA(DB::DataBase &db) +GA::GA(DB::DataBase &db_) + :db(db_) { // создаём список идентификаторов БД: @@ -36,6 +47,11 @@ GA::GA(DB::DataBase &db) db.GetEntitiesIDs(DB::g_Teachers, &ids_t); ids_l.resize(db.GetEntitiesCount(DB::g_Lessons)); db.GetEntitiesIDs(DB::g_Lessons, &ids_l); + + G = ids_g.size(); + T = ids_t.size(); + L = ids_l.size(); + /* // получаем список G*T @@ -53,7 +69,7 @@ GA::GA(DB::DataBase &db) for(Gtk::TreeIter it = table_la->children().begin(); it != table_la->children().end(); it ++) { - less_aud[db2index(ids_l, it->get_value(scheme_la.f1)) * ids_a.size() + db2index(ids_a, it->get_value(scheme_la.f2))] = true; + less_aud[db2index(ids_l, it->get_value(scheme_la.f1)) * A + db2index(ids_a, it->get_value(scheme_la.f2))] = true; } } @@ -93,11 +109,9 @@ GA::GA(DB::DataBase &db) void GA::Run() { - ADH::SetSizes(A, D, H); - Individual::SetMultiAud(multi_aud); + Individual::SetGA(this); // генерируем случайную популяцию - const size_t POPULATION_SIZE = 20; std::vector population; for(size_t i = 0; i < POPULATION_SIZE; i ++) { @@ -114,7 +128,6 @@ void GA::Run() } std::cout << "Generated" << std::endl; - const size_t MAX_STABLE_LOOPS = 100; size_t loops = MAX_STABLE_LOOPS; size_t gen = 0; //цикл ГА @@ -126,26 +139,208 @@ void GA::Run() if(best_changed) { loops = MAX_STABLE_LOOPS; + std::cout << "Found new best" << std::endl; } else { loops --; } gen ++; + std::cout << "Generation: " << gen << std::endl; } + std::ofstream f("answer.txt"); + population[0].Output(f); } bool GA::Loop(std::vector *population) { std::vector fitnesses; + bool changed = false; for(std::vector::iterator it = population->begin(); it != population->end(); it ++) { - size_t errors; - size_t quality; - - // ошибки соответсвия аудиторий и занятий + size_t errors = 0; + size_t quality = 0; + + size_t i; + for(i = 0; i < table_base.size(); i ++) + { + // ошибки соответствия аудиторий и занятий + const long l = table_base[i]->l; + const long a = ADH(it->GetTable()[i]).a; + if(! less_aud[l * A + a]) + { + errors ++; + } + + // ошибки соответствия занятий многих групп + if(multi_aud[a] && (it->GetBusy()[it->GetTable()[i]] > 1)) + { + for(size_t j = i + 1; j < table_base.size(); j ++) + { + if(it->GetTable()[i] == it->GetTable()[j]) + { + if((table_base[i]->t != table_base[j]->t) || (table_base[i]->l != table_base[j]->l)) + { + errors ++; + } + } + } + } + } + + // занятость групп + i = 0; + for(size_t g = 0; g < G; g ++) + { + std::vector busy_time(D * H, false); // адресация [d + D * h] + while((i < table_base.size()) && (table_base[i]->g == g)) + { + const long d = ADH(it->GetTable()[i]).d; + const long h = ADH(it->GetTable()[i]).h; + + if(busy_time[d + D * h]) + { + errors ++; + } + else + { + busy_time[d + D * h] = true; + } + + i++; + } + + //расчёт "окон" в расписании + for(size_t d = 0; d < D; d ++) + { + bool study = false; + size_t moves = 0; + for(size_t h = 0; h < H; h ++) + { + if(busy_time[d + D * h] != study) + { + moves ++; + study = busy_time[d + D * h]; + } + } + if(study) + { + moves ++; + } + if(moves > 2) + { + // в расписании есть (moves - 2) / 2 окон + quality += GROUP_WINDOW * ((moves - 2) >> 1); + } + } + + } + + // занятость преподавателей + i = 0; + for(size_t t = 0; t < T; t ++) + { + std::vector busy_time(D * H, -1); // адресация [d + D * h], -1 нет занятий, (l * A + l) - занятие + for(i = 0; i < table_base.size(); i ++) + { + if(table_base[i]->t == t) + { + const long d = ADH(it->GetTable()[i]).d; + const long h = ADH(it->GetTable()[i]).h; + const long a = ADH(it->GetTable()[i]).a; + + if(busy_time[d + D * h] == -1) + { + busy_time[d + D * h] = table_base[i]->l * A + a; + } + else // уже есть занятие + { + if(multi_aud[a]) + { + if(busy_time[d + D * h] != (table_base[i]->l * A + a)) + { + errors ++; + } + } + else + { + errors ++; + } + } + } + } + + // оценка занятости + for(size_t d = 0; d < D; d ++) + { + bool study = false; + for(size_t h = 0; h < H; h ++) + { + if(busy_time[d + D * h] != -1) + { + study = true; + break; + } + } + if(study) + { + quality += TEACHER_DAY; + } + } + } + + //std::cout << "error: " << errors << " quality: " << quality << std::endl; + fitnesses.push_back(Fitness(it, errors, quality)); + } + + std::vector::iterator elite = std::min_element(fitnesses.begin(), fitnesses.end()); + if(&elite->GetIndividual() == &population->at(0)) + { + // лучшая особь не изменилась + changed = false; } - return false; + else + { + std::cout << "Fitness errors = " << elite->errors << " quality = " << elite->quality << std::endl; + changed = true; + } + + std::vector new_population; + new_population.push_back(elite->GetIndividual()); + + // селекция + std::vector::const_iterator> parent_pool; + for(size_t i = 0; i < POPULATION_SIZE - 1; i ++) + { + // турнирная селекция + size_t i1 = rand() % POPULATION_SIZE; + size_t i2 = rand() % POPULATION_SIZE; + parent_pool.push_back(std::min(fitnesses[i1], fitnesses[i2]).GetIter()); + } + + // создание новой популяции + while(new_population.size() < POPULATION_SIZE) + { + if(rand() % 2) + { + // мутация + size_t i1 = rand() % parent_pool.size(); + new_population.push_back(*parent_pool[i1]); + new_population[new_population.size() - 1].Mutation(); + } + else + { + // кроссовер + size_t i1 = rand() % parent_pool.size(); + size_t i2 = rand() % parent_pool.size(); + new_population.push_back(*parent_pool[i1]); + new_population[new_population.size() - 1].Crossover(*parent_pool[i2]); + } + } + + (*population) = new_population; + + return changed; } diff --git a/src/ga/ga.h b/src/ga/ga.h index 59fbf8c..01259cf 100644 --- a/src/ga/ga.h +++ b/src/ga/ga.h @@ -3,7 +3,6 @@ #include #include "../db/db.h" -#include "individual.h" // Занятие struct Task @@ -19,10 +18,15 @@ struct Task } }; +class Individual; +class ADH; + class GA { + friend class Individual; + friend class ADH; public: - GA(DB::DataBase &db); + GA(DB::DataBase &db_); ~GA() { } @@ -31,13 +35,13 @@ class GA void Run(); bool Loop(std::vector *population); private: - std::vector less_aud; + DB::DataBase &db; + + std::vector less_aud; // адресация [l * A + a] std::vector tasks; std::vector::const_iterator> table_base; std::vector multi_aud; - size_t A; - size_t D; - size_t H; + static size_t A, D, H, G, T, L; std::vector ids_a, ids_d, ids_h, ids_g, ids_t, ids_l; }; diff --git a/src/ga/individual.cpp b/src/ga/individual.cpp index 056c743..d82aebe 100644 --- a/src/ga/individual.cpp +++ b/src/ga/individual.cpp @@ -1,8 +1,26 @@ #include "individual.h" -size_t ADH::A = 0; -size_t ADH::D = 0; -size_t ADH::H = 0; +GA* Individual::ga = 0; -std::vector Individual::multi_aud; +void Individual::Output(std::ostream &os) const +{ + for(size_t i = 0; i < table.size(); i ++) + { + const size_t g = ga->ids_g[ga->table_base[i]->g]; + const size_t t = ga->ids_t[ga->table_base[i]->t]; + const size_t l = ga->ids_l[ga->table_base[i]->l]; + + const size_t a = ga->ids_a[ADH(table[i]).a]; + const size_t d = ga->ids_d[ADH(table[i]).d]; + const size_t h = ga->ids_h[ADH(table[i]).h]; + + os << "(" << + ga->db.GetEntityName(DB::g_Groups, g) << "," << + ga->db.GetEntityName(DB::g_Teachers, t) << "," << + ga->db.GetEntityName(DB::g_Lessons, l) << ") -> (" << + ga->db.GetEntityName(DB::g_Auditoriums, a) << "," << + ga->db.GetEntityName(DB::g_Days, d) << "," << + ga->db.GetEntityName(DB::g_Hours, h) << ")" << std::endl; + } +} diff --git a/src/ga/individual.h b/src/ga/individual.h index 40661f3..0bbbcaa 100644 --- a/src/ga/individual.h +++ b/src/ga/individual.h @@ -2,20 +2,21 @@ #define _GA_INDIVIDUAL_H_ #include +#include "ga.h" struct ADH { public: ADH(long adh) { - a = adh % A; - adh /= A; - d = adh % D; - adh /= D; + a = adh % GA::A; + adh /= GA::A; + d = adh % GA::D; + adh /= GA::D; h = adh; } size_t a, d, h; - +/* static void SetSizes(size_t A_, size_t D_, size_t H_) { A = A_; @@ -23,7 +24,7 @@ struct ADH H = H_; } private: - static size_t A, D, H; + static size_t A, D, H;*/ }; // особь @@ -42,7 +43,7 @@ class Individual bool SetTable(size_t index_gtl, long adh_value) { //check - if((adh_value != -1) && (busy[adh_value] > 0) && (! multi_aud[ADH(adh_value).a])) + if((adh_value != -1) && (busy[adh_value] > 0) && (! ga->multi_aud[ADH(adh_value).a])) { return false; } @@ -59,14 +60,48 @@ class Individual return true; } - static void SetMultiAud(const std::vector& multi_aud_) + const std::vector& GetTable() const + { + return table; + } + + const std::vector& GetBusy() const + { + return busy; + } + + void Mutation() + { + size_t i1 = rand() % table.size(); + size_t i2 = rand() % table.size(); + signed long swap = table[i1]; + table[i1] = table[i2]; + table[i2] = swap; + } + + void Crossover(const Individual& other) + { + for(size_t i = 0; i < table.size() ; i ++) + { + if(rand() % 2) + { + SetTable(i, other.table[i]); + } + } + } + + static void SetGA(GA *ga_) { - multi_aud = multi_aud_; + ga = ga_; } + + void Output(std::ostream &os) const; private: std::vector table; // вектор соответствия занятий и времени с аудиторией. std::vector busy; // занятие соответствующих аудиторий и времени - static std::vector multi_aud; // многопоточные аудитории + //std::vector busy_gdh; // занятость групп + //std::vector busy_tdh; // занятость преподавателей + static GA *ga; }; diff --git a/src/logbuf.cpp b/src/logbuf.cpp index 0738bd4..2f4d7dd 100755 --- a/src/logbuf.cpp +++ b/src/logbuf.cpp @@ -24,9 +24,9 @@ int LogBuf::overflow(int c) { char ch = c; //std::cout << "Overflow "; - std::cout.write("\x1b[32m", 5); + /*std::cout.write("\x1b[32m", 5); std::cout.write(&ch, 1); - std::cout.write("\x1b[0m", 4); + std::cout.write("\x1b[0m", 4);*/ } return traits_type::not_eof(c); } @@ -34,16 +34,16 @@ int LogBuf::overflow(int c) int LogBuf::sync() { //std::cout << "Flush" << std::endl; - std::cout.flush(); + /*std::cout.flush();*/ return 0; } std::streamsize LogBuf::xsputn(const char *s, std::streamsize n) { //std::cout << "Out n=" << n << " s=\""; - std::cout.write("\x1b[32m", 5); + /*std::cout.write("\x1b[32m", 5); std::cout.write(s, n); - std::cout.write("\x1b[0m", 4); + std::cout.write("\x1b[0m", 4);*/ //std::cout << "\"" << std::endl; return n; } diff --git a/src/main.cpp b/src/main.cpp index 05bc193..5e7d319 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,22 +4,6 @@ #include "main_window.h" #include "shared.h" -// ToDo: -// редактирование условий -// * Связать сущности и модели -// * ScrolledWindow для OrderDialog -// * Запрет на отрицательные и нулевые индексы в зависимых полях -// * Объединение виджетов для отображения моделей в шаблонный класс -// решение -// * построение списков соответствия идентификаторов и индексов в математической модели -// * создание входных массивов данных -// * построение оптимизированной нейросети -// * алгоритм -// редактирование расписания -// * таблица хранения расписания -// * виджет ячейки с элементов расписания -// - int main(int argc, char **argv) { Gtk::Main prog(argc, argv); @@ -28,18 +12,40 @@ int main(int argc, char **argv) bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); Glib::thread_init(); + MainWindow *p_main_window = 0; try { - MainWindow main_window; - prog.run(main_window); + Glib::RefPtr refBuilder = Gtk::Builder::create(); + refBuilder->add_from_file(UIDIR "main_window.glade"); + + refBuilder->get_widget_derived("MainWindow", p_main_window); + if(p_main_window) + { + prog.run(*p_main_window); + } + } + catch(Gtk::BuilderError &err) + { + std::cerr << "Gtk::BuilderError: " << err.what() << std::endl; + Gtk::MessageDialog dialog(err.what(), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dialog.run(); } catch(Glib::Error &err) { - Gtk::MessageDialog(err.what(), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + std::cerr << "Glib::Error: " << err.what() << std::endl; + Gtk::MessageDialog dialog(err.what(), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dialog.run(); } catch(std::exception &err) { - Gtk::MessageDialog(err.what(), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + std::cerr << "std::exception: " << err.what() << std::endl; + Gtk::MessageDialog dialog(err.what(), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dialog.run(); + } + + if(p_main_window) + { + delete p_main_window; } return 0; diff --git a/src/main_window.cpp b/src/main_window.cpp index fa4f820..911d1cf 100755 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -12,12 +12,39 @@ #include "table_frame.h" #include "ga/ga.h" -MainWindow::MainWindow() - :m_DB(0) +MainWindow::MainWindow(GtkWindow *cobject, const Glib::RefPtr& builder) + :Gtk::Window(cobject), + m_refBuilder(builder), + m_DB(0) { - set_title(_("Table")); +#if 0 + try + { + m_refBuilder = Gtk::Builder::create_from_file(UIDIR "main_window.glade"); + } + catch(const Glib::Error &e) + { + std::cerr << e.what() << std::endl; + } +#endif - m_refActionGroup = Gtk::ActionGroup::create(); + + //set_title(_("Table")); + + m_refActionGroup = Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("ActionGroup")); + + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("FileNew")),sigc::mem_fun(*this, &MainWindow::OnNew)); + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("FileOpen")),sigc::mem_fun(*this, &MainWindow::OnOpen)); + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("FileQuit")),sigc::mem_fun(*this, &MainWindow::OnQuit)); + + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("RunSolve")),sigc::mem_fun(*this, &MainWindow::OnRun)); + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("RunEdit")),sigc::mem_fun(*this, &MainWindow::OnEdit)); + + m_refActionGroup->add(Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("HelpAbout")),sigc::mem_fun(*this, &MainWindow::OnQuit)); + + //m_refNotebook = Glib::RefPtr::cast_dynamic(m_refBuilder->get_object("Notebook")); + +#if 0 m_refActionGroup->add(Gtk::Action::create("MenuFile", _("File"))); m_refActionGroup->add(Gtk::Action::create("FileNew", Gtk::Stock::NEW), sigc::mem_fun(*this, &MainWindow::OnNew)); @@ -34,7 +61,6 @@ MainWindow::MainWindow() m_refActionGroup->add(Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT), sigc::mem_fun(*this, &MainWindow::OnAbout)); - m_refUIManager = Gtk::UIManager::create(); m_refUIManager->insert_action_group(m_refActionGroup); add_accel_group(m_refUIManager->get_accel_group()); @@ -98,6 +124,7 @@ MainWindow::MainWindow() m_Box.pack_start(m_Statusbar, Gtk::PACK_SHRINK); add(m_Box); +#endif show_all_children(); } @@ -166,17 +193,19 @@ void MainWindow::OnRun() void MainWindow::OnEdit() { - m_Notebook.append_page(*Gtk::manage(new TableFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Table")))); +// m_refNotebook->append_page(*Gtk::manage(new TableFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Table")))); show_all_children(); } void MainWindow::ShowAllEntities() { - m_Notebook.append_page(*Gtk::manage(new TimeFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Time")))); - m_Notebook.append_page(*Gtk::manage(new AuditoriumFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Auditoruiums")))); - m_Notebook.append_page(*Gtk::manage(new TeachersFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Teachers")))); - m_Notebook.append_page(*Gtk::manage(new LessonsFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Lessons")))); - m_Notebook.append_page(*Gtk::manage(new GroupsFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Groups")))); +#if 0 + m_refNotebook->append_page(*Gtk::manage(new TimeFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Time")))); + m_refNotebook->append_page(*Gtk::manage(new AuditoriumFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Auditoruiums")))); + m_refNotebook->append_page(*Gtk::manage(new TeachersFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Teachers")))); + m_refNotebook->append_page(*Gtk::manage(new LessonsFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Lessons")))); + m_refNotebook->append_page(*Gtk::manage(new GroupsFrame(*m_DB)), *Gtk::manage(new NotebookLabelWidget(_("Groups")))); +#endif show_all_children(); } diff --git a/src/main_window.h b/src/main_window.h index 704dcdc..2e94feb 100755 --- a/src/main_window.h +++ b/src/main_window.h @@ -6,14 +6,15 @@ #include #include #include -#include +//#include +#include #include "db/db.h" class MainWindow : public Gtk::Window { public: - MainWindow(); - ~MainWindow(); + MainWindow(GtkWindow *cobject, const Glib::RefPtr& builder); + virtual ~MainWindow(); private: void OnNew(); void OnOpen(); @@ -25,11 +26,13 @@ class MainWindow : public Gtk::Window void ShowAllEntities(); - Gtk::VBox m_Box; - Gtk::Statusbar m_Statusbar; - Gtk::Notebook m_Notebook; + //Gtk::VBox m_Box; + //Gtk::Statusbar m_Statusbar; + //Glib::RefPtr m_refNotebook; Glib::RefPtr m_refActionGroup; - Glib::RefPtr m_refUIManager; + //Glib::RefPtr m_refUIManager; + + const Glib::RefPtr& m_refBuilder; DB::DataBase *m_DB; }; diff --git a/ui/Makefile.am b/ui/Makefile.am new file mode 100644 index 0000000..a76f99f --- /dev/null +++ b/ui/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = main_window.glade +dist_DATA = $(EXTRA_DIST) +distdir = $(pkgdatadir)/ui diff --git a/ui/main_window.glade b/ui/main_window.glade new file mode 100644 index 0000000..8f1946b --- /dev/null +++ b/ui/main_window.glade @@ -0,0 +1,253 @@ + + + + + + Table + + + True + vertical + + + True + + + True + _File + True + + + True + + + True + FileNew + True + True + + + + + True + FileOpen + True + True + + + + + True + + + + + True + FileQuit + True + True + True + + + + + + + + + True + _Schedule + True + + + + + True + _Help + True + + + True + + + True + HelpAbout + True + True + + + + + + + + + False + 0 + + + + + True + + + True + FileNew + True + toolbutton1 + True + + + False + True + + + + + True + FileOpen + True + toolbutton2 + True + + + False + True + + + + + True + FileQuit + True + toolbutton3 + True + + + False + True + + + + + True + + + False + True + + + + + False + 1 + + + + + True + True + + + True + True + + + True + True + False + both + True + + + + + True + Hours + + + False + + + + + + + True + Lists + True + + + False + + + + + + + + True + Loading + + + 1 + False + + + + + + + + True + Schedule + + + 2 + False + + + + + 2 + + + + + True + 2 + + + False + 3 + + + + + + + gtk-quit + True + + + + gtk-open + True + + + gtk-new + True + + + gtk-media-play + True + + + gtk-edit + True + + + gtk-about + True + +