Mercurial > hg > syntilista
changeset 80:c8fd927cd2c4
Restructure the project by placing source code, images into appropriate
subdirectories.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 24 Apr 2017 12:12:39 +0300 |
parents | f48b8fc1de64 |
children | 810ca71af506 |
files | Makefile.gen editperson.ui icon-16.png icon-32.png icon-48.png icon-64.png img/icon-16.png img/icon-32.png img/icon-48.png img/icon-64.png img/kampuscafe1.svg img/kampuscafe2.svg img/kampuscafe3.svg img/kampuscafe4.svg img/logo.png kampuscafe1.svg kampuscafe2.svg kampuscafe3.svg kampuscafe4.svg logo.png main.cpp main.h mainwindow.ui resources.qrc src/editperson.ui src/main.cpp src/main.h src/mainwindow.ui src/resources.qrc src/winres.rc.in winres.rc.in |
diffstat | 31 files changed, 2429 insertions(+), 2427 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.gen Wed Apr 12 12:16:00 2017 +0300 +++ b/Makefile.gen Mon Apr 24 12:12:39 2017 +0300 @@ -17,6 +17,8 @@ DEFINES += -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_SQL_LIB -DQT_CORE_LIB # Application stuff +APP_SRC=src/ +APP_IMG=img/ APP_BIN=$(BINPATH)Syntilista$(EXEEXT) APP_OBJS=main.o resources.o moc_main.o APP_VERSION := $(shell cat VERSION) @@ -27,14 +29,14 @@ LOGO_SVG ?= kampuscafe4.svg ICON_PNGS = icon-64.png icon-48.png icon-32.png icon-16.png -APP_RESOURCES += logo.png $(ICON_PNGS) +APP_RESOURCES += $(addprefix $(APP_IMG),logo.png $(ICON_PNGS)) # And target lists TARGETS = $(APP_BIN) NOBUILD_TARGETS += $(OBJPATH) $(BINPATH) NOINST_TARGETS += -DISTCLEAN_TARGETS += icon.ico moc_*.cpp ui_*.h +DISTCLEAN_TARGETS += icon.ico $(APP_SRC)moc_*.cpp $(APP_SRC)ui_*.h ### @@ -60,11 +62,11 @@ @echo " MKDIR $@" @$(MKDIR_P) $@ -$(OBJPATH)%.o: %.cpp %.h +$(OBJPATH)%.o: $(APP_SRC)%.cpp $(APP_SRC)%.h @echo " CXX $@" @$(CXX) $(CXXFLAGS) $(DEFINES) $(INCPATH) -c -o $@ $< -$(OBJPATH)%.o: %.cpp +$(OBJPATH)%.o: $(APP_SRC)%.cpp @echo " CXX $@" @$(CXX) $(CXXFLAGS) $(DEFINES) $(INCPATH) -c -o $@ $< @@ -76,7 +78,7 @@ %.rc: %.rc.in icon.ico VERSION @sed -e "s/@APP_VERSION@/$(APP_VERSION)/g;s/@APP_VERSION_COM@/$(APP_VERSION_COM)/g;s#@APP_EXE@#$(notdir $(APP_BIN))#g" < $< > $@ -$(OBJPATH)%.o: %.rc +$(OBJPATH)%.o: $(APP_SRC)%.rc @echo " WINDRES $<" @$(WINDRES) $< -O coff -o $@ @@ -84,21 +86,21 @@ ### ### Application rules ### -icon-%.png: $(LOGO_SVG) +$(APP_IMG)icon-%.png: $(addprefix $(APP_IMG),$(LOGO_SVG)) inkscape --export-area-page -w $(patsubst icon-%.png,%,$@) -h $(patsubst icon-%.png,%,$@) -e "$@" "$<" -logo.png: $(LOGO_SVG) +$(APP_IMG)logo.png: $(addprefix $(APP_IMG),$(LOGO_SVG)) inkscape --export-area-page -w 320 -h 280 -e "$@" "$<" -icon.ico: $(ICON_PNGS) +icon.ico: $(addprefix $(APP_IMG),$(ICON_PNGS)) @echo " CONVERT $+ -> $@" @convert $+ $@ -%.cpp: %.qrc $(APP_RESOURCES) +$(APP_SRC)%.cpp: $(APP_SRC)%.qrc $(APP_RESOURCES) @echo " Qt:RCC $@ $<" @$(QT_RCC) -name "Syntilista" $< -o $@ -$(OBJPATH)main.o: main.cpp main.h ui_mainwindow.h ui_editperson.h VERSION +$(OBJPATH)main.o: $(addprefix $(APP_SRC),main.cpp main.h ui_mainwindow.h ui_editperson.h) VERSION @echo " CXX $@" @$(CXX) $(CXXFLAGS) $(DEFINES) $(INCPATH) -c -o $@ $<
--- a/editperson.ui Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>EditPerson</class> - <widget class="QDialog" name="EditPerson"> - <property name="windowModality"> - <enum>Qt::NonModal</enum> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>564</width> - <height>500</height> - </rect> - </property> - <property name="windowTitle"> - <string>Muokkaa henkilöä</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Henkilön perustiedot</string> - </property> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_FirstName"> - <property name="text"> - <string>Etunimi</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="label_LastName"> - <property name="text"> - <string>Sukunimi</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="edit_LastName"/> - </item> - <item row="1" column="0"> - <widget class="QLineEdit" name="edit_FirstName"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_ExtraInfo"> - <property name="text"> - <string>Lisätietoja:</string> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2"> - <widget class="QPlainTextEdit" name="textedit_ExtraInfo"/> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Tapahtumat:</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QTableView" name="tableview_Transactions"> - <property name="contextMenuPolicy"> - <enum>Qt::DefaultContextMenu</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="button_Cancel"> - <property name="text"> - <string>Peruuta</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_OK"> - <property name="text"> - <string>Talleta / OK</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <tabstops> - <tabstop>edit_FirstName</tabstop> - <tabstop>edit_LastName</tabstop> - <tabstop>textedit_ExtraInfo</tabstop> - <tabstop>button_OK</tabstop> - <tabstop>button_Cancel</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/kampuscafe1.svg Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="129.27827mm" + height="100.09245mm" + viewBox="0 0 129.27827 100.09245" + version="1.1" + id="svg8" + inkscape:version="0.92.1 r15371" + sodipodi:docname="kampuscafe.svg" + inkscape:export-filename="/home/ccr/syntilista/logo.png" + inkscape:export-xdpi="58.939999" + inkscape:export-ydpi="58.939999"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4142136" + inkscape:cx="367.702" + inkscape:cy="192.39597" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:snap-grids="true" + inkscape:snap-to-guides="false" + inkscape:snap-others="true" + inkscape:window-width="2558" + inkscape:window-height="1402" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:object-nodes="false" + inkscape:snap-global="false" + inkscape:snap-page="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-33.675957,-79.041702)"> + <rect + style="opacity:1;fill:#fcfcfc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + id="rect4489" + width="129.27827" + height="100.09245" + x="33.675957" + y="79.041702" + rx="1.4271281" + ry="1.4271282" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 61.847708,113.50711 c -2.514304,4.28362 -1.074055,1.48352 -0.02466,6.03801 11.281973,17.3705 14.842373,47.33917 20.488129,50.62371 10.742374,2.02599 18.417143,-0.41726 29.278183,-0.034 7.36024,-0.56797 9.7848,-5.04174 11.16765,-14.72544 3.83655,-3.17889 5.69394,-1.87444 9.54739,-4.55175 4.59353,-5.56191 6.48809,-9.87079 11.20272,-15.70691 3.69312,-4.88682 6.85525,-13.78534 0.45512,-15.84033 -5.95141,-2.01246 -6.60877,-3.71891 -11.2574,-0.76452 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -27.170753,1.91033 -34.139695,4.68073 z m 61.530802,-0.57086 c 1.30371,0.0876 8.26515,1.57927 3.58221,1.67173 -11.02663,1.67858 -41.8771,4.87511 -61.538187,0.36526 12.90601,-5.85387 48.952857,-4.39622 57.955977,-2.03699 z m -59.185014,4.23437 c 14.143363,10.25342 51.567824,1.63929 64.775664,0.63503 -11.91685,14.59736 -6.08219,45.66306 -15.15371,48.84621 -11.85472,-0.1447 -23.059354,1.86016 -29.777977,-0.035 -3.043523,-0.91095 -9.295304,-33.44794 -19.843972,-49.44627 z m 77.559514,12.20958 c -8.7291,14.02432 -8.79009,20.63449 -17.72206,19.98842 0.96521,-8.38622 3.73261,-19.14833 6.3172,-24.32052 0.89269,-1.78641 3.89953,-3.93174 6.91219,-1.94539 1.78418,1.17636 7.73946,1.06115 4.49267,6.27749 z" + id="path4491" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccczcccccczcccczscsss" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 86.980649,113.17149 c 8.624681,1.22211 10.190907,0.34302 15.768381,-0.6914 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -1.588008,0.55933 -9.701094,0.30125 -11.394543,-1.04845 z" + id="path4517" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -5.640588,-0.36212 -5.731606,-1.05049 4.14736,-0.985 8.914937,-0.40633 9.264379,1.32623 1.791737,2.50119 12.424036,-1.23998 11.845163,1.76915 z" + id="path4521" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 98.240442,85.527697 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.916682,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" + id="path4544" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61458302px;line-height:6.61458302px;font-family:'Conduit 2 BRK';-inkscape-font-specification:'Conduit 2 BRK';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="text4558" + x="-3.3675961" + y="-68.848633" + transform="matrix(2.0583104,0.04404385,-0.04404385,2.0583104,-69.441849,-187.70019)"><textPath + xlink:href="#path4572" + id="textPath4574">Kampus Cafe</textPath></text> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" + id="path4572" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/kampuscafe2.svg Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="129.27827mm" + height="100.09245mm" + viewBox="0 0 129.27827 100.09245" + version="1.1" + id="svg8" + inkscape:version="0.92.1 r15371" + sodipodi:docname="kampuscafe2.svg" + inkscape:export-filename="/home/ccr/syntilista/logo.png" + inkscape:export-xdpi="58.939999" + inkscape:export-ydpi="58.939999"> + <defs + id="defs2"> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" + id="path4572-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4142136" + inkscape:cx="-3.7309669" + inkscape:cy="174.37429" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:snap-grids="true" + inkscape:snap-to-guides="false" + inkscape:snap-others="true" + inkscape:window-width="2558" + inkscape:window-height="1402" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:object-nodes="false" + inkscape:snap-global="false" + inkscape:snap-page="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-33.675957,-79.041702)"> + <rect + style="opacity:1;fill:#fcfcfc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + id="rect4489" + width="129.27827" + height="100.09245" + x="33.675957" + y="79.041702" + rx="5.263587" + ry="5.263587" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m -63.682934,4.23437 c 6.050393,6.17716 22.651863,6.7611 37.741354,5.96705 -7.865682,17.72781 -6.030294,43.44196 -8.986434,44.69622 -2.244313,1.20734 -9.817979,0.33752 -11.823307,-0.78335 -2.944203,-3.12668 -5.890911,-32.32961 -16.931608,-49.87995 0,0 -6.050398,-6.17713 -5e-6,3e-5 z m 74.384514,12.47416 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" + id="path4491" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccczccccczcccczcccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" + id="path4517" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" + id="path4521" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 96.556644,83.750355 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.91668,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" + id="path4544" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61455727px;line-height:6.61458302px;font-family:'URW Gothic L';-inkscape-font-specification:'URW Gothic L, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.26471969;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="text4558" + x="46.374069" + y="-181.29654" + transform="matrix(2.3147054,0,0,2.3057299,-1.4448132,-388.12719)"><textPath + xlink:href="#path4572" + id="textPath4574"> Kampus Cafe</textPath></text> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" + id="path4572" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54500002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 132.84703,114.66028 c -5.06553,-2.70415 -23.78713,-4.06917 -30.98141,-2.78419 11.26023,0.50906 29.96108,1.98648 30.08841,4.73637 0.76361,0.0994 0.60544,-1.40801 0.893,-1.95218 z" + id="path4583" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/kampuscafe3.svg Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="129.27827mm" + height="100.09245mm" + viewBox="0 0 129.27827 100.09245" + version="1.1" + id="svg8" + inkscape:version="0.92.1 r15371" + sodipodi:docname="kampuscafe3.svg" + inkscape:export-filename="/home/ccr/syntilista/logo.png" + inkscape:export-xdpi="58.939999" + inkscape:export-ydpi="58.939999"> + <defs + id="defs2"> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" + id="path4572-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" + id="path4572-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" + id="path4572-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.0000001" + inkscape:cx="299.69183" + inkscape:cy="153.45574" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:snap-grids="true" + inkscape:snap-to-guides="false" + inkscape:snap-others="true" + inkscape:window-width="2558" + inkscape:window-height="1402" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:object-nodes="false" + inkscape:snap-global="false" + inkscape:snap-page="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-33.675957,-79.041702)"> + <rect + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + id="rect4489" + width="129.27827" + height="100.09245" + x="33.675957" + y="79.041702" + rx="5.263587" + ry="5.263587" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m 10.70158,16.70853 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" + id="path4491" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccczccccccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" + id="path4517" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" + id="path4521" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 96.556644,83.750355 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.91668,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" + id="path4544" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61455727px;line-height:6.61458302px;font-family:'Xipital BRK';-inkscape-font-specification:'Xipital BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26471969;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="text4558" + x="46.374069" + y="-181.29654" + transform="matrix(2.1253758,0,0,2.4298663,3.0532112,-416.20974)"><textPath + xlink:href="#path4572" + id="textPath4574"> Kampus Cafe</textPath></text> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.94839,220.93915 c 12.131327,-8.19749 34.047138,-8.55371 46.32601,-1.00446" + id="path4572" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54777914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 131.53794,114.78751 c -4.95174,-2.69755 -22.98806,-3.6054 -29.86349,-2.054 10.8385,0.21846 28.85832,1.24493 29.06505,4.12916 0.73701,0.0829 0.53874,-1.49563 0.79844,-2.07516 z" + id="path4583" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.30457115px;line-height:11.30461502px;font-family:'Xerox Malfunction BRK';-inkscape-font-specification:'Xerox Malfunction BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.4524177;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="text4558-7" + x="-39.710236" + y="194.22658" + transform="scale(1.0019445,0.99805928)"> Kampus Cafe</text> + </g> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/img/kampuscafe4.svg Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="129.27827mm" + height="100.09245mm" + viewBox="0 0 129.27827 100.09245" + version="1.1" + id="svg8" + inkscape:version="0.92.1 r15371" + sodipodi:docname="kampuscafe4.svg" + inkscape:export-filename="/home/ccr/Syntilista/icon-64.png" + inkscape:export-xdpi="12.57" + inkscape:export-ydpi="12.57"> + <defs + id="defs2"> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" + id="path4572-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" + id="path4572-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" + id="path4572-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.0000002" + inkscape:cx="163.73568" + inkscape:cy="202.04481" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:snap-grids="true" + inkscape:snap-to-guides="false" + inkscape:snap-others="true" + inkscape:window-width="1278" + inkscape:window-height="992" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:object-nodes="false" + inkscape:snap-global="false" + inkscape:snap-page="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-33.675957,-79.041702)"> + <rect + style="opacity:1;fill:#d86836;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + id="rect4489" + width="129.27827" + height="100.09245" + x="33.675957" + y="79.041702" + rx="5.263587" + ry="5.263587" + inkscape:export-xdpi="12.57" + inkscape:export-ydpi="12.57" /> + <path + style="opacity:1;fill:#974d00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59584385;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + id="path4511" + sodipodi:type="arc" + sodipodi:cx="93.987808" + sodipodi:cy="118.35854" + sodipodi:rx="33.208237" + sodipodi:ry="6.5481029" + sodipodi:start="5.4977871" + sodipodi:end="5.4924115" + sodipodi:open="true" + d="m 117.46958,113.72834 a 33.208237,6.5481029 0 0 1 0.0315,9.25418 33.208237,6.5481029 0 0 1 -46.931871,0.0187 33.208237,6.5481029 0 0 1 -0.157682,-9.25414 33.208237,6.5481029 0 0 1 46.931453,-0.0435" + transform="rotate(-1.4760674)" /> + <g + id="g4516" + style="fill:#c76906;fill-opacity:1"> + <path + sodipodi:nodetypes="ccccc" + inkscape:connector-curvature="0" + id="path4517" + d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" + style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cccccc" + inkscape:connector-curvature="0" + id="path4521" + d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" + style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cccc" + inkscape:connector-curvature="0" + id="path4583" + d="m 131.53794,114.78751 c -4.95174,-2.69755 -22.98806,-3.6054 -29.86349,-2.054 10.8385,0.21846 28.85832,1.24493 29.06505,4.12916 0.73701,0.0829 0.53874,-1.49563 0.79844,-2.07516 z" + style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54777914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> + </g> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m 10.70158,16.70853 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" + id="path4491" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccczccccccccc" /> + <path + style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" + d="m 100.92211,83.750355 c 0.69488,2.429065 -0.17139,2.268105 -1.254897,3.453205 -2.216664,0.90466 -1.275839,2.68681 0.655367,3.07444 6.91668,7.3086 -8.50572,5.95412 -2.152497,2.98704 1.44177,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395356,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" + id="path4544" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.03176022px;line-height:15.03181839px;font-family:'Xipital BRK';-inkscape-font-specification:'Xipital BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.60158265;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="text4558" + inkscape:transform-center-x="1.6681159" + inkscape:transform-center-y="2.9122167"><textPath + xlink:href="#path4497" + id="textPath4499">Cafe Kampus</textPath></text> + <path + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none" + id="path4497" + sodipodi:type="arc" + sodipodi:cx="-98.053421" + sodipodi:cy="-134.99261" + sodipodi:rx="64.022369" + sodipodi:ry="28.862976" + sodipodi:start="0.71258024" + sodipodi:end="2.6663229" + d="m -49.609137,-116.12234 a 64.022369,28.862976 0 0 1 -56.023063,9.78976 64.022369,28.862976 0 0 1 -49.34795,-15.45296" + transform="scale(-1)" + sodipodi:open="true" /> + <path + style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14791916" + d="m 79.25037,98.520978 c -0.137248,-0.261792 -0.245338,-0.535534 -0.366883,-0.803253 -0.06638,-0.143254 -0.175431,-0.695861 -0.312471,-0.320844 -0.48232,0.837206 -0.955319,1.679254 -1.43402,2.518338 0.122262,0.343501 0.294066,0.669201 0.412933,1.012831 0.06332,0.15443 0.207886,0.39317 0.27848,0.10735 0.478881,-0.83596 0.946657,-1.676882 1.421968,-2.514429 z" + id="path4501" + inkscape:connector-curvature="0" /> + </g> +</svg>
--- a/kampuscafe1.svg Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="129.27827mm" - height="100.09245mm" - viewBox="0 0 129.27827 100.09245" - version="1.1" - id="svg8" - inkscape:version="0.92.1 r15371" - sodipodi:docname="kampuscafe.svg" - inkscape:export-filename="/home/ccr/syntilista/logo.png" - inkscape:export-xdpi="58.939999" - inkscape:export-ydpi="58.939999"> - <defs - id="defs2" /> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="1.4142136" - inkscape:cx="367.702" - inkscape:cy="192.39597" - inkscape:document-units="mm" - inkscape:current-layer="layer1" - showgrid="false" - inkscape:snap-grids="true" - inkscape:snap-to-guides="false" - inkscape:snap-others="true" - inkscape:window-width="2558" - inkscape:window-height="1402" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:object-nodes="false" - inkscape:snap-global="false" - inkscape:snap-page="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata5"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-33.675957,-79.041702)"> - <rect - style="opacity:1;fill:#fcfcfc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - id="rect4489" - width="129.27827" - height="100.09245" - x="33.675957" - y="79.041702" - rx="1.4271281" - ry="1.4271282" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 61.847708,113.50711 c -2.514304,4.28362 -1.074055,1.48352 -0.02466,6.03801 11.281973,17.3705 14.842373,47.33917 20.488129,50.62371 10.742374,2.02599 18.417143,-0.41726 29.278183,-0.034 7.36024,-0.56797 9.7848,-5.04174 11.16765,-14.72544 3.83655,-3.17889 5.69394,-1.87444 9.54739,-4.55175 4.59353,-5.56191 6.48809,-9.87079 11.20272,-15.70691 3.69312,-4.88682 6.85525,-13.78534 0.45512,-15.84033 -5.95141,-2.01246 -6.60877,-3.71891 -11.2574,-0.76452 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -27.170753,1.91033 -34.139695,4.68073 z m 61.530802,-0.57086 c 1.30371,0.0876 8.26515,1.57927 3.58221,1.67173 -11.02663,1.67858 -41.8771,4.87511 -61.538187,0.36526 12.90601,-5.85387 48.952857,-4.39622 57.955977,-2.03699 z m -59.185014,4.23437 c 14.143363,10.25342 51.567824,1.63929 64.775664,0.63503 -11.91685,14.59736 -6.08219,45.66306 -15.15371,48.84621 -11.85472,-0.1447 -23.059354,1.86016 -29.777977,-0.035 -3.043523,-0.91095 -9.295304,-33.44794 -19.843972,-49.44627 z m 77.559514,12.20958 c -8.7291,14.02432 -8.79009,20.63449 -17.72206,19.98842 0.96521,-8.38622 3.73261,-19.14833 6.3172,-24.32052 0.89269,-1.78641 3.89953,-3.93174 6.91219,-1.94539 1.78418,1.17636 7.73946,1.06115 4.49267,6.27749 z" - id="path4491" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccccczcccccczcccczscsss" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 86.980649,113.17149 c 8.624681,1.22211 10.190907,0.34302 15.768381,-0.6914 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -1.588008,0.55933 -9.701094,0.30125 -11.394543,-1.04845 z" - id="path4517" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -5.640588,-0.36212 -5.731606,-1.05049 4.14736,-0.985 8.914937,-0.40633 9.264379,1.32623 1.791737,2.50119 12.424036,-1.23998 11.845163,1.76915 z" - id="path4521" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 98.240442,85.527697 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.916682,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" - id="path4544" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccc" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61458302px;line-height:6.61458302px;font-family:'Conduit 2 BRK';-inkscape-font-specification:'Conduit 2 BRK';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - id="text4558" - x="-3.3675961" - y="-68.848633" - transform="matrix(2.0583104,0.04404385,-0.04404385,2.0583104,-69.441849,-187.70019)"><textPath - xlink:href="#path4572" - id="textPath4574">Kampus Cafe</textPath></text> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" - id="path4572" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - </g> -</svg>
--- a/kampuscafe2.svg Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="129.27827mm" - height="100.09245mm" - viewBox="0 0 129.27827 100.09245" - version="1.1" - id="svg8" - inkscape:version="0.92.1 r15371" - sodipodi:docname="kampuscafe2.svg" - inkscape:export-filename="/home/ccr/syntilista/logo.png" - inkscape:export-xdpi="58.939999" - inkscape:export-ydpi="58.939999"> - <defs - id="defs2"> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" - id="path4572-0" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="1.4142136" - inkscape:cx="-3.7309669" - inkscape:cy="174.37429" - inkscape:document-units="mm" - inkscape:current-layer="layer1" - showgrid="false" - inkscape:snap-grids="true" - inkscape:snap-to-guides="false" - inkscape:snap-others="true" - inkscape:window-width="2558" - inkscape:window-height="1402" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:object-nodes="false" - inkscape:snap-global="false" - inkscape:snap-page="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata5"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-33.675957,-79.041702)"> - <rect - style="opacity:1;fill:#fcfcfc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - id="rect4489" - width="129.27827" - height="100.09245" - x="33.675957" - y="79.041702" - rx="5.263587" - ry="5.263587" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m -63.682934,4.23437 c 6.050393,6.17716 22.651863,6.7611 37.741354,5.96705 -7.865682,17.72781 -6.030294,43.44196 -8.986434,44.69622 -2.244313,1.20734 -9.817979,0.33752 -11.823307,-0.78335 -2.944203,-3.12668 -5.890911,-32.32961 -16.931608,-49.87995 0,0 -6.050398,-6.17713 -5e-6,3e-5 z m 74.384514,12.47416 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" - id="path4491" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccczccccczcccczcccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" - id="path4517" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" - id="path4521" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 96.556644,83.750355 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.91668,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" - id="path4544" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccc" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61455727px;line-height:6.61458302px;font-family:'URW Gothic L';-inkscape-font-specification:'URW Gothic L, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.26471969;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="text4558" - x="46.374069" - y="-181.29654" - transform="matrix(2.3147054,0,0,2.3057299,-1.4448132,-388.12719)"><textPath - xlink:href="#path4572" - id="textPath4574"> Kampus Cafe</textPath></text> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" - id="path4572" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54500002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 132.84703,114.66028 c -5.06553,-2.70415 -23.78713,-4.06917 -30.98141,-2.78419 11.26023,0.50906 29.96108,1.98648 30.08841,4.73637 0.76361,0.0994 0.60544,-1.40801 0.893,-1.95218 z" - id="path4583" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" /> - </g> -</svg>
--- a/kampuscafe3.svg Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="129.27827mm" - height="100.09245mm" - viewBox="0 0 129.27827 100.09245" - version="1.1" - id="svg8" - inkscape:version="0.92.1 r15371" - sodipodi:docname="kampuscafe3.svg" - inkscape:export-filename="/home/ccr/syntilista/logo.png" - inkscape:export-xdpi="58.939999" - inkscape:export-ydpi="58.939999"> - <defs - id="defs2"> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" - id="path4572-0" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" - id="path4572-6" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" - id="path4572-3" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="2.0000001" - inkscape:cx="299.69183" - inkscape:cy="153.45574" - inkscape:document-units="mm" - inkscape:current-layer="layer1" - showgrid="false" - inkscape:snap-grids="true" - inkscape:snap-to-guides="false" - inkscape:snap-others="true" - inkscape:window-width="2558" - inkscape:window-height="1402" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:object-nodes="false" - inkscape:snap-global="false" - inkscape:snap-page="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata5"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-33.675957,-79.041702)"> - <rect - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - id="rect4489" - width="129.27827" - height="100.09245" - x="33.675957" - y="79.041702" - rx="5.263587" - ry="5.263587" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m 10.70158,16.70853 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" - id="path4491" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccczccccccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" - id="path4517" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" - id="path4521" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 96.556644,83.750355 c 0.694879,2.429065 -0.171389,2.268105 -1.254906,3.453205 -2.21666,0.90466 -1.275835,2.68681 0.655372,3.07444 6.91668,7.3086 -8.505721,5.95412 -2.152498,2.98704 1.441767,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395359,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" - id="path4544" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccc" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.61455727px;line-height:6.61458302px;font-family:'Xipital BRK';-inkscape-font-specification:'Xipital BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26471969;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="text4558" - x="46.374069" - y="-181.29654" - transform="matrix(2.1253758,0,0,2.4298663,3.0532112,-416.20974)"><textPath - xlink:href="#path4572" - id="textPath4574"> Kampus Cafe</textPath></text> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.94839,220.93915 c 12.131327,-8.19749 34.047138,-8.55371 46.32601,-1.00446" - id="path4572" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54777914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 131.53794,114.78751 c -4.95174,-2.69755 -22.98806,-3.6054 -29.86349,-2.054 10.8385,0.21846 28.85832,1.24493 29.06505,4.12916 0.73701,0.0829 0.53874,-1.49563 0.79844,-2.07516 z" - id="path4583" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.30457115px;line-height:11.30461502px;font-family:'Xerox Malfunction BRK';-inkscape-font-specification:'Xerox Malfunction BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.4524177;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="text4558-7" - x="-39.710236" - y="194.22658" - transform="scale(1.0019445,0.99805928)"> Kampus Cafe</text> - </g> -</svg>
--- a/kampuscafe4.svg Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="129.27827mm" - height="100.09245mm" - viewBox="0 0 129.27827 100.09245" - version="1.1" - id="svg8" - inkscape:version="0.92.1 r15371" - sodipodi:docname="kampuscafe4.svg" - inkscape:export-filename="/home/ccr/Syntilista/icon-64.png" - inkscape:export-xdpi="12.57" - inkscape:export-ydpi="12.57"> - <defs - id="defs2"> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 60.429639,145.66518 c 15.437034,-6.02558 31.837023,-7.1078 49.765591,-0.34301" - id="path4572-0" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" - id="path4572-6" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.75544739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 19.683807,220.93915 c 11.60216,-8.95683 35.634638,-8.22269 46.458301,-0.87217" - id="path4572-3" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cc" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="2.0000002" - inkscape:cx="163.73568" - inkscape:cy="202.04481" - inkscape:document-units="mm" - inkscape:current-layer="layer1" - showgrid="false" - inkscape:snap-grids="true" - inkscape:snap-to-guides="false" - inkscape:snap-others="true" - inkscape:window-width="1278" - inkscape:window-height="992" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:object-nodes="false" - inkscape:snap-global="false" - inkscape:snap-page="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" /> - <metadata - id="metadata5"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-33.675957,-79.041702)"> - <rect - style="opacity:1;fill:#d86836;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17169559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - id="rect4489" - width="129.27827" - height="100.09245" - x="33.675957" - y="79.041702" - rx="5.263587" - ry="5.263587" - inkscape:export-xdpi="12.57" - inkscape:export-ydpi="12.57" /> - <path - style="opacity:1;fill:#974d00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.59584385;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - id="path4511" - sodipodi:type="arc" - sodipodi:cx="93.987808" - sodipodi:cy="118.35854" - sodipodi:rx="33.208237" - sodipodi:ry="6.5481029" - sodipodi:start="5.4977871" - sodipodi:end="5.4924115" - sodipodi:open="true" - d="m 117.46958,113.72834 a 33.208237,6.5481029 0 0 1 0.0315,9.25418 33.208237,6.5481029 0 0 1 -46.931871,0.0187 33.208237,6.5481029 0 0 1 -0.157682,-9.25414 33.208237,6.5481029 0 0 1 46.931453,-0.0435" - transform="rotate(-1.4760674)" /> - <g - id="g4516" - style="fill:#c76906;fill-opacity:1"> - <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="path4517" - d="m 91.377233,111.86187 c -2.088357,2.91364 5.794323,1.65264 11.371797,0.61822 1.54259,-0.85542 10.03239,0.31297 6.58213,1.58142 -5.08258,0.53408 -3.45152,-1.2253 -10.955968,0.15843 -5.750872,0.76747 -11.064699,-0.72036 -6.997959,-2.35807 z" - style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75557709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="path4521" - d="m 98.432708,116.25617 c -3.64243,1.12556 -15.515477,0.71497 -15.377931,-2.04493 0.228137,-1.42355 -4.798689,0.85396 -4.889707,0.16559 4.14736,-0.985 7.04405,-1.52887 7.393492,0.20369 1.791737,2.50119 13.453024,-1.33352 12.874151,1.67561 z" - style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.02475154;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccc" - inkscape:connector-curvature="0" - id="path4583" - d="m 131.53794,114.78751 c -4.95174,-2.69755 -22.98806,-3.6054 -29.86349,-2.054 10.8385,0.21846 28.85832,1.24493 29.06505,4.12916 0.73701,0.0829 0.53874,-1.49563 0.79844,-2.07516 z" - style="opacity:1;fill:#c76906;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.54777914;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" /> - </g> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 62.21151,118.69956 c 4.409165,4.34969 9.030096,25.27938 16.3955,51.46927 5.367766,4.2244 29.39154,4.59103 39.13391,-0.034 1.1932,-9.60266 1.68587,-11.18223 2.56869,-13.86554 3.83655,-3.17889 6.83172,-1.42472 10.68517,-4.10203 4.59353,-5.56191 4.89784,-12.30294 12.51234,-17.01653 11.42957,-10.40202 -0.92193,-19.15854 -10.80228,-16.60485 -0.91307,-3.14931 2.43292,-5.33053 -1.97617,-6.79193 -3.71085,-1.9731 -16.87131,-3.27169 -34.741268,-2.92759 -17.86995,0.34409 -26.211638,1.64575 -33.18058,4.41615 -0.891262,1.4726 -1.771128,2.95091 -0.595312,5.45705 z m 65.66492,-5.76331 c 3.19542,5.1354 -50.771937,6.89562 -62.453897,2.03699 12.90601,-5.85387 53.450777,-4.39622 62.453897,-2.03699 z m 10.70158,16.70853 c -11.93575,12.24285 -9.20443,21.9716 -17.0974,21.90275 0.78925,-7.12082 6.78423,-27.12614 9.61589,-29.30576 6.54001,-0.98632 9.35816,4.16767 7.48151,7.40301 z" - id="path4491" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccczccccccccc" /> - <path - style="opacity:1;fill:#800000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29645836;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:20;stroke-opacity:1" - d="m 100.92211,83.750355 c 0.69488,2.429065 -0.17139,2.268105 -1.254897,3.453205 -2.216664,0.90466 -1.275839,2.68681 0.655367,3.07444 6.91668,7.3086 -8.50572,5.95412 -2.152497,2.98704 1.44177,-1.2706 -2.297888,-1.02629 -1.227899,-5.92248 6.395356,-0.73633 1.652463,-5.650141 2.059483,-5.038528 z" - id="path4544" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccccc" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.03176022px;line-height:15.03181839px;font-family:'Xipital BRK';-inkscape-font-specification:'Xipital BRK';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.60158265;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="text4558" - inkscape:transform-center-x="1.6681159" - inkscape:transform-center-y="2.9122167"><textPath - xlink:href="#path4497" - id="textPath4499">Cafe Kampus</textPath></text> - <path - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none" - id="path4497" - sodipodi:type="arc" - sodipodi:cx="-98.053421" - sodipodi:cy="-134.99261" - sodipodi:rx="64.022369" - sodipodi:ry="28.862976" - sodipodi:start="0.71258024" - sodipodi:end="2.6663229" - d="m -49.609137,-116.12234 a 64.022369,28.862976 0 0 1 -56.023063,9.78976 64.022369,28.862976 0 0 1 -49.34795,-15.45296" - transform="scale(-1)" - sodipodi:open="true" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14791916" - d="m 79.25037,98.520978 c -0.137248,-0.261792 -0.245338,-0.535534 -0.366883,-0.803253 -0.06638,-0.143254 -0.175431,-0.695861 -0.312471,-0.320844 -0.48232,0.837206 -0.955319,1.679254 -1.43402,2.518338 0.122262,0.343501 0.294066,0.669201 0.412933,1.012831 0.06332,0.15443 0.207886,0.39317 0.27848,0.10735 0.478881,-0.83596 0.946657,-1.676882 1.421968,-2.514429 z" - id="path4501" - inkscape:connector-curvature="0" /> - </g> -</svg>
--- a/main.cpp Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1189 +0,0 @@ -// -// Syntilista - velkalistasovellus Kampus-kahvilaan -// Programmed and designed by Matti Hämäläinen <ccr@tnsp.org> -// (C) Copyright 2017 Tecnic Software productions (TNSP) -// -// Distributed under 3-clause BSD style license, refer to -// included file "COPYING" for exact terms. -// -#include <QApplication> -#include <QMessageBox> -#include <QSettings> -#include "main.h" -#include "ui_mainwindow.h" -#include "ui_editperson.h" - -double setScale; - - -int errorMsg(QString title, QString msg) -{ - QMessageBox dlg; - - dlg.setText(title); - dlg.setInformativeText(msg); - dlg.setTextFormat(Qt::RichText); - dlg.setIcon(QMessageBox::Critical); - dlg.setStandardButtons(QMessageBox::Ok); - dlg.setDefaultButton(QMessageBox::Ok); - - return dlg.exec(); -} - - -double moneyStrToValue(const QString &str) -{ - QString str2 = str; - return str2.replace(",", ".").toDouble(); -} - - -QString moneyValueToStr(double val) -{ - return QStringLiteral("%1").arg(val, 1, 'f', 2); -} - - -QString cleanupStr(const QString &str) -{ - return str.simplified().trimmed(); -} - - -const QString dateTimeToStr(const QDateTime &val) -{ - QDateTime tmp = val; - tmp.setOffsetFromUtc(0); - return tmp.toLocalTime().toString(QStringLiteral("yyyy-MM-dd hh:mm")); -} - - -bool checkAndReportSQLError(const QString where, const QSqlError &err) -{ - if (err.isValid()) - { - printf("SQL Error in %s: %s\n", - where.toUtf8().constData(), - err.text().toUtf8().constData()); - return false; - } - else - return true; -} - - -void PersonInfo::dump() -{ - printf("PersonInfo() #%lld '%s %s' (added=%s, updated=%s, balance %1.2f)\n#%s#\n", - id, - firstName.toUtf8().constData(), - lastName.toUtf8().constData(), - dateTimeToStr(added).toUtf8().constData(), - dateTimeToStr(updated).toUtf8().constData(), - balance, - extraInfo.toUtf8().constData()); -} - - -// -// Get PersonInfo record from SQL database for specified persn ID # -// -bool getPersonInfo(qint64 id, PersonInfo &info) -{ - QSqlQuery person; - person.prepare( - "SELECT id,first_name,last_name,extra_info,added,updated, " - "(SELECT SUM(value) FROM transactions WHERE transactions.person=people.id) AS balance " - "FROM people WHERE id=?"); - - person.addBindValue(id); - person.exec(); - if (!person.next()) - return false; - - info.id = person.value(0).toInt(); - info.firstName = person.value(1).toString(); - info.lastName = person.value(2).toString(); - info.extraInfo = person.value(3).toString(); - info.added = person.value(4).toDateTime(); - info.updated = person.value(5).toDateTime(); - info.balance = person.value(6).toDouble(); - - person.finish(); - - return true; -} - - -void setCommonStyleSheet(QWidget *widget) -{ - // Clamp scale value - if (setScale < 0.5f) - setScale = 0.5f; - if (setScale > 3.0f) - setScale = 3.0f; - - // Set the stylesheet - widget->setStyleSheet( - QStringLiteral( - "* { font-size: %1pt; }" - "QPushButton { font-size: %2pt; padding: 0.25em; }" - "#button_AddDebt[enabled='true'] { font-size: %3pt; background-color: #900; color: white; }" - "#button_PayDebt[enabled='true'] { font-size: %3pt; background-color: #090; color: white; }" - "#button_PayFullDebt[enabled='true'] { background-color: #060; color: white; }" - - "#button_AddDebt[enabled='false'] { font-size: %3pt; background-color: #622; color: black; }" - "#button_PayDebt[enabled='false'] { font-size: %3pt; background-color: #262; color: black; }" - "#button_PayFullDebt[enabled='false'] { background-color: #131; color: black; }" - - "#label_PersonName { font-size: %5pt; font-weight: bold; }" - "#label_BalanceValue { font-size: %4pt; font-weight: bold; }" - "#label_EUR { font-size: %4pt; font-weight: bold; }" - "#edit_Amount { font-size: %4pt; margin: 0.5em; padding: 0.5em; }" - ). - arg(12 * setScale). - arg(14 * setScale). - arg(16 * setScale). - arg(18 * setScale). - arg(20 * setScale) - ); -} - - -int main(int argc, char *argv[]) -{ - QApplication sapp(argc, argv); - - // - // Initialize / open SQL database connection - // - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); - db.setDatabaseName(qApp->applicationDirPath() + - QDir::separator() + APP_SQLITE_FILE); - - if (!db.open()) - { - errorMsg( - QObject::tr("Tietokantaa ei voitu avata"), - QObject::tr("Yhteyttä SQL-tietokantaan ei saatu.<br><br>Virhe: %1<br><br>"). - arg(db.lastError().text()) - ); - return 1; - } - - QSqlQuery query; - if (!db.tables().contains("people")) - { - query.exec(QStringLiteral( - "CREATE TABLE people (id INTEGER PRIMARY KEY, " - "first_name VARCHAR(128) NOT NULL, " - "last_name VARCHAR(128) NOT NULL, " - "extra_info VARCHAR(2048), " - "added DATETIME NOT NULL, " - "updated DATETIME NOT NULL)")); - - checkAndReportSQLError("CREATE TABLE people", query.lastError()); - } - - if (!db.tables().contains("transactions")) - { - query.exec(QStringLiteral( - "CREATE TABLE transactions (" - "id INTEGER PRIMARY KEY, " - "person INT NOT NULL, " - "value REAL, " - "added DATETIME NOT NULL)")); - - checkAndReportSQLError("CREATE TABLE transactions", query.lastError()); - } - - SyntilistaMainWindow swin; - swin.show(); - return sapp.exec(); -} - - -// -// Main application window code -// -SyntilistaMainWindow::SyntilistaMainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::SyntilistaMainWindow) -{ - // Setup UI - ui->setupUi(this); - - // Read config - readSettings(); - - // Setup other UI things - setWindowIcon(QIcon(QPixmap(":/img/icon-64.png"))); - setWindowTitle(tr("%1 versio %3"). - arg(tr(APP_NAME)). - arg(tr(APP_VERSION))); - - QPixmap logoImage(":/img/logo.png"); - ui->button_LogoImage->setPixmap(logoImage); - ui->button_LogoImage->setAlignment(Qt::AlignCenter); - - setCommonStyleSheet(this); - - // Validator for amount input - //ui->edit_Amount->setValidator(new QDoubleValidator(0, 1000, 2, this)); - QRegExp vregex("\\d{0,4}[,.]\\d{0,2}|\\d{0,4}"); - ui->edit_Amount->setValidator(new QRegExpValidator(vregex, this)); - - // Setup person list filtering and sorting - peopleSortIndex = 1; - peopleSortOrder = Qt::AscendingOrder; - peopleFilter = ""; - - model_People = new PersonSQLModel(); - updatePersonList(); - - ui->tableview_People->setModel(model_People); - ui->tableview_People->setColumnHidden(0, true); - ui->tableview_People->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_People)); - ui->tableview_People->verticalHeader()->setVisible(false); - ui->tableview_People->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ui->tableview_People->setSortingEnabled(true); - ui->tableview_People->sortByColumn(peopleSortIndex, peopleSortOrder); - - connect( - ui->tableview_People->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), - this, - SLOT(selectedPersonChanged(const QModelIndex &, const QModelIndex &))); - - connect( - ui->tableview_People->horizontalHeader(), - SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), - this, - SLOT(updateSortOrder(int, Qt::SortOrder))); - - ui->tableview_People->horizontalHeader()->setSortIndicator(1, Qt::AscendingOrder); - - model_Latest = new TransactionSQLModel(); - ui->tableview_Latest->setModel(model_Latest); - ui->tableview_Latest->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Latest)); - ui->tableview_Latest->verticalHeader()->setVisible(false); - ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - setActivePerson(-1); - - // Keyboard shortcuts - ui->button_Quit->setShortcut(QKeySequence(Qt::Key_F10)); - new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(on_button_Quit_clicked())); - - ui->button_AddPerson->setShortcut(QKeySequence(Qt::Key_F5)); - ui->button_DeletePerson->setShortcut(QKeySequence(Qt::Key_F8)); - ui->button_EditPerson->setShortcut(QKeySequence(Qt::Key_F6)); - ui->button_ClearFilter->setShortcut(QKeySequence(Qt::Key_Escape)); - ui->button_Help->setShortcut(QKeySequence(Qt::Key_F1)); - ui->button_About->setShortcut(QKeySequence(Qt::Key_F2)); - - new QShortcut(QKeySequence(QKeySequence::ZoomIn), this, SLOT(changeUIZoomIn())); - new QShortcut(QKeySequence(QKeySequence::ZoomOut), this, SLOT(changeUIZoomOut())); - new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_Plus), this, SLOT(changeUIZoomIn())); - new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_Minus), this, SLOT(changeUIZoomOut())); - new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_0), this, SLOT(changeUIZoomReset())); - new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_0), this, SLOT(changeUIZoomReset())); - - new QShortcut(QKeySequence(Qt::Key_PageUp), this, SLOT(selectRowPrev())); - new QShortcut(QKeySequence(Qt::Key_PageDown), this, SLOT(selectRowNext())); - - new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(focusDebtEdit())); -} - - -SyntilistaMainWindow::~SyntilistaMainWindow() -{ - saveSettings(); - - delete ui; - delete model_People; - delete model_Latest; -} - - -void SyntilistaMainWindow::statusMsg(const QString &msg) -{ - ui->statusbar->showMessage(msg); -} - - -void SyntilistaMainWindow::readSettings() -{ - QSettings settings(APP_VENDOR, APP_ID); - move(settings.value("pos", QPoint(100, 100)).toPoint()); - resize(settings.value("size", QSize(1000, 600)).toSize()); - setScale = settings.value("scale", 1.0f).toDouble(); -} - - -void SyntilistaMainWindow::saveSettings() -{ - QSettings settings(APP_VENDOR, APP_ID); - settings.setValue("pos", pos()); - settings.setValue("size", size()); - settings.setValue("scale", setScale); -} - - -void SyntilistaMainWindow::changeUIZoomIn() -{ - setScale += 0.1f; - setCommonStyleSheet(this); -} - - -void SyntilistaMainWindow::changeUIZoomOut() -{ - setScale -= 0.1f; - setCommonStyleSheet(this); -} - - -void SyntilistaMainWindow::changeUIZoomReset() -{ - setScale = 1.0f; - setCommonStyleSheet(this); -} - - -void SyntilistaMainWindow::selectedPersonChanged(const QModelIndex &curr, const QModelIndex &prev) -{ - (void) prev; - int row = curr.row(); - if (row >= 0) - { - const QAbstractItemModel *model = curr.model(); - setActivePerson(model->data(model->index(row, 0)).toInt()); - } - else - setActivePerson(-1); -} - - -void SyntilistaMainWindow::updateSortOrder(int index, Qt::SortOrder order) -{ - peopleSortIndex = index; - peopleSortOrder = order; - updatePersonList(); -} - - -void SyntilistaMainWindow::setActivePerson(qint64 id) -{ - currPerson.id = id; - - ui->button_EditPerson->setEnabled(id >= 0); - - if (id >= 0) - { - if (!getPersonInfo(id, currPerson)) - { - statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(id)); - } - else - { - ui->personGB->setEnabled(true); - ui->label_PersonName->setText(currPerson.lastName +", "+ currPerson.firstName); - - ui->label_BalanceValue->setText(moneyValueToStr(currPerson.balance)); - ui->label_BalanceValue->setStyleSheet(currPerson.balance < 0 ? "color: red;" : "color: green;"); - ui->button_PayFullDebt->setEnabled(currPerson.balance < 0); - - QSqlQuery query; - query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC LIMIT 5"); - query.addBindValue(id); - query.exec(); - checkAndReportSQLError("SELECT transactions for tableview_Latest", query.lastError()); - - model_Latest->setQuery(query); - - model_Latest->setHeaderData(0, Qt::Horizontal, tr("ID")); - model_Latest->setHeaderData(1, Qt::Horizontal, tr("Summa")); - model_Latest->setHeaderData(2, Qt::Horizontal, tr("Aika")); - - ui->tableview_Latest->setModel(model_Latest); - ui->tableview_Latest->setColumnHidden(0, true); - ui->tableview_Latest->verticalHeader()->setVisible(false); - ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - setCommonStyleSheet(this); - return; // Ugly - } - } - - // In case of id < 0 or errors .. - ui->personGB->setEnabled(false); - ui->edit_Amount->clear(); - ui->label_BalanceValue->setText("--"); - ui->label_BalanceValue->setStyleSheet(NULL); - ui->label_PersonName->setText("???"); - ui->tableview_Latest->setModel(NULL); - setCommonStyleSheet(this); -} - - -// -// Widget slot handlers -// -void SyntilistaMainWindow::on_button_Quit_clicked() -{ - close(); -} - - -void SyntilistaMainWindow::on_button_About_clicked() -{ - QMessageBox dlg; - - setCommonStyleSheet(&dlg); - dlg.setWindowTitle(tr("Tietoja ohjelmasta")); - dlg.setTextFormat(Qt::RichText); - dlg.setIconPixmap(QPixmap(":/img/icon-64.png")); - dlg.setStandardButtons(QMessageBox::Ok); - dlg.setDefaultButton(QMessageBox::Ok); - - //dlg.setInformativeText(tr( - dlg.setText(tr( - "<h1>%1 v%2</h1>" - "<p>" - "<b>Ohjelmoinut ja kehittänyt Matti Hämäläinen <ccr@tnsp.org><br>" - "(C) Copyright 2017 Tecnic Software productions (TNSP)</b><br>" - "<br>" - "Kehitetty Raahen kaupungin Hanketoiminta ja Kehittäminen -yksikön " - "alaisuudessa Café Kampuksen käyttöön.<br>" - "</p>" - "<p>" - "Ohjelma ja sen lähdekoodi ovat uudemman BSD-tyylisen lisenssin alaisia. " - "Lue ohjelman mukana tullut tiedosto \"COPYING\" (tai \"COPYING.txt\") " - "nähdäksesi täydelliset lisenssiehdot." - "</p>" - ). - arg(tr(APP_NAME)). - arg(tr(APP_VERSION)) - ); - - dlg.exec(); -} - - -void SyntilistaMainWindow::on_button_Help_clicked() -{ - QMessageBox dlg; - - setCommonStyleSheet(&dlg); - dlg.setWindowTitle(tr("Tietoja ohjelmasta")); - dlg.setTextFormat(Qt::RichText); - dlg.setIconPixmap(QPixmap(":/img/icon-64.png")); - dlg.setStandardButtons(QMessageBox::Ok); - dlg.setDefaultButton(QMessageBox::Ok); - - dlg.setText(tr( - "<h1>Pikanäppäimet</h1>" - "<table>" - "<tr><td><b>F1</b></td><td>Tämä tietoikkuna</td></tr>" - "<tr><td><b>F2</b></td><td>Tietoja ohjelmasta</td></tr>" - "<tr><td><b>CTRL + Q</b></td><td>Ohjelman lopetus</td></tr>" - "<tr><td><b>CTRL + Page Up</b></td><td>Suurenna ohjelman tekstejä/käyttöliittymää</td></tr>" - "<tr><td><b>CTRL + Page Down</b></td><td>Pienennä ohjelman tekstejä/käyttöliittymää</td></tr>" - "<tr></tr>" - "<tr><td><b>Esc</b></td><td>Tyhjennä 'Etsi / suodata' kenttä ja siirry siihen</td></tr>" - "<tr><td><b>CTRL + Enter</b></td><td>Siirry summan syöttökenttään</td></tr>" - "<tr><td><b>Page Up</b></td><td>Siirry ylös henkilölistassa</td></tr>" - "<tr><td><b>Page Down</b></td><td>Siirry alas henkilölistassa</td></tr>" - "<tr></tr>" - "<tr><td><b>F5</b></td><td>Lisää uusi henkilö</td></tr>" - "<tr><td><b>F6</b></td><td>Muokkaa henkilöä</td></tr>" - "<tr><td><b>F8</b></td><td>Poista henkilö</td></tr>" - "</table>" - )); - - dlg.exec(); -} - - -void SyntilistaMainWindow::on_button_DeletePerson_clicked() -{ - if (currPerson.id <= 0) - { - statusMsg(tr("Ei valittua henkilöä!")); - return; - } - - PersonInfo info; - if (!getPersonInfo(currPerson.id, info)) - { - statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(currPerson.id)); - return; - } - - QMessageBox dlg; - setCommonStyleSheet(&dlg); - dlg.setText(tr("Varmistus")); - dlg.setInformativeText( - tr("<br>Haluatko varmasti poistaa henkilön:<br>" - "<br>" - "<b>'%1, %2'</b> <i>(ID #%3)</i>?<br>" - "<br>" - "Tämä poistaa sekä henkilön ja hänen koko tapahtumahistoriansa PYSYVÄSTI!<br>"). - arg(info.lastName).arg(info.firstName).arg(info.id)); - - dlg.setTextFormat(Qt::RichText); - dlg.setIcon(QMessageBox::Question); - dlg.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - dlg.setButtonText(QMessageBox::Yes, tr("Kyllä")); - dlg.setButtonText(QMessageBox::No, tr("Ei / peruuta")); - dlg.setDefaultButton(QMessageBox::No); - - if (dlg.exec() == QMessageBox::Yes) - { - int rv = model_People->deletePerson(info.id); - updatePersonList(); - setActivePerson(-1); - if (rv != 0) - { - errorMsg(tr("SQL-tietokantavirhe"), - tr("Henkilön tietoja poistettaessa tapahtui virhe #%1."). - arg(rv)); - } - else - { - statusMsg(tr("Henkilö '%1 %2' (ID #%3) poistettu."). - arg(info.firstName).arg(info.lastName). - arg(info.id)); - } - } -} - - -void SyntilistaMainWindow::on_button_AddPerson_clicked() -{ - EditPerson *person = new EditPerson(this); - person->setPerson(-1); -} - - -void SyntilistaMainWindow::on_button_EditPerson_clicked() -{ - if (currPerson.id >= 0) - { - EditPerson *person = new EditPerson(this); - person->setPerson(currPerson.id); - } -} - - -void SyntilistaMainWindow::on_tableview_People_doubleClicked(const QModelIndex &curr) -{ - int row = curr.row(); - if (row >= 0) - { - const QAbstractItemModel *model = curr.model(); - setActivePerson(model->data(model->index(row, 0)).toInt()); - - EditPerson *person = new EditPerson(this); - person->setPerson(currPerson.id); - } - else - setActivePerson(-1); -} - - -void SyntilistaMainWindow::on_button_ClearFilter_clicked() -{ - ui->edit_PersonFilter->clear(); - ui->edit_PersonFilter->setFocus(Qt::ShortcutFocusReason); -} - - -void SyntilistaMainWindow::focusDebtEdit() -{ - if (currPerson.id >= 0) - ui->edit_Amount->setFocus(Qt::ShortcutFocusReason); -} - - -void SyntilistaMainWindow::selectRowPrev() -{ - QItemSelectionModel *sel = ui->tableview_People->selectionModel(); - int row = sel->currentIndex().row() - 1; - if (row < 0) - row = 0; - - sel->setCurrentIndex(model_People->index(row, 0), - QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows); -} - - -void SyntilistaMainWindow::selectRowNext() -{ - QItemSelectionModel *sel = ui->tableview_People->selectionModel(); - int row = sel->currentIndex().row() + 1; - if (row >= model_People->rowCount()) - row = model_People->rowCount() - 1; - - sel->setCurrentIndex(model_People->index(row, 0), - QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows); -} - - -// -// Update visible person list/query based on the current -// filtering and sorting settings. -// -void SyntilistaMainWindow::updatePersonList() -{ - static QString queryBase = - "SELECT id,last_name,first_name," - "(SELECT SUM(value) FROM transactions WHERE transactions.person=people.id) AS balance," - "updated FROM people"; - - QSqlQuery query; - QString queryOrderDir, queryOrderBy; - - // Sort order - if (peopleSortOrder == Qt::AscendingOrder) - queryOrderDir = QStringLiteral("ASC"); - else - queryOrderDir = QStringLiteral("DESC"); - - // Sort by which column - switch (peopleSortIndex) - { - case 1: - case 2: - queryOrderBy = QStringLiteral(" ORDER BY last_name ") + queryOrderDir + QStringLiteral(",first_name ") + queryOrderDir; - break; - - case 3: - queryOrderBy = QStringLiteral(" ORDER BY balance ") + queryOrderDir; - break; - - case 4: - queryOrderBy = QStringLiteral(" ORDER BY updated ") + queryOrderDir; - break; - - default: - queryOrderBy = ""; - } - - // Are we filtering or not? - if (peopleFilter != "") - { - // Filter by name(s) - QString tmp = "%"+ peopleFilter +"%"; - query.prepare(queryBase +" WHERE first_name LIKE ? OR last_name LIKE ?" + queryOrderBy); - - query.addBindValue(tmp); - query.addBindValue(tmp); - } - else - { - // No filter - query.prepare(queryBase + queryOrderBy); - } - - // Execute the query and update model - checkAndReportSQLError("updatePersonList() before exec", query.lastError()); - query.exec(); - checkAndReportSQLError("updatePersonList() after exec", query.lastError()); - - model_People->setQuery(query); - - model_People->setHeaderData(0, Qt::Horizontal, tr("ID")); - model_People->setHeaderData(1, Qt::Horizontal, tr("Sukunimi")); - model_People->setHeaderData(2, Qt::Horizontal, tr("Etunimi")); - model_People->setHeaderData(3, Qt::Horizontal, tr("Tase")); - model_People->setHeaderData(4, Qt::Horizontal, tr("Muutettu")); -} - - -// -// Update the list of people when filter parameter changes -// -void SyntilistaMainWindow::on_edit_PersonFilter_textChanged(const QString &str) -{ - peopleFilter = cleanupStr(str); - updatePersonList(); -} - - -// -// Add one transaction to given person id -// -int SyntilistaMainWindow::addTransaction(qint64 id, double value, PersonInfo &info) -{ - if (!getPersonInfo(id, info)) - return -1; - - QSqlDatabase::database().transaction(); - - QSqlQuery query; - query.prepare("INSERT INTO transactions (person,value,added) VALUES (?,?,?)"); - query.addBindValue(id); - query.addBindValue(value); - query.addBindValue(QDateTime::currentDateTimeUtc()); - query.exec(); - if (!checkAndReportSQLError("addTransaction()", query.lastError())) - { - QSqlDatabase::database().rollback(); - return -2; - } - - query.prepare("UPDATE people SET updated=? WHERE id=?"); - query.addBindValue(QDateTime::currentDateTimeUtc()); - query.addBindValue(id); - query.exec(); - if (!checkAndReportSQLError("addTransaction update timestamp", query.lastError())) - { - QSqlDatabase::database().rollback(); - return -3; - } - - QSqlDatabase::database().commit(); - - return 0; -} - - -int SyntilistaMainWindow::addTransactionGUI(qint64 id, bool debt, double value) -{ - PersonInfo info; - - // Check if person is selected - if (id <= 0) - return -1; - - // Check value - if (value == 0) - { - QString tmp = (debt ? "lisätty" : "vähennetty"); - statusMsg("Velkaa ei "+ tmp +" koska summaa ei määritetty."); - return 1; - } - - // Perform transaction insert - int ret = addTransaction(id, debt ? -value : value, info); - if (ret == 0) - { - // All ok, clear amount entry and update person data - ui->edit_Amount->clear(); - if (info.id == currPerson.id) - setActivePerson(info.id); - - model_People->updateModel(); - - QString str; - if (debt) - { - str = tr("Lisättiin velkaa %1 EUR henkilölle '%2 %3' (#%4)."). - arg(moneyValueToStr(value)). - arg(info.firstName). - arg(info.lastName). - arg(info.id); - } - else - { - str = tr("Vähennettiin velkaa %1 EUR henkilöltä '%2 %3' (#%4)."). - arg(moneyValueToStr(value)). - arg(info.firstName). - arg(info.lastName). - arg(info.id); - } - statusMsg(str); - } - else - { - errorMsg( - tr("SQL-tietokantavirhe"), - tr("Tietokantaan tapahtumaa lisättäessa tapahtui virhe #%1."). - arg(ret)); - } - - return ret; -} - - -void SyntilistaMainWindow::on_button_AddDebt_clicked() -{ - addTransactionGUI(currPerson.id, true, moneyStrToValue(ui->edit_Amount->text())); -} - - -void SyntilistaMainWindow::on_button_PayDebt_clicked() -{ - addTransactionGUI(currPerson.id, false, moneyStrToValue(ui->edit_Amount->text())); -} - - -void SyntilistaMainWindow::on_button_PayFullDebt_clicked() -{ - if (currPerson.balance < 0) - addTransactionGUI(currPerson.id, false, -currPerson.balance); - else - { - statusMsg( - tr("Valitulla henkilöllä '%1, %2' ei ole velkaa."). - arg(currPerson.lastName). - arg(currPerson.firstName)); - } -} - - -// -// Edit person dialog -// -EditPerson::EditPerson(QWidget *parent) : - QDialog(parent), - ui(new Ui::EditPerson) -{ - ui->setupUi(this); - - setCommonStyleSheet(this); - - setModal(true); - setAttribute(Qt::WA_DeleteOnClose); - show(); - activateWindow(); - raise(); - setFocus(); - - model_Transactions = new TransactionSQLModel(); - ui->tableview_Transactions->setModel(model_Transactions); - ui->tableview_Transactions->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Transactions)); - ui->tableview_Transactions->verticalHeader()->setVisible(false); - ui->tableview_Transactions->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - - validateForm(); -} - - -EditPerson::~EditPerson() -{ - delete ui; - delete model_Transactions; -} - - -void EditPerson::statusMsg(const QString &msg) -{ - dynamic_cast<SyntilistaMainWindow *>(parent())->statusMsg(msg); -} - - -bool EditPerson::validateForm() -{ - selPerson.firstName = cleanupStr(ui->edit_FirstName->text()); - selPerson.lastName = cleanupStr(ui->edit_LastName->text()); - selPerson.extraInfo = ui->textedit_ExtraInfo->document()->toPlainText(); - - ui->edit_FirstName->setStyleSheet(selPerson.firstName == "" ? "background-color: red;" : NULL); - ui->edit_LastName->setStyleSheet(selPerson.lastName == "" ? "background-color: red;" : NULL); - - return selPerson.firstName != "" && selPerson.lastName != ""; -} - - -void EditPerson::on_button_Cancel_clicked() -{ - close(); -} - - -void EditPerson::on_button_OK_clicked() -{ - if (!validateForm()) - { - errorMsg( - tr("Virhe!"), - tr("Vaaditut kentät (etunimi, sukunimi) eivät ole täytetty.")); - - return; - } - - if (selPerson.id >= 0) - { - QSqlQuery person; - person.prepare("SELECT * FROM people WHERE id <> ? AND first_name=? AND last_name=?"); - person.addBindValue(selPerson.id); - person.addBindValue(selPerson.firstName); - person.addBindValue(selPerson.lastName); - person.exec(); - - checkAndReportSQLError("SELECT check for existing person by same name (UPDATE)", person.lastError()); - - if (person.next()) - { - errorMsg( - tr("Virhe!"), - tr("Ei pysty! Samalla nimellä '%1 %2' on olemassa jo henkilö!"). - arg(selPerson.firstName).arg(selPerson.lastName)); - return; - } - - dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->updatePerson(selPerson); - dynamic_cast<SyntilistaMainWindow *>(parent())->setActivePerson(selPerson.id); - - statusMsg(tr("Päivitettiin henkilö '%1 %2' (#%3)."). - arg(selPerson.firstName).arg(selPerson.lastName).arg(selPerson.id)); - } - else - { - QSqlQuery person; - person.prepare("SELECT * FROM people WHERE first_name=? AND last_name=?"); - person.addBindValue(selPerson.firstName); - person.addBindValue(selPerson.lastName); - person.exec(); - - checkAndReportSQLError("SELECT check for existing person by same name (ADD)", person.lastError()); - - if (person.next()) - { - errorMsg( - tr("Virhe!"), - tr("Ei pysty! Samalla nimellä '%1 %2' on olemassa jo henkilö!"). - arg(selPerson.firstName).arg(selPerson.lastName)); - - return; - } - - dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->addPerson(selPerson); - dynamic_cast<SyntilistaMainWindow *>(parent())->updatePersonList(); - - statusMsg(tr("Lisättiin uusi henkilö '%1 %2'."). - arg(selPerson.firstName).arg(selPerson.lastName)); - } - - close(); -} - - -void EditPerson::on_edit_FirstName_textChanged(const QString &arg1) -{ - (void) arg1; - validateForm(); -} - - -void EditPerson::on_edit_LastName_textChanged(const QString &arg1) -{ - (void) arg1; - validateForm(); -} - - -void EditPerson::clearForm() -{ - ui->edit_FirstName->clear(); - ui->edit_LastName->clear(); - ui->textedit_ExtraInfo->document()->clear(); - ui->edit_FirstName->setFocus(); -} - - -void EditPerson::setPerson(qint64 id) -{ - selPerson.id = id; - - if (id >= 0) - { - PersonInfo pinfo; - if (!getPersonInfo(id, pinfo)) - { - statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(id)); - } - else - { - ui->edit_FirstName->setText(pinfo.firstName); - ui->edit_LastName->setText(pinfo.lastName); - ui->textedit_ExtraInfo->document()->setPlainText(pinfo.extraInfo); - - QSqlQuery query; - query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC"); - query.addBindValue(pinfo.id); - query.exec(); - checkAndReportSQLError("SELECT transactions for tableview_Transactions", query.lastError()); - - model_Transactions->setQuery(query); - - model_Transactions->setHeaderData(0, Qt::Horizontal, tr("ID")); - model_Transactions->setHeaderData(1, Qt::Horizontal, tr("Summa")); - model_Transactions->setHeaderData(2, Qt::Horizontal, tr("Aika")); - - ui->tableview_Transactions->setModel(model_Transactions); - ui->tableview_Transactions->setColumnHidden(0, true); - - return; // Ugly - } - } - - // In case of id < 0 or errors .. - clearForm(); - ui->tableview_Transactions->setModel(NULL); -} - - -// -// Custom SQL models -// -PersonSQLModel::PersonSQLModel(QObject *parent) : QSqlQueryModel(parent) -{ -} - - -QVariant PersonSQLModel::data(const QModelIndex &index, int role) const -{ - QVariant value = QSqlQueryModel::data(index, role); - - if (value.isValid() && role == Qt::DisplayRole) - { - switch (index.column()) - { - case 3: - return moneyValueToStr(value.toDouble()); - - case 4: - return dateTimeToStr(value.toDateTime()); - } - } - - if (index.column() == 3 && role == Qt::ForegroundRole) - { - double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); - if (val < 0) - return QVariant::fromValue(QColor(Qt::red)); - else - return QVariant::fromValue(QColor(Qt::green)); - } - - return value; -} - - -int PersonSQLModel::updatePerson(const PersonInfo &info) -{ - QSqlQuery np; - - np.prepare("UPDATE people SET first_name=?,last_name=?,extra_info=?,updated=? WHERE id=?"); - np.addBindValue(info.firstName); - np.addBindValue(info.lastName); - np.addBindValue(info.extraInfo); - np.addBindValue(QDateTime::currentDateTimeUtc()); - np.addBindValue(info.id); - np.exec(); - - if (!checkAndReportSQLError("PersonSQLModel::updatePerson()", np.lastError())) - return -1; - - QSqlDatabase::database().commit(); - - updateModel(); - return 0; -} - - -int PersonSQLModel::addPerson(const PersonInfo &info) -{ -// beginInsertRows(QModelIndex(), rowCount(), rowCount()); - - QSqlQuery np; - np.prepare("INSERT INTO people (first_name,last_name,extra_info,added,updated) VALUES (?,?,?,?,?)"); - np.addBindValue(info.firstName); - np.addBindValue(info.lastName); - np.addBindValue(info.extraInfo); - np.addBindValue(QDateTime::currentDateTimeUtc()); - np.addBindValue(QDateTime::currentDateTimeUtc()); - np.exec(); - - if (!checkAndReportSQLError("PersonSQLModel::addPerson()", np.lastError())) - return -1; - - QSqlDatabase::database().commit(); - -// endInsertRows(); - updateModel(); - return 0; -} - - -int PersonSQLModel::deletePerson(qint64 id) -{ - QSqlDatabase::database().transaction(); - QSqlQuery del; - - del.prepare("DELETE FROM people WHERE id=?"); - del.addBindValue(id); - del.exec(); - - if (!checkAndReportSQLError("delete user", del.lastError())) - { - QSqlDatabase::database().rollback(); - return -1; - } - - del.prepare("DELETE FROM transactions WHERE person=?"); - del.addBindValue(id); - del.exec(); - - if (!checkAndReportSQLError("delete user transactions", del.lastError())) - { - QSqlDatabase::database().rollback(); - return -2; - } - - QSqlDatabase::database().commit(); - updateModel(); - return 0; -} - - -void PersonSQLModel::updateModel() -{ - query().exec(); - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} - - -TransactionSQLModel::TransactionSQLModel(QObject *parent) : QSqlQueryModel(parent) -{ -} - - -QVariant TransactionSQLModel::data(const QModelIndex &index, int role) const -{ - QVariant value = QSqlQueryModel::data(index, role); - - if (value.isValid() && role == Qt::DisplayRole) - { - switch (index.column()) - { - case 1: - return moneyValueToStr(value.toDouble()); - - case 2: - return dateTimeToStr(value.toDateTime()); - } - } - - if (index.column() == 1 && role == Qt::ForegroundRole) - { - double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); - if (val < 0) - return QVariant::fromValue(QColor(Qt::red)); - else - return QVariant::fromValue(QColor(Qt::green)); - } - - return value; -} - - -void TransactionSQLModel::updateModel() -{ - query().exec(); - emit dataChanged(QModelIndex(), QModelIndex()); -}
--- a/main.h Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -// -// Syntilista - velkalistasovellus Kampus-kahvilaan -// Programmed and designed by Matti Hämäläinen <ccr@tnsp.org> -// (C) Copyright 2017 Tecnic Software productions (TNSP) -// -// Distributed under 3-clause BSD style license, refer to -// included file "COPYING" for exact terms. -// -#ifndef SYNTILISTA_H -#define SYNTILISTA_H - -#include <QMainWindow> -#include <QShortcut> -#include <QDialog> -#include <QtSql> -#include <QSqlQueryModel> - - -// -// Global application defines -// -#define APP_VENDOR "TNSP" // Vendor ID (for settings, etc.) -#define APP_ID "Kampus Syntilista" // Application ID (for settings) -#define APP_NAME "Café Kampus Syntilista" // Application title/name -#define APP_SQLITE_FILE "syntilista.sqlite3" // SQLite3 database file name (without path) - - -// -// Custom SQL models -// -class PersonInfo : public QObject -{ - Q_OBJECT - -public: - explicit PersonInfo() - { - id = -1; - firstName = ""; - lastName = ""; - extraInfo = ""; - balance = 0; - } - - ~PersonInfo() - { - } - - void dump(); - - qint64 id; - QString firstName, lastName, extraInfo; - double balance; - QDateTime added, updated; -}; - - - -class PersonSQLModel : public QSqlQueryModel -{ - Q_OBJECT - -private: - -public: - PersonSQLModel(QObject *parent = 0); - - QVariant data(const QModelIndex &item, int role) const Q_DECL_OVERRIDE; - - int updatePerson(const PersonInfo &person); - int addPerson(const PersonInfo &person); - int deletePerson(qint64 id); - void updateModel(); -}; - - - -class TransactionSQLModel : public QSqlQueryModel -{ - Q_OBJECT - -private: - -public: - TransactionSQLModel(QObject *parent = 0); - - QVariant data(const QModelIndex &item, int role) const Q_DECL_OVERRIDE; - - void updateModel(); -}; - - - -// -// Main window -// -namespace Ui { -class SyntilistaMainWindow; -class EditPerson; -} - -class SyntilistaMainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit SyntilistaMainWindow(QWidget *parent = 0); - ~SyntilistaMainWindow(); - - void statusMsg(const QString &msg); - - void readSettings(); - void saveSettings(); - void setActivePerson(qint64 id); - int addTransaction(qint64 id, double value, PersonInfo &info); - int addTransactionGUI(qint64 id, bool debt, double value); - void updatePersonList(); - - PersonSQLModel *model_People; - -private slots: - void on_button_AddPerson_clicked(); - void on_button_EditPerson_clicked(); - void on_button_DeletePerson_clicked(); - - void on_edit_PersonFilter_textChanged(const QString &arg1); - void on_button_ClearFilter_clicked(); - - void on_button_Quit_clicked(); - void on_button_About_clicked(); - void on_button_Help_clicked(); - - void on_button_AddDebt_clicked(); - void on_button_PayDebt_clicked(); - void on_button_PayFullDebt_clicked(); - - void on_tableview_People_doubleClicked(const QModelIndex &index); - - void selectedPersonChanged(const QModelIndex &, const QModelIndex &); - - void focusDebtEdit(); - void selectRowPrev(); - void selectRowNext(); - - void changeUIZoomIn(); - void changeUIZoomOut(); - void changeUIZoomReset(); - - void updateSortOrder(int index, Qt::SortOrder order); - - -private: - Ui::SyntilistaMainWindow *ui; - - TransactionSQLModel *model_Latest; - PersonInfo currPerson; - - int peopleSortIndex; - Qt::SortOrder peopleSortOrder; - QString peopleFilter; -}; - - -// -// Person edit / new person dialog -// -class EditPerson : public QDialog -{ - Q_OBJECT - -public: - explicit EditPerson(QWidget *parent = 0); - ~EditPerson(); - - void statusMsg(const QString &msg); - - void clearForm(); - bool validateForm(); - void setPerson(qint64 id); - -private slots: - void on_button_OK_clicked(); - - void on_button_Cancel_clicked(); - - void on_edit_FirstName_textChanged(const QString &arg1); - - void on_edit_LastName_textChanged(const QString &arg1); - -private: - Ui::EditPerson *ui; - - PersonInfo selPerson; - TransactionSQLModel *model_Transactions; -}; - -#endif // SYNTILISTA_H
--- a/mainwindow.ui Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SyntilistaMainWindow</class> - <widget class="QMainWindow" name="SyntilistaMainWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>835</width> - <height>646</height> - </rect> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QGroupBox" name="henkilotGB"> - <property name="title"> - <string>Henkilöt</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Etsi / suodata</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="edit_PersonFilter"/> - </item> - <item> - <widget class="QPushButton" name="button_ClearFilter"> - <property name="text"> - <string>Tyhjennä suodatin</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTableView" name="tableview_People"> - <property name="selectionMode"> - <enum>QAbstractItemView::SingleSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="button_DeletePerson"> - <property name="text"> - <string>Poista henkilö</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="button_AddPerson"> - <property name="text"> - <string>Lisää uusi henkilö</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_EditPerson"> - <property name="text"> - <string>Muokkaa henkilöä</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item> - <widget class="QGroupBox" name="personGB"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Henkilön syntilista</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="flat"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item> - <widget class="QLabel" name="label_PersonName"> - <property name="text"> - <string>Henkilön nimi</string> - </property> - </widget> - </item> - <item> - <widget class="Line" name="line"> - <property name="lineWidth"> - <number>4</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="label_CurrentBalance"> - <property name="text"> - <string>Nykyinen tase:</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_BalanceValue"> - <property name="text"> - <string>12345</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_EUR"> - <property name="text"> - <string>EUR</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="Line" name="line_2"> - <property name="lineWidth"> - <number>4</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="edit_Amount"> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QPushButton" name="button_AddDebt"> - <property name="text"> - <string>Lisää velkaa</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_PayDebt"> - <property name="text"> - <string>Maksa velkaa</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QPushButton" name="button_PayFullDebt"> - <property name="text"> - <string>Maksa koko velka</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Viimeisimmät tapahtumat:</string> - </property> - </widget> - </item> - <item> - <widget class="QTableView" name="tableview_Latest"> - <property name="selectionMode"> - <enum>QAbstractItemView::SingleSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QLabel" name="button_LogoImage"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item> - <widget class="QPushButton" name="button_About"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="resources.qrc"> - <normaloff>:/img/icon-64.png</normaloff>:/img/icon-64.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="button_Help"> - <property name="text"> - <string>?</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="button_Quit"> - <property name="text"> - <string>Poistu ohjelmasta</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <tabstops> - <tabstop>edit_PersonFilter</tabstop> - <tabstop>button_ClearFilter</tabstop> - <tabstop>button_AddPerson</tabstop> - <tabstop>button_Quit</tabstop> - </tabstops> - <resources> - <include location="resources.qrc"/> - </resources> - <connections/> -</ui>
--- a/resources.qrc Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -<RCC> - <qresource prefix="img"> - <file>logo.png</file> - <file>icon-64.png</file> - </qresource> -</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/editperson.ui Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>EditPerson</class> + <widget class="QDialog" name="EditPerson"> + <property name="windowModality"> + <enum>Qt::NonModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>564</width> + <height>500</height> + </rect> + </property> + <property name="windowTitle"> + <string>Muokkaa henkilöä</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Henkilön perustiedot</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_FirstName"> + <property name="text"> + <string>Etunimi</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_LastName"> + <property name="text"> + <string>Sukunimi</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="edit_LastName"/> + </item> + <item row="1" column="0"> + <widget class="QLineEdit" name="edit_FirstName"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_ExtraInfo"> + <property name="text"> + <string>Lisätietoja:</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QPlainTextEdit" name="textedit_ExtraInfo"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Tapahtumat:</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QTableView" name="tableview_Transactions"> + <property name="contextMenuPolicy"> + <enum>Qt::DefaultContextMenu</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="button_Cancel"> + <property name="text"> + <string>Peruuta</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_OK"> + <property name="text"> + <string>Talleta / OK</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <tabstops> + <tabstop>edit_FirstName</tabstop> + <tabstop>edit_LastName</tabstop> + <tabstop>textedit_ExtraInfo</tabstop> + <tabstop>button_OK</tabstop> + <tabstop>button_Cancel</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cpp Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,1189 @@ +// +// Syntilista - velkalistasovellus Kampus-kahvilaan +// Programmed and designed by Matti Hämäläinen <ccr@tnsp.org> +// (C) Copyright 2017 Tecnic Software productions (TNSP) +// +// Distributed under 3-clause BSD style license, refer to +// included file "COPYING" for exact terms. +// +#include <QApplication> +#include <QMessageBox> +#include <QSettings> +#include "main.h" +#include "ui_mainwindow.h" +#include "ui_editperson.h" + +double setScale; + + +int errorMsg(QString title, QString msg) +{ + QMessageBox dlg; + + dlg.setText(title); + dlg.setInformativeText(msg); + dlg.setTextFormat(Qt::RichText); + dlg.setIcon(QMessageBox::Critical); + dlg.setStandardButtons(QMessageBox::Ok); + dlg.setDefaultButton(QMessageBox::Ok); + + return dlg.exec(); +} + + +double moneyStrToValue(const QString &str) +{ + QString str2 = str; + return str2.replace(",", ".").toDouble(); +} + + +QString moneyValueToStr(double val) +{ + return QStringLiteral("%1").arg(val, 1, 'f', 2); +} + + +QString cleanupStr(const QString &str) +{ + return str.simplified().trimmed(); +} + + +const QString dateTimeToStr(const QDateTime &val) +{ + QDateTime tmp = val; + tmp.setOffsetFromUtc(0); + return tmp.toLocalTime().toString(QStringLiteral("yyyy-MM-dd hh:mm")); +} + + +bool checkAndReportSQLError(const QString where, const QSqlError &err) +{ + if (err.isValid()) + { + printf("SQL Error in %s: %s\n", + where.toUtf8().constData(), + err.text().toUtf8().constData()); + return false; + } + else + return true; +} + + +void PersonInfo::dump() +{ + printf("PersonInfo() #%lld '%s %s' (added=%s, updated=%s, balance %1.2f)\n#%s#\n", + id, + firstName.toUtf8().constData(), + lastName.toUtf8().constData(), + dateTimeToStr(added).toUtf8().constData(), + dateTimeToStr(updated).toUtf8().constData(), + balance, + extraInfo.toUtf8().constData()); +} + + +// +// Get PersonInfo record from SQL database for specified persn ID # +// +bool getPersonInfo(qint64 id, PersonInfo &info) +{ + QSqlQuery person; + person.prepare( + "SELECT id,first_name,last_name,extra_info,added,updated, " + "(SELECT SUM(value) FROM transactions WHERE transactions.person=people.id) AS balance " + "FROM people WHERE id=?"); + + person.addBindValue(id); + person.exec(); + if (!person.next()) + return false; + + info.id = person.value(0).toInt(); + info.firstName = person.value(1).toString(); + info.lastName = person.value(2).toString(); + info.extraInfo = person.value(3).toString(); + info.added = person.value(4).toDateTime(); + info.updated = person.value(5).toDateTime(); + info.balance = person.value(6).toDouble(); + + person.finish(); + + return true; +} + + +void setCommonStyleSheet(QWidget *widget) +{ + // Clamp scale value + if (setScale < 0.5f) + setScale = 0.5f; + if (setScale > 3.0f) + setScale = 3.0f; + + // Set the stylesheet + widget->setStyleSheet( + QStringLiteral( + "* { font-size: %1pt; }" + "QPushButton { font-size: %2pt; padding: 0.25em; }" + "#button_AddDebt[enabled='true'] { font-size: %3pt; background-color: #900; color: white; }" + "#button_PayDebt[enabled='true'] { font-size: %3pt; background-color: #090; color: white; }" + "#button_PayFullDebt[enabled='true'] { background-color: #060; color: white; }" + + "#button_AddDebt[enabled='false'] { font-size: %3pt; background-color: #622; color: black; }" + "#button_PayDebt[enabled='false'] { font-size: %3pt; background-color: #262; color: black; }" + "#button_PayFullDebt[enabled='false'] { background-color: #131; color: black; }" + + "#label_PersonName { font-size: %5pt; font-weight: bold; }" + "#label_BalanceValue { font-size: %4pt; font-weight: bold; }" + "#label_EUR { font-size: %4pt; font-weight: bold; }" + "#edit_Amount { font-size: %4pt; margin: 0.5em; padding: 0.5em; }" + ). + arg(12 * setScale). + arg(14 * setScale). + arg(16 * setScale). + arg(18 * setScale). + arg(20 * setScale) + ); +} + + +int main(int argc, char *argv[]) +{ + QApplication sapp(argc, argv); + + // + // Initialize / open SQL database connection + // + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(qApp->applicationDirPath() + + QDir::separator() + APP_SQLITE_FILE); + + if (!db.open()) + { + errorMsg( + QObject::tr("Tietokantaa ei voitu avata"), + QObject::tr("Yhteyttä SQL-tietokantaan ei saatu.<br><br>Virhe: %1<br><br>"). + arg(db.lastError().text()) + ); + return 1; + } + + QSqlQuery query; + if (!db.tables().contains("people")) + { + query.exec(QStringLiteral( + "CREATE TABLE people (id INTEGER PRIMARY KEY, " + "first_name VARCHAR(128) NOT NULL, " + "last_name VARCHAR(128) NOT NULL, " + "extra_info VARCHAR(2048), " + "added DATETIME NOT NULL, " + "updated DATETIME NOT NULL)")); + + checkAndReportSQLError("CREATE TABLE people", query.lastError()); + } + + if (!db.tables().contains("transactions")) + { + query.exec(QStringLiteral( + "CREATE TABLE transactions (" + "id INTEGER PRIMARY KEY, " + "person INT NOT NULL, " + "value REAL, " + "added DATETIME NOT NULL)")); + + checkAndReportSQLError("CREATE TABLE transactions", query.lastError()); + } + + SyntilistaMainWindow swin; + swin.show(); + return sapp.exec(); +} + + +// +// Main application window code +// +SyntilistaMainWindow::SyntilistaMainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::SyntilistaMainWindow) +{ + // Setup UI + ui->setupUi(this); + + // Read config + readSettings(); + + // Setup other UI things + setWindowIcon(QIcon(QPixmap(":/img/icon-64.png"))); + setWindowTitle(tr("%1 versio %3"). + arg(tr(APP_NAME)). + arg(tr(APP_VERSION))); + + QPixmap logoImage(":/img/logo.png"); + ui->button_LogoImage->setPixmap(logoImage); + ui->button_LogoImage->setAlignment(Qt::AlignCenter); + + setCommonStyleSheet(this); + + // Validator for amount input + //ui->edit_Amount->setValidator(new QDoubleValidator(0, 1000, 2, this)); + QRegExp vregex("\\d{0,4}[,.]\\d{0,2}|\\d{0,4}"); + ui->edit_Amount->setValidator(new QRegExpValidator(vregex, this)); + + // Setup person list filtering and sorting + peopleSortIndex = 1; + peopleSortOrder = Qt::AscendingOrder; + peopleFilter = ""; + + model_People = new PersonSQLModel(); + updatePersonList(); + + ui->tableview_People->setModel(model_People); + ui->tableview_People->setColumnHidden(0, true); + ui->tableview_People->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_People)); + ui->tableview_People->verticalHeader()->setVisible(false); + ui->tableview_People->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + ui->tableview_People->setSortingEnabled(true); + ui->tableview_People->sortByColumn(peopleSortIndex, peopleSortOrder); + + connect( + ui->tableview_People->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, + SLOT(selectedPersonChanged(const QModelIndex &, const QModelIndex &))); + + connect( + ui->tableview_People->horizontalHeader(), + SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), + this, + SLOT(updateSortOrder(int, Qt::SortOrder))); + + ui->tableview_People->horizontalHeader()->setSortIndicator(1, Qt::AscendingOrder); + + model_Latest = new TransactionSQLModel(); + ui->tableview_Latest->setModel(model_Latest); + ui->tableview_Latest->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Latest)); + ui->tableview_Latest->verticalHeader()->setVisible(false); + ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + setActivePerson(-1); + + // Keyboard shortcuts + ui->button_Quit->setShortcut(QKeySequence(Qt::Key_F10)); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this, SLOT(on_button_Quit_clicked())); + + ui->button_AddPerson->setShortcut(QKeySequence(Qt::Key_F5)); + ui->button_DeletePerson->setShortcut(QKeySequence(Qt::Key_F8)); + ui->button_EditPerson->setShortcut(QKeySequence(Qt::Key_F6)); + ui->button_ClearFilter->setShortcut(QKeySequence(Qt::Key_Escape)); + ui->button_Help->setShortcut(QKeySequence(Qt::Key_F1)); + ui->button_About->setShortcut(QKeySequence(Qt::Key_F2)); + + new QShortcut(QKeySequence(QKeySequence::ZoomIn), this, SLOT(changeUIZoomIn())); + new QShortcut(QKeySequence(QKeySequence::ZoomOut), this, SLOT(changeUIZoomOut())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_Plus), this, SLOT(changeUIZoomIn())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_Minus), this, SLOT(changeUIZoomOut())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::KeypadModifier + Qt::Key_0), this, SLOT(changeUIZoomReset())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_0), this, SLOT(changeUIZoomReset())); + + new QShortcut(QKeySequence(Qt::Key_PageUp), this, SLOT(selectRowPrev())); + new QShortcut(QKeySequence(Qt::Key_PageDown), this, SLOT(selectRowNext())); + + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(focusDebtEdit())); +} + + +SyntilistaMainWindow::~SyntilistaMainWindow() +{ + saveSettings(); + + delete ui; + delete model_People; + delete model_Latest; +} + + +void SyntilistaMainWindow::statusMsg(const QString &msg) +{ + ui->statusbar->showMessage(msg); +} + + +void SyntilistaMainWindow::readSettings() +{ + QSettings settings(APP_VENDOR, APP_ID); + move(settings.value("pos", QPoint(100, 100)).toPoint()); + resize(settings.value("size", QSize(1000, 600)).toSize()); + setScale = settings.value("scale", 1.0f).toDouble(); +} + + +void SyntilistaMainWindow::saveSettings() +{ + QSettings settings(APP_VENDOR, APP_ID); + settings.setValue("pos", pos()); + settings.setValue("size", size()); + settings.setValue("scale", setScale); +} + + +void SyntilistaMainWindow::changeUIZoomIn() +{ + setScale += 0.1f; + setCommonStyleSheet(this); +} + + +void SyntilistaMainWindow::changeUIZoomOut() +{ + setScale -= 0.1f; + setCommonStyleSheet(this); +} + + +void SyntilistaMainWindow::changeUIZoomReset() +{ + setScale = 1.0f; + setCommonStyleSheet(this); +} + + +void SyntilistaMainWindow::selectedPersonChanged(const QModelIndex &curr, const QModelIndex &prev) +{ + (void) prev; + int row = curr.row(); + if (row >= 0) + { + const QAbstractItemModel *model = curr.model(); + setActivePerson(model->data(model->index(row, 0)).toInt()); + } + else + setActivePerson(-1); +} + + +void SyntilistaMainWindow::updateSortOrder(int index, Qt::SortOrder order) +{ + peopleSortIndex = index; + peopleSortOrder = order; + updatePersonList(); +} + + +void SyntilistaMainWindow::setActivePerson(qint64 id) +{ + currPerson.id = id; + + ui->button_EditPerson->setEnabled(id >= 0); + + if (id >= 0) + { + if (!getPersonInfo(id, currPerson)) + { + statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(id)); + } + else + { + ui->personGB->setEnabled(true); + ui->label_PersonName->setText(currPerson.lastName +", "+ currPerson.firstName); + + ui->label_BalanceValue->setText(moneyValueToStr(currPerson.balance)); + ui->label_BalanceValue->setStyleSheet(currPerson.balance < 0 ? "color: red;" : "color: green;"); + ui->button_PayFullDebt->setEnabled(currPerson.balance < 0); + + QSqlQuery query; + query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC LIMIT 5"); + query.addBindValue(id); + query.exec(); + checkAndReportSQLError("SELECT transactions for tableview_Latest", query.lastError()); + + model_Latest->setQuery(query); + + model_Latest->setHeaderData(0, Qt::Horizontal, tr("ID")); + model_Latest->setHeaderData(1, Qt::Horizontal, tr("Summa")); + model_Latest->setHeaderData(2, Qt::Horizontal, tr("Aika")); + + ui->tableview_Latest->setModel(model_Latest); + ui->tableview_Latest->setColumnHidden(0, true); + ui->tableview_Latest->verticalHeader()->setVisible(false); + ui->tableview_Latest->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + setCommonStyleSheet(this); + return; // Ugly + } + } + + // In case of id < 0 or errors .. + ui->personGB->setEnabled(false); + ui->edit_Amount->clear(); + ui->label_BalanceValue->setText("--"); + ui->label_BalanceValue->setStyleSheet(NULL); + ui->label_PersonName->setText("???"); + ui->tableview_Latest->setModel(NULL); + setCommonStyleSheet(this); +} + + +// +// Widget slot handlers +// +void SyntilistaMainWindow::on_button_Quit_clicked() +{ + close(); +} + + +void SyntilistaMainWindow::on_button_About_clicked() +{ + QMessageBox dlg; + + setCommonStyleSheet(&dlg); + dlg.setWindowTitle(tr("Tietoja ohjelmasta")); + dlg.setTextFormat(Qt::RichText); + dlg.setIconPixmap(QPixmap(":/img/icon-64.png")); + dlg.setStandardButtons(QMessageBox::Ok); + dlg.setDefaultButton(QMessageBox::Ok); + + //dlg.setInformativeText(tr( + dlg.setText(tr( + "<h1>%1 v%2</h1>" + "<p>" + "<b>Ohjelmoinut ja kehittänyt Matti Hämäläinen <ccr@tnsp.org><br>" + "(C) Copyright 2017 Tecnic Software productions (TNSP)</b><br>" + "<br>" + "Kehitetty Raahen kaupungin Hanketoiminta ja Kehittäminen -yksikön " + "alaisuudessa Café Kampuksen käyttöön.<br>" + "</p>" + "<p>" + "Ohjelma ja sen lähdekoodi ovat uudemman BSD-tyylisen lisenssin alaisia. " + "Lue ohjelman mukana tullut tiedosto \"COPYING\" (tai \"COPYING.txt\") " + "nähdäksesi täydelliset lisenssiehdot." + "</p>" + ). + arg(tr(APP_NAME)). + arg(tr(APP_VERSION)) + ); + + dlg.exec(); +} + + +void SyntilistaMainWindow::on_button_Help_clicked() +{ + QMessageBox dlg; + + setCommonStyleSheet(&dlg); + dlg.setWindowTitle(tr("Tietoja ohjelmasta")); + dlg.setTextFormat(Qt::RichText); + dlg.setIconPixmap(QPixmap(":/img/icon-64.png")); + dlg.setStandardButtons(QMessageBox::Ok); + dlg.setDefaultButton(QMessageBox::Ok); + + dlg.setText(tr( + "<h1>Pikanäppäimet</h1>" + "<table>" + "<tr><td><b>F1</b></td><td>Tämä tietoikkuna</td></tr>" + "<tr><td><b>F2</b></td><td>Tietoja ohjelmasta</td></tr>" + "<tr><td><b>CTRL + Q</b></td><td>Ohjelman lopetus</td></tr>" + "<tr><td><b>CTRL + Page Up</b></td><td>Suurenna ohjelman tekstejä/käyttöliittymää</td></tr>" + "<tr><td><b>CTRL + Page Down</b></td><td>Pienennä ohjelman tekstejä/käyttöliittymää</td></tr>" + "<tr></tr>" + "<tr><td><b>Esc</b></td><td>Tyhjennä 'Etsi / suodata' kenttä ja siirry siihen</td></tr>" + "<tr><td><b>CTRL + Enter</b></td><td>Siirry summan syöttökenttään</td></tr>" + "<tr><td><b>Page Up</b></td><td>Siirry ylös henkilölistassa</td></tr>" + "<tr><td><b>Page Down</b></td><td>Siirry alas henkilölistassa</td></tr>" + "<tr></tr>" + "<tr><td><b>F5</b></td><td>Lisää uusi henkilö</td></tr>" + "<tr><td><b>F6</b></td><td>Muokkaa henkilöä</td></tr>" + "<tr><td><b>F8</b></td><td>Poista henkilö</td></tr>" + "</table>" + )); + + dlg.exec(); +} + + +void SyntilistaMainWindow::on_button_DeletePerson_clicked() +{ + if (currPerson.id <= 0) + { + statusMsg(tr("Ei valittua henkilöä!")); + return; + } + + PersonInfo info; + if (!getPersonInfo(currPerson.id, info)) + { + statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(currPerson.id)); + return; + } + + QMessageBox dlg; + setCommonStyleSheet(&dlg); + dlg.setText(tr("Varmistus")); + dlg.setInformativeText( + tr("<br>Haluatko varmasti poistaa henkilön:<br>" + "<br>" + "<b>'%1, %2'</b> <i>(ID #%3)</i>?<br>" + "<br>" + "Tämä poistaa sekä henkilön ja hänen koko tapahtumahistoriansa PYSYVÄSTI!<br>"). + arg(info.lastName).arg(info.firstName).arg(info.id)); + + dlg.setTextFormat(Qt::RichText); + dlg.setIcon(QMessageBox::Question); + dlg.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + dlg.setButtonText(QMessageBox::Yes, tr("Kyllä")); + dlg.setButtonText(QMessageBox::No, tr("Ei / peruuta")); + dlg.setDefaultButton(QMessageBox::No); + + if (dlg.exec() == QMessageBox::Yes) + { + int rv = model_People->deletePerson(info.id); + updatePersonList(); + setActivePerson(-1); + if (rv != 0) + { + errorMsg(tr("SQL-tietokantavirhe"), + tr("Henkilön tietoja poistettaessa tapahtui virhe #%1."). + arg(rv)); + } + else + { + statusMsg(tr("Henkilö '%1 %2' (ID #%3) poistettu."). + arg(info.firstName).arg(info.lastName). + arg(info.id)); + } + } +} + + +void SyntilistaMainWindow::on_button_AddPerson_clicked() +{ + EditPerson *person = new EditPerson(this); + person->setPerson(-1); +} + + +void SyntilistaMainWindow::on_button_EditPerson_clicked() +{ + if (currPerson.id >= 0) + { + EditPerson *person = new EditPerson(this); + person->setPerson(currPerson.id); + } +} + + +void SyntilistaMainWindow::on_tableview_People_doubleClicked(const QModelIndex &curr) +{ + int row = curr.row(); + if (row >= 0) + { + const QAbstractItemModel *model = curr.model(); + setActivePerson(model->data(model->index(row, 0)).toInt()); + + EditPerson *person = new EditPerson(this); + person->setPerson(currPerson.id); + } + else + setActivePerson(-1); +} + + +void SyntilistaMainWindow::on_button_ClearFilter_clicked() +{ + ui->edit_PersonFilter->clear(); + ui->edit_PersonFilter->setFocus(Qt::ShortcutFocusReason); +} + + +void SyntilistaMainWindow::focusDebtEdit() +{ + if (currPerson.id >= 0) + ui->edit_Amount->setFocus(Qt::ShortcutFocusReason); +} + + +void SyntilistaMainWindow::selectRowPrev() +{ + QItemSelectionModel *sel = ui->tableview_People->selectionModel(); + int row = sel->currentIndex().row() - 1; + if (row < 0) + row = 0; + + sel->setCurrentIndex(model_People->index(row, 0), + QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows); +} + + +void SyntilistaMainWindow::selectRowNext() +{ + QItemSelectionModel *sel = ui->tableview_People->selectionModel(); + int row = sel->currentIndex().row() + 1; + if (row >= model_People->rowCount()) + row = model_People->rowCount() - 1; + + sel->setCurrentIndex(model_People->index(row, 0), + QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows); +} + + +// +// Update visible person list/query based on the current +// filtering and sorting settings. +// +void SyntilistaMainWindow::updatePersonList() +{ + static QString queryBase = + "SELECT id,last_name,first_name," + "(SELECT SUM(value) FROM transactions WHERE transactions.person=people.id) AS balance," + "updated FROM people"; + + QSqlQuery query; + QString queryOrderDir, queryOrderBy; + + // Sort order + if (peopleSortOrder == Qt::AscendingOrder) + queryOrderDir = QStringLiteral("ASC"); + else + queryOrderDir = QStringLiteral("DESC"); + + // Sort by which column + switch (peopleSortIndex) + { + case 1: + case 2: + queryOrderBy = QStringLiteral(" ORDER BY last_name ") + queryOrderDir + QStringLiteral(",first_name ") + queryOrderDir; + break; + + case 3: + queryOrderBy = QStringLiteral(" ORDER BY balance ") + queryOrderDir; + break; + + case 4: + queryOrderBy = QStringLiteral(" ORDER BY updated ") + queryOrderDir; + break; + + default: + queryOrderBy = ""; + } + + // Are we filtering or not? + if (peopleFilter != "") + { + // Filter by name(s) + QString tmp = "%"+ peopleFilter +"%"; + query.prepare(queryBase +" WHERE first_name LIKE ? OR last_name LIKE ?" + queryOrderBy); + + query.addBindValue(tmp); + query.addBindValue(tmp); + } + else + { + // No filter + query.prepare(queryBase + queryOrderBy); + } + + // Execute the query and update model + checkAndReportSQLError("updatePersonList() before exec", query.lastError()); + query.exec(); + checkAndReportSQLError("updatePersonList() after exec", query.lastError()); + + model_People->setQuery(query); + + model_People->setHeaderData(0, Qt::Horizontal, tr("ID")); + model_People->setHeaderData(1, Qt::Horizontal, tr("Sukunimi")); + model_People->setHeaderData(2, Qt::Horizontal, tr("Etunimi")); + model_People->setHeaderData(3, Qt::Horizontal, tr("Tase")); + model_People->setHeaderData(4, Qt::Horizontal, tr("Muutettu")); +} + + +// +// Update the list of people when filter parameter changes +// +void SyntilistaMainWindow::on_edit_PersonFilter_textChanged(const QString &str) +{ + peopleFilter = cleanupStr(str); + updatePersonList(); +} + + +// +// Add one transaction to given person id +// +int SyntilistaMainWindow::addTransaction(qint64 id, double value, PersonInfo &info) +{ + if (!getPersonInfo(id, info)) + return -1; + + QSqlDatabase::database().transaction(); + + QSqlQuery query; + query.prepare("INSERT INTO transactions (person,value,added) VALUES (?,?,?)"); + query.addBindValue(id); + query.addBindValue(value); + query.addBindValue(QDateTime::currentDateTimeUtc()); + query.exec(); + if (!checkAndReportSQLError("addTransaction()", query.lastError())) + { + QSqlDatabase::database().rollback(); + return -2; + } + + query.prepare("UPDATE people SET updated=? WHERE id=?"); + query.addBindValue(QDateTime::currentDateTimeUtc()); + query.addBindValue(id); + query.exec(); + if (!checkAndReportSQLError("addTransaction update timestamp", query.lastError())) + { + QSqlDatabase::database().rollback(); + return -3; + } + + QSqlDatabase::database().commit(); + + return 0; +} + + +int SyntilistaMainWindow::addTransactionGUI(qint64 id, bool debt, double value) +{ + PersonInfo info; + + // Check if person is selected + if (id <= 0) + return -1; + + // Check value + if (value == 0) + { + QString tmp = (debt ? "lisätty" : "vähennetty"); + statusMsg("Velkaa ei "+ tmp +" koska summaa ei määritetty."); + return 1; + } + + // Perform transaction insert + int ret = addTransaction(id, debt ? -value : value, info); + if (ret == 0) + { + // All ok, clear amount entry and update person data + ui->edit_Amount->clear(); + if (info.id == currPerson.id) + setActivePerson(info.id); + + model_People->updateModel(); + + QString str; + if (debt) + { + str = tr("Lisättiin velkaa %1 EUR henkilölle '%2 %3' (#%4)."). + arg(moneyValueToStr(value)). + arg(info.firstName). + arg(info.lastName). + arg(info.id); + } + else + { + str = tr("Vähennettiin velkaa %1 EUR henkilöltä '%2 %3' (#%4)."). + arg(moneyValueToStr(value)). + arg(info.firstName). + arg(info.lastName). + arg(info.id); + } + statusMsg(str); + } + else + { + errorMsg( + tr("SQL-tietokantavirhe"), + tr("Tietokantaan tapahtumaa lisättäessa tapahtui virhe #%1."). + arg(ret)); + } + + return ret; +} + + +void SyntilistaMainWindow::on_button_AddDebt_clicked() +{ + addTransactionGUI(currPerson.id, true, moneyStrToValue(ui->edit_Amount->text())); +} + + +void SyntilistaMainWindow::on_button_PayDebt_clicked() +{ + addTransactionGUI(currPerson.id, false, moneyStrToValue(ui->edit_Amount->text())); +} + + +void SyntilistaMainWindow::on_button_PayFullDebt_clicked() +{ + if (currPerson.balance < 0) + addTransactionGUI(currPerson.id, false, -currPerson.balance); + else + { + statusMsg( + tr("Valitulla henkilöllä '%1, %2' ei ole velkaa."). + arg(currPerson.lastName). + arg(currPerson.firstName)); + } +} + + +// +// Edit person dialog +// +EditPerson::EditPerson(QWidget *parent) : + QDialog(parent), + ui(new Ui::EditPerson) +{ + ui->setupUi(this); + + setCommonStyleSheet(this); + + setModal(true); + setAttribute(Qt::WA_DeleteOnClose); + show(); + activateWindow(); + raise(); + setFocus(); + + model_Transactions = new TransactionSQLModel(); + ui->tableview_Transactions->setModel(model_Transactions); + ui->tableview_Transactions->setItemDelegate(new QSqlRelationalDelegate(ui->tableview_Transactions)); + ui->tableview_Transactions->verticalHeader()->setVisible(false); + ui->tableview_Transactions->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + validateForm(); +} + + +EditPerson::~EditPerson() +{ + delete ui; + delete model_Transactions; +} + + +void EditPerson::statusMsg(const QString &msg) +{ + dynamic_cast<SyntilistaMainWindow *>(parent())->statusMsg(msg); +} + + +bool EditPerson::validateForm() +{ + selPerson.firstName = cleanupStr(ui->edit_FirstName->text()); + selPerson.lastName = cleanupStr(ui->edit_LastName->text()); + selPerson.extraInfo = ui->textedit_ExtraInfo->document()->toPlainText(); + + ui->edit_FirstName->setStyleSheet(selPerson.firstName == "" ? "background-color: red;" : NULL); + ui->edit_LastName->setStyleSheet(selPerson.lastName == "" ? "background-color: red;" : NULL); + + return selPerson.firstName != "" && selPerson.lastName != ""; +} + + +void EditPerson::on_button_Cancel_clicked() +{ + close(); +} + + +void EditPerson::on_button_OK_clicked() +{ + if (!validateForm()) + { + errorMsg( + tr("Virhe!"), + tr("Vaaditut kentät (etunimi, sukunimi) eivät ole täytetty.")); + + return; + } + + if (selPerson.id >= 0) + { + QSqlQuery person; + person.prepare("SELECT * FROM people WHERE id <> ? AND first_name=? AND last_name=?"); + person.addBindValue(selPerson.id); + person.addBindValue(selPerson.firstName); + person.addBindValue(selPerson.lastName); + person.exec(); + + checkAndReportSQLError("SELECT check for existing person by same name (UPDATE)", person.lastError()); + + if (person.next()) + { + errorMsg( + tr("Virhe!"), + tr("Ei pysty! Samalla nimellä '%1 %2' on olemassa jo henkilö!"). + arg(selPerson.firstName).arg(selPerson.lastName)); + return; + } + + dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->updatePerson(selPerson); + dynamic_cast<SyntilistaMainWindow *>(parent())->setActivePerson(selPerson.id); + + statusMsg(tr("Päivitettiin henkilö '%1 %2' (#%3)."). + arg(selPerson.firstName).arg(selPerson.lastName).arg(selPerson.id)); + } + else + { + QSqlQuery person; + person.prepare("SELECT * FROM people WHERE first_name=? AND last_name=?"); + person.addBindValue(selPerson.firstName); + person.addBindValue(selPerson.lastName); + person.exec(); + + checkAndReportSQLError("SELECT check for existing person by same name (ADD)", person.lastError()); + + if (person.next()) + { + errorMsg( + tr("Virhe!"), + tr("Ei pysty! Samalla nimellä '%1 %2' on olemassa jo henkilö!"). + arg(selPerson.firstName).arg(selPerson.lastName)); + + return; + } + + dynamic_cast<SyntilistaMainWindow *>(parent())->model_People->addPerson(selPerson); + dynamic_cast<SyntilistaMainWindow *>(parent())->updatePersonList(); + + statusMsg(tr("Lisättiin uusi henkilö '%1 %2'."). + arg(selPerson.firstName).arg(selPerson.lastName)); + } + + close(); +} + + +void EditPerson::on_edit_FirstName_textChanged(const QString &arg1) +{ + (void) arg1; + validateForm(); +} + + +void EditPerson::on_edit_LastName_textChanged(const QString &arg1) +{ + (void) arg1; + validateForm(); +} + + +void EditPerson::clearForm() +{ + ui->edit_FirstName->clear(); + ui->edit_LastName->clear(); + ui->textedit_ExtraInfo->document()->clear(); + ui->edit_FirstName->setFocus(); +} + + +void EditPerson::setPerson(qint64 id) +{ + selPerson.id = id; + + if (id >= 0) + { + PersonInfo pinfo; + if (!getPersonInfo(id, pinfo)) + { + statusMsg(tr("Virhe! Ei henkilöä ID:llä #%1").arg(id)); + } + else + { + ui->edit_FirstName->setText(pinfo.firstName); + ui->edit_LastName->setText(pinfo.lastName); + ui->textedit_ExtraInfo->document()->setPlainText(pinfo.extraInfo); + + QSqlQuery query; + query.prepare("SELECT id,value,added FROM transactions WHERE person=? ORDER BY added DESC"); + query.addBindValue(pinfo.id); + query.exec(); + checkAndReportSQLError("SELECT transactions for tableview_Transactions", query.lastError()); + + model_Transactions->setQuery(query); + + model_Transactions->setHeaderData(0, Qt::Horizontal, tr("ID")); + model_Transactions->setHeaderData(1, Qt::Horizontal, tr("Summa")); + model_Transactions->setHeaderData(2, Qt::Horizontal, tr("Aika")); + + ui->tableview_Transactions->setModel(model_Transactions); + ui->tableview_Transactions->setColumnHidden(0, true); + + return; // Ugly + } + } + + // In case of id < 0 or errors .. + clearForm(); + ui->tableview_Transactions->setModel(NULL); +} + + +// +// Custom SQL models +// +PersonSQLModel::PersonSQLModel(QObject *parent) : QSqlQueryModel(parent) +{ +} + + +QVariant PersonSQLModel::data(const QModelIndex &index, int role) const +{ + QVariant value = QSqlQueryModel::data(index, role); + + if (value.isValid() && role == Qt::DisplayRole) + { + switch (index.column()) + { + case 3: + return moneyValueToStr(value.toDouble()); + + case 4: + return dateTimeToStr(value.toDateTime()); + } + } + + if (index.column() == 3 && role == Qt::ForegroundRole) + { + double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); + if (val < 0) + return QVariant::fromValue(QColor(Qt::red)); + else + return QVariant::fromValue(QColor(Qt::green)); + } + + return value; +} + + +int PersonSQLModel::updatePerson(const PersonInfo &info) +{ + QSqlQuery np; + + np.prepare("UPDATE people SET first_name=?,last_name=?,extra_info=?,updated=? WHERE id=?"); + np.addBindValue(info.firstName); + np.addBindValue(info.lastName); + np.addBindValue(info.extraInfo); + np.addBindValue(QDateTime::currentDateTimeUtc()); + np.addBindValue(info.id); + np.exec(); + + if (!checkAndReportSQLError("PersonSQLModel::updatePerson()", np.lastError())) + return -1; + + QSqlDatabase::database().commit(); + + updateModel(); + return 0; +} + + +int PersonSQLModel::addPerson(const PersonInfo &info) +{ +// beginInsertRows(QModelIndex(), rowCount(), rowCount()); + + QSqlQuery np; + np.prepare("INSERT INTO people (first_name,last_name,extra_info,added,updated) VALUES (?,?,?,?,?)"); + np.addBindValue(info.firstName); + np.addBindValue(info.lastName); + np.addBindValue(info.extraInfo); + np.addBindValue(QDateTime::currentDateTimeUtc()); + np.addBindValue(QDateTime::currentDateTimeUtc()); + np.exec(); + + if (!checkAndReportSQLError("PersonSQLModel::addPerson()", np.lastError())) + return -1; + + QSqlDatabase::database().commit(); + +// endInsertRows(); + updateModel(); + return 0; +} + + +int PersonSQLModel::deletePerson(qint64 id) +{ + QSqlDatabase::database().transaction(); + QSqlQuery del; + + del.prepare("DELETE FROM people WHERE id=?"); + del.addBindValue(id); + del.exec(); + + if (!checkAndReportSQLError("delete user", del.lastError())) + { + QSqlDatabase::database().rollback(); + return -1; + } + + del.prepare("DELETE FROM transactions WHERE person=?"); + del.addBindValue(id); + del.exec(); + + if (!checkAndReportSQLError("delete user transactions", del.lastError())) + { + QSqlDatabase::database().rollback(); + return -2; + } + + QSqlDatabase::database().commit(); + updateModel(); + return 0; +} + + +void PersonSQLModel::updateModel() +{ + query().exec(); + emit dataChanged(index(0, 0), index(rowCount(), columnCount())); +} + + +TransactionSQLModel::TransactionSQLModel(QObject *parent) : QSqlQueryModel(parent) +{ +} + + +QVariant TransactionSQLModel::data(const QModelIndex &index, int role) const +{ + QVariant value = QSqlQueryModel::data(index, role); + + if (value.isValid() && role == Qt::DisplayRole) + { + switch (index.column()) + { + case 1: + return moneyValueToStr(value.toDouble()); + + case 2: + return dateTimeToStr(value.toDateTime()); + } + } + + if (index.column() == 1 && role == Qt::ForegroundRole) + { + double val = QSqlQueryModel::data(index, Qt::DisplayRole).toDouble(); + if (val < 0) + return QVariant::fromValue(QColor(Qt::red)); + else + return QVariant::fromValue(QColor(Qt::green)); + } + + return value; +} + + +void TransactionSQLModel::updateModel() +{ + query().exec(); + emit dataChanged(QModelIndex(), QModelIndex()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.h Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,197 @@ +// +// Syntilista - velkalistasovellus Kampus-kahvilaan +// Programmed and designed by Matti Hämäläinen <ccr@tnsp.org> +// (C) Copyright 2017 Tecnic Software productions (TNSP) +// +// Distributed under 3-clause BSD style license, refer to +// included file "COPYING" for exact terms. +// +#ifndef SYNTILISTA_H +#define SYNTILISTA_H + +#include <QMainWindow> +#include <QShortcut> +#include <QDialog> +#include <QtSql> +#include <QSqlQueryModel> + + +// +// Global application defines +// +#define APP_VENDOR "TNSP" // Vendor ID (for settings, etc.) +#define APP_ID "Kampus Syntilista" // Application ID (for settings) +#define APP_NAME "Café Kampus Syntilista" // Application title/name +#define APP_SQLITE_FILE "syntilista.sqlite3" // SQLite3 database file name (without path) + + +// +// Custom SQL models +// +class PersonInfo : public QObject +{ + Q_OBJECT + +public: + explicit PersonInfo() + { + id = -1; + firstName = ""; + lastName = ""; + extraInfo = ""; + balance = 0; + } + + ~PersonInfo() + { + } + + void dump(); + + qint64 id; + QString firstName, lastName, extraInfo; + double balance; + QDateTime added, updated; +}; + + + +class PersonSQLModel : public QSqlQueryModel +{ + Q_OBJECT + +private: + +public: + PersonSQLModel(QObject *parent = 0); + + QVariant data(const QModelIndex &item, int role) const Q_DECL_OVERRIDE; + + int updatePerson(const PersonInfo &person); + int addPerson(const PersonInfo &person); + int deletePerson(qint64 id); + void updateModel(); +}; + + + +class TransactionSQLModel : public QSqlQueryModel +{ + Q_OBJECT + +private: + +public: + TransactionSQLModel(QObject *parent = 0); + + QVariant data(const QModelIndex &item, int role) const Q_DECL_OVERRIDE; + + void updateModel(); +}; + + + +// +// Main window +// +namespace Ui { +class SyntilistaMainWindow; +class EditPerson; +} + +class SyntilistaMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit SyntilistaMainWindow(QWidget *parent = 0); + ~SyntilistaMainWindow(); + + void statusMsg(const QString &msg); + + void readSettings(); + void saveSettings(); + void setActivePerson(qint64 id); + int addTransaction(qint64 id, double value, PersonInfo &info); + int addTransactionGUI(qint64 id, bool debt, double value); + void updatePersonList(); + + PersonSQLModel *model_People; + +private slots: + void on_button_AddPerson_clicked(); + void on_button_EditPerson_clicked(); + void on_button_DeletePerson_clicked(); + + void on_edit_PersonFilter_textChanged(const QString &arg1); + void on_button_ClearFilter_clicked(); + + void on_button_Quit_clicked(); + void on_button_About_clicked(); + void on_button_Help_clicked(); + + void on_button_AddDebt_clicked(); + void on_button_PayDebt_clicked(); + void on_button_PayFullDebt_clicked(); + + void on_tableview_People_doubleClicked(const QModelIndex &index); + + void selectedPersonChanged(const QModelIndex &, const QModelIndex &); + + void focusDebtEdit(); + void selectRowPrev(); + void selectRowNext(); + + void changeUIZoomIn(); + void changeUIZoomOut(); + void changeUIZoomReset(); + + void updateSortOrder(int index, Qt::SortOrder order); + + +private: + Ui::SyntilistaMainWindow *ui; + + TransactionSQLModel *model_Latest; + PersonInfo currPerson; + + int peopleSortIndex; + Qt::SortOrder peopleSortOrder; + QString peopleFilter; +}; + + +// +// Person edit / new person dialog +// +class EditPerson : public QDialog +{ + Q_OBJECT + +public: + explicit EditPerson(QWidget *parent = 0); + ~EditPerson(); + + void statusMsg(const QString &msg); + + void clearForm(); + bool validateForm(); + void setPerson(qint64 id); + +private slots: + void on_button_OK_clicked(); + + void on_button_Cancel_clicked(); + + void on_edit_FirstName_textChanged(const QString &arg1); + + void on_edit_LastName_textChanged(const QString &arg1); + +private: + Ui::EditPerson *ui; + + PersonInfo selPerson; + TransactionSQLModel *model_Transactions; +}; + +#endif // SYNTILISTA_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mainwindow.ui Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,309 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SyntilistaMainWindow</class> + <widget class="QMainWindow" name="SyntilistaMainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>835</width> + <height>646</height> + </rect> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QGroupBox" name="henkilotGB"> + <property name="title"> + <string>Henkilöt</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Etsi / suodata</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edit_PersonFilter"/> + </item> + <item> + <widget class="QPushButton" name="button_ClearFilter"> + <property name="text"> + <string>Tyhjennä suodatin</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QTableView" name="tableview_People"> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="button_DeletePerson"> + <property name="text"> + <string>Poista henkilö</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="button_AddPerson"> + <property name="text"> + <string>Lisää uusi henkilö</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_EditPerson"> + <property name="text"> + <string>Muokkaa henkilöä</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="QGroupBox" name="personGB"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Henkilön syntilista</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="QLabel" name="label_PersonName"> + <property name="text"> + <string>Henkilön nimi</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="lineWidth"> + <number>4</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="label_CurrentBalance"> + <property name="text"> + <string>Nykyinen tase:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_BalanceValue"> + <property name="text"> + <string>12345</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_EUR"> + <property name="text"> + <string>EUR</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line_2"> + <property name="lineWidth"> + <number>4</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edit_Amount"> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QPushButton" name="button_AddDebt"> + <property name="text"> + <string>Lisää velkaa</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_PayDebt"> + <property name="text"> + <string>Maksa velkaa</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="button_PayFullDebt"> + <property name="text"> + <string>Maksa koko velka</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Viimeisimmät tapahtumat:</string> + </property> + </widget> + </item> + <item> + <widget class="QTableView" name="tableview_Latest"> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="button_LogoImage"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="QPushButton" name="button_About"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="resources.qrc"> + <normaloff>:/img/icon-64.png</normaloff>:/img/icon-64.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_Help"> + <property name="text"> + <string>?</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="button_Quit"> + <property name="text"> + <string>Poistu ohjelmasta</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <tabstops> + <tabstop>edit_PersonFilter</tabstop> + <tabstop>button_ClearFilter</tabstop> + <tabstop>button_AddPerson</tabstop> + <tabstop>button_Quit</tabstop> + </tabstops> + <resources> + <include location="resources.qrc"/> + </resources> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/resources.qrc Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="img"> + <file>../img/logo.png</file> + <file>../img/icon-64.png</file> + </qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/winres.rc.in Mon Apr 24 12:12:39 2017 +0300 @@ -0,0 +1,20 @@ +MAINICON ICON "icon.ico" +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION @APP_VERSION_COM@ +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "TNSP" + VALUE "FileDescription", "Cafe Kampus Syntilista" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "Syntilista" + VALUE "LegalCopyright", "(C) Copyright 2017 Tecnic Software productions" + VALUE "OriginalFilename", "@APP_EXE@" + VALUE "ProductName", "Syntilista" + VALUE "ProductVersion", "@APP_VERSION@" + END + END +END
--- a/winres.rc.in Wed Apr 12 12:16:00 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -MAINICON ICON "icon.ico" -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION @APP_VERSION_COM@ -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - BEGIN - VALUE "CompanyName", "TNSP" - VALUE "FileDescription", "Cafe Kampus Syntilista" - VALUE "FileVersion", "1.0" - VALUE "InternalName", "Syntilista" - VALUE "LegalCopyright", "(C) Copyright 2017 Tecnic Software productions" - VALUE "OriginalFilename", "@APP_EXE@" - VALUE "ProductName", "Syntilista" - VALUE "ProductVersion", "@APP_VERSION@" - END - END -END