Initial commit
9
.classpath
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" path="gen"/>
|
||||||
|
<classpathentry kind="output" path="bin/classes"/>
|
||||||
|
</classpath>
|
33
.project
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>Journal</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
55
AndroidManifest.xml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.university.journal"
|
||||||
|
android:versionCode="1"
|
||||||
|
android:versionName="1.0" >
|
||||||
|
|
||||||
|
<uses-sdk
|
||||||
|
android:minSdkVersion="8"
|
||||||
|
android:targetSdkVersion="19" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme" >
|
||||||
|
<activity
|
||||||
|
android:name="com.university.journal.MainActivity"
|
||||||
|
android:label="@string/app_name" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider android:authorities="com.university.journal.dbprovider"
|
||||||
|
android:name="com.university.journal.db.DbContentProvider"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="com.university.journal.accounts.AccountService"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.accounts.AccountAuthenticator" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.accounts.AccountAuthenticator"
|
||||||
|
android:resource="@xml/authenticator" />
|
||||||
|
</service>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
20
proguard-project.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# To enable ProGuard in your project, edit project.properties
|
||||||
|
# to define the proguard.config property as described in that file.
|
||||||
|
#
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the ProGuard
|
||||||
|
# include property in project.properties.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
16
project.properties
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-19
|
||||||
|
android.library.reference.1=..\\TableFixHeaders
|
||||||
|
android.library.reference.2=../android-support-v7-appcompat
|
BIN
res/drawable-hdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 114 B |
BIN
res/drawable-hdpi/ic_action_export.png
Normal file
After Width: | Height: | Size: 379 B |
BIN
res/drawable-hdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
res/drawable-hdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 96 B |
BIN
res/drawable-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
res/drawable-mdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 95 B |
BIN
res/drawable-mdpi/ic_action_export.png
Normal file
After Width: | Height: | Size: 303 B |
BIN
res/drawable-mdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 124 B |
BIN
res/drawable-mdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 87 B |
BIN
res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
res/drawable-xhdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 129 B |
BIN
res/drawable-xhdpi/ic_action_export.png
Normal file
After Width: | Height: | Size: 392 B |
BIN
res/drawable-xhdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
res/drawable-xhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 109 B |
BIN
res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
res/drawable-xxhdpi/drawer_shadow.9.png
Normal file
After Width: | Height: | Size: 157 B |
BIN
res/drawable-xxhdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
res/drawable-xxhdpi/ic_drawer.png
Normal file
After Width: | Height: | Size: 111 B |
BIN
res/drawable-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
9
res/drawable/ab_background.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<gradient
|
||||||
|
android:angle="180"
|
||||||
|
android:endColor="@color/ab_background2"
|
||||||
|
android:startColor="@color/ab_background1" />
|
||||||
|
|
||||||
|
</shape>
|
7
res/drawable/bg_table_header.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle" >
|
||||||
|
|
||||||
|
<solid android:color="#CFEBD2" />
|
||||||
|
<stroke android:width="1dp" android:color="#C4E6C7" />
|
||||||
|
</shape>
|
7
res/drawable/bg_table_item1.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle" >
|
||||||
|
|
||||||
|
<solid android:color="#E4F8EA" />
|
||||||
|
<stroke android:width="1dp" android:color="#CEF2D9" />
|
||||||
|
</shape>
|
7
res/drawable/bg_table_item2.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle" >
|
||||||
|
|
||||||
|
<solid android:color="#EEEEEE" />
|
||||||
|
<stroke android:width="1dp" android:color="#E3E3E3" />
|
||||||
|
</shape>
|
10
res/drawable/list_selector.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- Pressed state. -->
|
||||||
|
<item android:drawable="@color/list_item_bg_pressed" android:state_pressed="true" />
|
||||||
|
|
||||||
|
<!-- Checked state. -->
|
||||||
|
<item android:drawable="@color/list_item_bg_checked" android:state_pressed="false" android:state_checked="true"/>
|
||||||
|
|
||||||
|
</selector>
|
34
res/layout-sw600dp-land/activity_main.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:context="com.university.journal.MainActivity" >
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The drawer is given a fixed width in dp and extends the full height of
|
||||||
|
the container.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_drawer"
|
||||||
|
android:name="com.university.journal.NavigationDrawerFragment"
|
||||||
|
android:layout_width="@dimen/navigation_drawer_width"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start" />
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
As the main content view, the view below consumes the entire
|
||||||
|
space available using match_parent in both dimensions.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
39
res/layout/activity_main.xml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
|
||||||
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context="com.university.journal.MainActivity" >
|
||||||
|
|
||||||
|
<!--
|
||||||
|
As the main content view, the view below consumes the entire
|
||||||
|
space available using match_parent in both dimensions.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
android:layout_gravity="start" tells DrawerLayout to treat
|
||||||
|
this as a sliding drawer on the left side for left-to-right
|
||||||
|
languages and on the right side for right-to-left languages.
|
||||||
|
If you're not building against API 17 or higher, use
|
||||||
|
android:layout_gravity="left" instead.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
The drawer is given a fixed width in dp and extends the full height of
|
||||||
|
the container.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/navigation_drawer"
|
||||||
|
android:name="com.university.journal.NavigationDrawerFragment"
|
||||||
|
android:layout_width="@dimen/navigation_drawer_width"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start" />
|
||||||
|
|
||||||
|
</android.support.v4.widget.DrawerLayout>
|
32
res/layout/dialog_add_criteria.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="255"
|
||||||
|
android:hint="@string/name" >
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/date"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="date"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="12"
|
||||||
|
android:hint="@string/date" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/subjectSpinner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
19
res/layout/dialog_add_group.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="16"
|
||||||
|
android:hint="@string/name" >
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
</LinearLayout>
|
19
res/layout/dialog_add_mark.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/mark"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="5"
|
||||||
|
android:maxLength="4"
|
||||||
|
android:hint="@string/mark" >
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
</LinearLayout>
|
41
res/layout/dialog_add_student.xml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/lastname"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="255"
|
||||||
|
android:hint="@string/lastname" >
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/firstname"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="255"
|
||||||
|
android:hint="@string/firstname" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/middlename"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="255"
|
||||||
|
android:hint="@string/middlename" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/groupSpinner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
28
res/layout/dialog_add_subject.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:maxLength="255"
|
||||||
|
android:hint="@string/name" >
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/shortName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="4"
|
||||||
|
android:maxLength="12"
|
||||||
|
android:hint="@string/short_name" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
29
res/layout/fragment_main.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/subjectSpinner"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/groupSpinner"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.inqbarna.tablefixheaders.TableFixHeaders
|
||||||
|
android:id="@+id/table"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</LinearLayout>
|
9
res/layout/fragment_navigation_drawer.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#C8E2F3E4"
|
||||||
|
android:choiceMode="singleChoice"
|
||||||
|
android:divider="@android:color/transparent"
|
||||||
|
android:dividerHeight="0dp"
|
||||||
|
tools:context="com.university.journal.NavigationDrawerFragment" />
|
17
res/layout/fragment_table.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:id="@+id/table"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:stretchColumns="*">
|
||||||
|
</TableLayout>
|
||||||
|
</HorizontalScrollView>
|
||||||
|
</ScrollView>
|
10
res/layout/item_nav_drawer.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
style="@style/navItemStyle"
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:checkMark="@null"
|
||||||
|
android:background="@drawable/list_selector"
|
||||||
|
/>
|
11
res/menu/add_item.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add"
|
||||||
|
android:title="@string/action_add"
|
||||||
|
android:icon="@drawable/ic_action_new"
|
||||||
|
app:showAsAction="always|withText"/>
|
||||||
|
|
||||||
|
</menu>
|
11
res/menu/item_context.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_delete"
|
||||||
|
android:title="@string/delete"
|
||||||
|
android:icon="@android:drawable/ic_menu_delete"
|
||||||
|
app:showAsAction="always|withText" />
|
||||||
|
|
||||||
|
</menu>
|
11
res/menu/main.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_export"
|
||||||
|
android:title="@string/action_export"
|
||||||
|
android:icon="@drawable/ic_action_export"
|
||||||
|
app:showAsAction="always|withText"/>
|
||||||
|
|
||||||
|
</menu>
|
19
res/values-v11/styles.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme for API 11+. This theme completely replaces
|
||||||
|
AppBaseTheme from res/values/styles.xml on API 11+ devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
|
||||||
|
<item name="android:actionBarStyle">@style/MintActionBar</item>
|
||||||
|
<item name="actionBarStyle">@style/MintActionBar</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="navItemStyle">
|
||||||
|
<item name="android:minHeight">?android:attr/listPreferredItemHeightSmall</item>
|
||||||
|
<item name="android:textAppearance">?android:attr/textAppearanceListItemSmall</item>
|
||||||
|
<item name="android:paddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
|
||||||
|
<item name="android:paddingRight">?android:attr/listPreferredItemPaddingRight</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
9
res/values/colors.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="background">#E2F3E4</color>
|
||||||
|
<color name="ab_background1">#51BB5B</color>
|
||||||
|
<color name="ab_background2">#3FA348</color>
|
||||||
|
|
||||||
|
<color name="list_item_bg_pressed">#C4E6C8</color>
|
||||||
|
<color name="list_item_bg_checked">#89D191</color>
|
||||||
|
</resources>
|
9
res/values/dimens.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Per the design guidelines, navigation drawers should be between 240dp and 320dp:
|
||||||
|
https://developer.android.com/design/patterns/navigation-drawer.html
|
||||||
|
-->
|
||||||
|
<dimen name="navigation_drawer_width">240dp</dimen>
|
||||||
|
|
||||||
|
</resources>
|
36
res/values/strings.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<string name="app_name">Журнал преподавателя</string>
|
||||||
|
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||||
|
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||||
|
<string name="action_example">Действие</string>
|
||||||
|
<string name="action_settings">Настройки</string>
|
||||||
|
<string name="action_add">Добавить</string>
|
||||||
|
<string name="action_export">Экспорт</string>
|
||||||
|
|
||||||
|
<string name="one_account_allowed">Разрешён только один аккаунт</string>
|
||||||
|
<string name="please_wait">Пожалуйста, подождите…</string>
|
||||||
|
<string name="no_data">Нет данных для отображения</string>
|
||||||
|
<string name="validate_error">Ошибка.\nПроверьте правильность ввода</string>
|
||||||
|
<string name="saved">Сохранено</string>
|
||||||
|
|
||||||
|
<string name="name">Название</string>
|
||||||
|
<string name="short_name">Сокращение</string>
|
||||||
|
<string name="lastname">Фамилия</string>
|
||||||
|
<string name="firstname">Имя</string>
|
||||||
|
<string name="middlename">Отчество</string>
|
||||||
|
<string name="date">Дата (yyyy-MM-dd)</string>
|
||||||
|
<string name="mark">Оценка или текст</string>
|
||||||
|
|
||||||
|
<string name="add">Добавить</string>
|
||||||
|
<string name="delete">Удалить</string>
|
||||||
|
|
||||||
|
<string-array name="nav_sections">
|
||||||
|
<item>Журнал</item>
|
||||||
|
<item>Дисциплины</item>
|
||||||
|
<item>Критерии оценки</item>
|
||||||
|
<item>Группы</item>
|
||||||
|
<item>Студенты</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
27
res/values/styles.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Base application theme, dependent on API level. This theme is replaced
|
||||||
|
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||||
|
-->
|
||||||
|
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
|
||||||
|
<item name="actionBarStyle">@style/MintActionBar</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Application theme. -->
|
||||||
|
<style name="AppTheme" parent="AppBaseTheme">
|
||||||
|
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="MintActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
|
||||||
|
<item name="android:background">@drawable/ab_background</item>
|
||||||
|
<item name="background">@drawable/ab_background</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="navItemStyle">
|
||||||
|
<item name="android:minHeight">?android:attr/listPreferredItemHeight</item>
|
||||||
|
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
|
||||||
|
<item name="android:paddingLeft">6dip</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
6
res/xml/authenticator.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:accountType="com.university.journal"
|
||||||
|
android:icon="@drawable/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:smallIcon="@drawable/ic_launcher" />
|
8
res/xml/db_sync.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:accountType="com.university.journal"
|
||||||
|
android:allowParallelSyncs="false"
|
||||||
|
android:contentAuthority="com.university.journal.dbprovider"
|
||||||
|
android:isAlwaysSyncable="false"
|
||||||
|
android:supportsUploading="true"
|
||||||
|
android:userVisible="true" />
|
66
src/com/university/journal/EmptyTableAdapter.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package com.university.journal;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import com.inqbarna.tablefixheaders.adapters.TableAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty adapter for marks table.
|
||||||
|
*/
|
||||||
|
public final class EmptyTableAdapter implements TableAdapter {
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
public EmptyTableAdapter(Context context) {
|
||||||
|
this.mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerDataSetObserver(DataSetObserver observer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int row, int column, View convertView, ViewGroup parent) {
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = new View(mContext);
|
||||||
|
}
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth(int column) {
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(int row) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int row, int column) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
104
src/com/university/journal/MainActivity.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package com.university.journal;
|
||||||
|
|
||||||
|
import static com.university.journal.accounts.Authenticator.ACCOUNT_TYPE;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import com.university.journal.accounts.Authenticator;
|
||||||
|
import com.university.journal.fragments.CriteriaFragment;
|
||||||
|
import com.university.journal.fragments.GroupFragment;
|
||||||
|
import com.university.journal.fragments.MainFragment;
|
||||||
|
import com.university.journal.fragments.StudentFragment;
|
||||||
|
import com.university.journal.fragments.SubjectFragment;
|
||||||
|
|
||||||
|
public final class MainActivity extends ActionBarActivity
|
||||||
|
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment managing the behaviors, interactions and presentation of the
|
||||||
|
* navigation drawer.
|
||||||
|
*/
|
||||||
|
private NavigationDrawerFragment mNavigationDrawerFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to store the last screen title. For use in
|
||||||
|
* {@link #restoreActionBar()}.
|
||||||
|
*/
|
||||||
|
private CharSequence mTitle;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
final AccountManager accountManager = AccountManager.get(this);
|
||||||
|
final Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);
|
||||||
|
if (accounts.length == 0) {
|
||||||
|
final String login = getString(R.string.app_name);
|
||||||
|
Authenticator.addAccount(login, accountManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.navigation_drawer);
|
||||||
|
mTitle = getTitle();
|
||||||
|
|
||||||
|
if (mNavigationDrawerFragment != null) {
|
||||||
|
// Set up the drawer.
|
||||||
|
mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
|
||||||
|
(DrawerLayout) findViewById(R.id.drawer_layout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNavigationDrawerItemSelected(int position) {
|
||||||
|
// update the main content by replacing fragments
|
||||||
|
Fragment frag = null;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case 0: // Æóðíàë
|
||||||
|
frag = new MainFragment();
|
||||||
|
break;
|
||||||
|
case 1: // Äèñöèïëèíû
|
||||||
|
frag = new SubjectFragment();
|
||||||
|
break;
|
||||||
|
case 2: // Êðèòåðèè
|
||||||
|
frag = new CriteriaFragment();
|
||||||
|
break;
|
||||||
|
case 3: // Ãðóïïû
|
||||||
|
frag = new GroupFragment();
|
||||||
|
break;
|
||||||
|
case 4: // Ñòóäåíòû
|
||||||
|
frag = new StudentFragment();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frag == null) return;
|
||||||
|
|
||||||
|
onSectionAttached(position);
|
||||||
|
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
fragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.container, frag).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSectionAttached(int number) {
|
||||||
|
final String[] titles = getResources().getStringArray(R.array.nav_sections);
|
||||||
|
mTitle = titles[number];
|
||||||
|
restoreActionBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreActionBar() {
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
if (actionBar == null) return;
|
||||||
|
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||||
|
actionBar.setDisplayShowTitleEnabled(true);
|
||||||
|
actionBar.setTitle(mTitle);
|
||||||
|
}
|
||||||
|
}
|
117
src/com/university/journal/MarksTableAdapter.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package com.university.journal;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.inqbarna.tablefixheaders.adapters.BaseTableAdapter;
|
||||||
|
import com.university.journal.entity.Criteria;
|
||||||
|
import com.university.journal.entity.MarksTableItem;
|
||||||
|
|
||||||
|
public final class MarksTableAdapter extends BaseTableAdapter {
|
||||||
|
|
||||||
|
private static final int VIEW_TYPE_HEADER = 0, VIEW_TYPE_MARK = 1;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final Criteria[] mHeaders;
|
||||||
|
private final MarksTableItem[] mItems;
|
||||||
|
private final int mColumnHeaderHeight, mRowHeaderWidth, mWidth, mHeight;
|
||||||
|
|
||||||
|
private View.OnClickListener mMarkClickListener;
|
||||||
|
|
||||||
|
public MarksTableAdapter(Context context, Criteria[] headers, MarksTableItem[] items) {
|
||||||
|
mContext = context;
|
||||||
|
mHeaders = headers;
|
||||||
|
mItems = items;
|
||||||
|
|
||||||
|
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||||
|
mRowHeaderWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 125, dm));
|
||||||
|
mWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, dm));
|
||||||
|
mColumnHeaderHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, dm));
|
||||||
|
mHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, dm));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Criteria getHeader(int column) {
|
||||||
|
return mHeaders[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarksTableItem getItem(int row) {
|
||||||
|
return mItems[row];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarkClickListener(View.OnClickListener markClickListener) {
|
||||||
|
mMarkClickListener = markClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return mItems.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return mHeaders.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int row, int column, View convertView, ViewGroup parent) {
|
||||||
|
switch (getItemViewType(row, column)) {
|
||||||
|
case VIEW_TYPE_HEADER:
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = new TextView(mContext);
|
||||||
|
convertView.setBackgroundResource(R.drawable.bg_table_header);
|
||||||
|
}
|
||||||
|
if (row == -1 && column == -1) break;
|
||||||
|
if (row == -1) {
|
||||||
|
// Column header - Criteries
|
||||||
|
((TextView) convertView).setText(mHeaders[column].readableString());
|
||||||
|
((TextView) convertView).setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
|
} else {
|
||||||
|
// Row header - Students
|
||||||
|
((TextView) convertView).setText(mItems[row].getStudent().readableString());
|
||||||
|
((TextView) convertView).setGravity(Gravity.CENTER_VERTICAL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VIEW_TYPE_MARK:
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = new Button(mContext);
|
||||||
|
convertView.setOnClickListener(mMarkClickListener);
|
||||||
|
}
|
||||||
|
final Button btn = (Button) convertView;
|
||||||
|
btn.setText(mItems[row].getMark(column).getMark());
|
||||||
|
|
||||||
|
final int resId = (row % 2 == 0) ?
|
||||||
|
R.drawable.bg_table_item1 : R.drawable.bg_table_item2;
|
||||||
|
convertView.setBackgroundResource(resId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth(int column) {
|
||||||
|
return (column == -1) ? mRowHeaderWidth : mWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(int row) {
|
||||||
|
return (row == -1) ? mColumnHeaderHeight : mHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int row, int column) {
|
||||||
|
if (row == -1 || column == -1) return VIEW_TYPE_HEADER;
|
||||||
|
return VIEW_TYPE_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
230
src/com/university/journal/NavigationDrawerFragment.java
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
package com.university.journal;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.v4.app.ActionBarDrawerToggle;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.view.GravityCompat;
|
||||||
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment used for managing interactions for and presentation of a navigation drawer.
|
||||||
|
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
|
||||||
|
* design guidelines</a> for a complete explanation of the behaviors implemented here.
|
||||||
|
*/
|
||||||
|
public final class NavigationDrawerFragment extends Fragment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remember the position of the selected item.
|
||||||
|
*/
|
||||||
|
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per the design guidelines, you should show the drawer on launch until the user manually
|
||||||
|
* expands it. This shared preference tracks this.
|
||||||
|
*/
|
||||||
|
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to the current callbacks instance (the Activity).
|
||||||
|
*/
|
||||||
|
private NavigationDrawerCallbacks mCallbacks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper component that ties the action bar to the navigation drawer.
|
||||||
|
*/
|
||||||
|
private ActionBarDrawerToggle mDrawerToggle;
|
||||||
|
|
||||||
|
private DrawerLayout mDrawerLayout;
|
||||||
|
private ListView mDrawerListView;
|
||||||
|
private View mFragmentContainerView;
|
||||||
|
|
||||||
|
private int mCurrentSelectedPosition = 0;
|
||||||
|
private boolean mFromSavedInstanceState;
|
||||||
|
private boolean mUserLearnedDrawer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Read in the flag indicating whether or not the user has demonstrated awareness of the
|
||||||
|
// drawer. See PREF_USER_LEARNED_DRAWER for details.
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
|
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
|
||||||
|
mFromSavedInstanceState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select either the default item (0) or the last selected item.
|
||||||
|
selectItem(mCurrentSelectedPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
mDrawerListView = (ListView) inflater.inflate(
|
||||||
|
R.layout.fragment_navigation_drawer, container, false);
|
||||||
|
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
selectItem(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mDrawerListView.setAdapter(new ArrayAdapter<>(
|
||||||
|
getActionBar().getThemedContext(),
|
||||||
|
R.layout.item_nav_drawer,
|
||||||
|
android.R.id.text1,
|
||||||
|
getResources().getStringArray(R.array.nav_sections)));
|
||||||
|
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
|
||||||
|
return mDrawerListView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDrawerOpen() {
|
||||||
|
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users of this fragment must call this method to set up the navigation drawer interactions.
|
||||||
|
*
|
||||||
|
* @param fragmentId The android:id of this fragment in its activity's layout.
|
||||||
|
* @param drawerLayout The DrawerLayout containing this fragment's UI.
|
||||||
|
*/
|
||||||
|
public void setUp(int fragmentId, DrawerLayout drawerLayout) {
|
||||||
|
mFragmentContainerView = getActivity().findViewById(fragmentId);
|
||||||
|
mDrawerLayout = drawerLayout;
|
||||||
|
if (mDrawerLayout == null) return;
|
||||||
|
|
||||||
|
// set a custom shadow that overlays the main content when the drawer opens
|
||||||
|
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
|
||||||
|
// set up the drawer's list view with items and click listener
|
||||||
|
|
||||||
|
ActionBar actionBar = getActionBar();
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
actionBar.setHomeButtonEnabled(true);
|
||||||
|
|
||||||
|
// ActionBarDrawerToggle ties together the the proper interactions
|
||||||
|
// between the navigation drawer and the action bar app icon.
|
||||||
|
|
||||||
|
mDrawerToggle = new ActionBarDrawerToggle(
|
||||||
|
getActivity(), /* host Activity */
|
||||||
|
mDrawerLayout, /* DrawerLayout object */
|
||||||
|
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
|
||||||
|
R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
|
||||||
|
R.string.navigation_drawer_close /* "close drawer" description for accessibility */
|
||||||
|
) {
|
||||||
|
@Override
|
||||||
|
public void onDrawerClosed(View drawerView) {
|
||||||
|
super.onDrawerClosed(drawerView);
|
||||||
|
if (!isAdded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawerOpened(View drawerView) {
|
||||||
|
super.onDrawerOpened(drawerView);
|
||||||
|
if (!isAdded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mUserLearnedDrawer) {
|
||||||
|
// The user manually opened the drawer; store this flag to prevent auto-showing
|
||||||
|
// the navigation drawer automatically in the future.
|
||||||
|
mUserLearnedDrawer = true;
|
||||||
|
SharedPreferences sp = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(getActivity());
|
||||||
|
sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
|
||||||
|
// per the navigation drawer design guidelines.
|
||||||
|
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
|
||||||
|
mDrawerLayout.openDrawer(mFragmentContainerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer code dependent on restoration of previous instance state.
|
||||||
|
mDrawerLayout.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mDrawerToggle.syncState();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mDrawerLayout.setDrawerListener(mDrawerToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectItem(int position) {
|
||||||
|
mCurrentSelectedPosition = position;
|
||||||
|
if (mDrawerListView != null) {
|
||||||
|
mDrawerListView.setItemChecked(position, true);
|
||||||
|
}
|
||||||
|
if (mDrawerLayout != null) {
|
||||||
|
mDrawerLayout.closeDrawer(mFragmentContainerView);
|
||||||
|
}
|
||||||
|
if (mCallbacks != null) {
|
||||||
|
mCallbacks.onNavigationDrawerItemSelected(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Activity activity) {
|
||||||
|
super.onAttach(activity);
|
||||||
|
try {
|
||||||
|
mCallbacks = (NavigationDrawerCallbacks) activity;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
super.onDetach();
|
||||||
|
mCallbacks = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
// Forward the new configuration the drawer toggle component.
|
||||||
|
mDrawerToggle.onConfigurationChanged(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionBar getActionBar() {
|
||||||
|
return ((ActionBarActivity) getActivity()).getSupportActionBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callbacks interface that all activities using this fragment must implement.
|
||||||
|
*/
|
||||||
|
public static interface NavigationDrawerCallbacks {
|
||||||
|
/**
|
||||||
|
* Called when an item in the navigation drawer is selected.
|
||||||
|
*/
|
||||||
|
void onNavigationDrawerItemSelected(int position);
|
||||||
|
}
|
||||||
|
}
|
20
src/com/university/journal/accounts/AccountService.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.university.journal.accounts;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
public final class AccountService extends Service {
|
||||||
|
|
||||||
|
private Authenticator mAuthenticator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
mAuthenticator = new Authenticator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return mAuthenticator.getIBinder();
|
||||||
|
}
|
||||||
|
}
|
110
src/com/university/journal/accounts/Authenticator.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package com.university.journal.accounts;
|
||||||
|
|
||||||
|
import static com.university.journal.db.DbContract.AUTHORITY;
|
||||||
|
import com.university.journal.R;
|
||||||
|
import android.accounts.AbstractAccountAuthenticator;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.accounts.NetworkErrorException;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public final class Authenticator extends AbstractAccountAuthenticator {
|
||||||
|
|
||||||
|
private static final long SYNC_PERIOD = 24 * 60 * 60;
|
||||||
|
|
||||||
|
public static final String AUTH_TOKEN_TYPE = "FULL";
|
||||||
|
public static final String ACCOUNT_TYPE = "com.university.journal";
|
||||||
|
|
||||||
|
public static void addAccount(String login, AccountManager accountManager) {
|
||||||
|
final Account account = new Account(login, ACCOUNT_TYPE);
|
||||||
|
|
||||||
|
accountManager.addAccountExplicitly(account, "password", null);
|
||||||
|
accountManager.setAuthToken(account, AUTH_TOKEN_TYPE, "token");
|
||||||
|
|
||||||
|
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
|
||||||
|
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
|
||||||
|
ContentResolver.addPeriodicSync(account, AUTHORITY, new Bundle(), SYNC_PERIOD);
|
||||||
|
// Force sync
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||||
|
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||||
|
ContentResolver.requestSync(account, AUTHORITY, extras);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
public Authenticator(Context context) {
|
||||||
|
super(context);
|
||||||
|
this.mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
AccountManager accountManager = AccountManager.get(mContext);
|
||||||
|
Account[] accountsByType = accountManager.getAccountsByType(accountType);
|
||||||
|
final Bundle bundle = new Bundle();
|
||||||
|
// Allow only one account
|
||||||
|
if (accountsByType.length > 0) {
|
||||||
|
bundle.putString(AccountManager.KEY_ERROR_MESSAGE, mContext.getString(R.string.one_account_allowed));
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
final Bundle bundle = new Bundle();
|
||||||
|
if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
|
||||||
|
bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "Invalid authTokenType");
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
final AccountManager am = AccountManager.get(mContext);
|
||||||
|
final String password = am.getPassword(account);
|
||||||
|
if (password != null) {
|
||||||
|
bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
|
||||||
|
bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
|
||||||
|
bundle.putString(AccountManager.KEY_AUTHTOKEN, account.name + "/" + password);
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthTokenLabel(String authTokenType) {
|
||||||
|
if (authTokenType.equals(AUTH_TOKEN_TYPE)) {
|
||||||
|
return mContext.getString(R.string.app_name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
83
src/com/university/journal/db/ContentManager.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package com.university.journal.db;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import com.university.journal.db.DbContract.Criteries;
|
||||||
|
import com.university.journal.db.DbContract.Marks;
|
||||||
|
import com.university.journal.db.DbContract.Students;
|
||||||
|
import com.university.journal.entity.Criteria;
|
||||||
|
import com.university.journal.entity.Mark;
|
||||||
|
import com.university.journal.entity.Student;
|
||||||
|
|
||||||
|
public final class ContentManager {
|
||||||
|
|
||||||
|
public static synchronized ContentManager with(ContentResolver cr) {
|
||||||
|
return new ContentManager(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ContentResolver mResolver;
|
||||||
|
|
||||||
|
private ContentManager(ContentResolver resolver) {
|
||||||
|
this.mResolver = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Criteria> getCriteries(long subjectId) {
|
||||||
|
final String selection = Criteries.SUBJECT_ID + " = ?";
|
||||||
|
final String[] args = { String.valueOf(subjectId) };
|
||||||
|
Cursor cursor = mResolver.query(
|
||||||
|
Criteries.CONTENT_URI, Criteries.PROJECTION_ALL,
|
||||||
|
selection, args, Criteries.DATE);
|
||||||
|
List<Criteria> criteries = new ArrayList<>();
|
||||||
|
if (cursor != null) {
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
Criteria obj = new Criteria();
|
||||||
|
obj.fromCursor(cursor);
|
||||||
|
criteries.add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return criteries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Student> getStudents(long groupId) {
|
||||||
|
final String selection = Students.GROUP_ID + " = ?";
|
||||||
|
final String[] args = { String.valueOf(groupId) };
|
||||||
|
Cursor cursor = mResolver.query(Students.CONTENT_URI, null,
|
||||||
|
selection, args, Students.LAST_NAME);
|
||||||
|
ArrayList<Student> students = new ArrayList<>();
|
||||||
|
if (cursor != null) {
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
Student obj = new Student();
|
||||||
|
obj.fromCursor(cursor);
|
||||||
|
obj.setId( cursor.getInt(cursor.getColumnIndex(Students._ID)) );
|
||||||
|
students.add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return students;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor getMarksCursor(long studentId) {
|
||||||
|
final String sel = Marks.STUDENT_ID + " = ?";
|
||||||
|
final String[] args = { String.valueOf(studentId) };
|
||||||
|
return mResolver.query(Marks.CONTENT_URI, null, sel, args, Marks.CRITERIA_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertOrUpdate(Mark mark) {
|
||||||
|
final String where = String.format("%s = ? AND %s = ?", Marks.CRITERIA_ID, Marks.STUDENT_ID);
|
||||||
|
final String[] args = {
|
||||||
|
String.valueOf(mark.getCriteriaId()),
|
||||||
|
String.valueOf(mark.getStudentId())
|
||||||
|
};
|
||||||
|
int updateCount = mResolver.update(Marks.CONTENT_URI, mark.getContentValues(), where, args);
|
||||||
|
if (updateCount <= 0) {
|
||||||
|
mResolver.insert(Marks.CONTENT_URI, mark.getContentValues());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
313
src/com/university/journal/db/DbContentProvider.java
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
package com.university.journal.db;
|
||||||
|
|
||||||
|
import static com.university.journal.db.DbContract.*;
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.UriMatcher;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.SQLException;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteQueryBuilder;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
public final class DbContentProvider extends ContentProvider {
|
||||||
|
|
||||||
|
private static final UriMatcher URI_MATCHER = buildUriMatcher();
|
||||||
|
private static final int STUDENTS_LIST = 10;
|
||||||
|
private static final int STUDENTS_ID = 11;
|
||||||
|
private static final int SUBJECTS_LIST = 20;
|
||||||
|
private static final int SUBJECTS_ID = 21;
|
||||||
|
private static final int GROUPS_LIST = 30;
|
||||||
|
private static final int GROUPS_ID = 31;
|
||||||
|
private static final int CRITERIES_LIST = 40;
|
||||||
|
private static final int CRITERIES_ID = 41;
|
||||||
|
private static final int MARKS_LIST = 50;
|
||||||
|
private static final int MARKS_ID = 51;
|
||||||
|
private static final int GROUP_BY_STUDENT = 91;
|
||||||
|
|
||||||
|
private DbOpenHelper mDbHelper;
|
||||||
|
|
||||||
|
private static final UriMatcher buildUriMatcher() {
|
||||||
|
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Students.TABLE_NAME, STUDENTS_LIST);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Students.TABLE_NAME + "/#", STUDENTS_ID);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Subjects.TABLE_NAME, SUBJECTS_LIST);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Subjects.TABLE_NAME + "/#", SUBJECTS_ID);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Groups.TABLE_NAME, GROUPS_LIST);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Groups.TABLE_NAME + "/#", GROUPS_ID);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Criteries.TABLE_NAME, CRITERIES_LIST);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Criteries.TABLE_NAME + "/#", CRITERIES_ID);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Marks.TABLE_NAME, MARKS_LIST);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, Marks.TABLE_NAME + "/#", MARKS_ID);
|
||||||
|
matcher.addURI(DbContract.AUTHORITY, "group_by_student", GROUP_BY_STUDENT);
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
mDbHelper = new DbOpenHelper(getContext());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri) {
|
||||||
|
final int match = URI_MATCHER.match(uri);
|
||||||
|
switch (match) {
|
||||||
|
case STUDENTS_LIST:
|
||||||
|
return Students.CONTENT_TYPE;
|
||||||
|
case STUDENTS_ID:
|
||||||
|
return Students.CONTENT_ITEM_TYPE;
|
||||||
|
case SUBJECTS_LIST:
|
||||||
|
return Subjects.CONTENT_TYPE;
|
||||||
|
case SUBJECTS_ID:
|
||||||
|
return Subjects.CONTENT_ITEM_TYPE;
|
||||||
|
case GROUPS_LIST:
|
||||||
|
return Groups.CONTENT_TYPE;
|
||||||
|
case GROUPS_ID:
|
||||||
|
return Groups.CONTENT_ITEM_TYPE;
|
||||||
|
case CRITERIES_LIST:
|
||||||
|
return Criteries.CONTENT_TYPE;
|
||||||
|
case CRITERIES_ID:
|
||||||
|
return Criteries.CONTENT_ITEM_TYPE;
|
||||||
|
case MARKS_LIST:
|
||||||
|
return Marks.CONTENT_TYPE;
|
||||||
|
case MARKS_ID:
|
||||||
|
return Marks.CONTENT_ITEM_TYPE;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("URI " + uri + " is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
|
SQLiteDatabase db = mDbHelper.getReadableDatabase();
|
||||||
|
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
|
||||||
|
final int match = URI_MATCHER.match(uri);
|
||||||
|
switch (match) {
|
||||||
|
case STUDENTS_LIST:
|
||||||
|
builder.setTables(Students.TABLE_NAME);
|
||||||
|
break;
|
||||||
|
case STUDENTS_ID:
|
||||||
|
builder.setTables(Students.TABLE_NAME);
|
||||||
|
builder.appendWhere(Students._ID + " = " + uri.getLastPathSegment());
|
||||||
|
break;
|
||||||
|
case SUBJECTS_LIST:
|
||||||
|
builder.setTables(Subjects.TABLE_NAME);
|
||||||
|
break;
|
||||||
|
case SUBJECTS_ID:
|
||||||
|
builder.setTables(Subjects.TABLE_NAME);
|
||||||
|
builder.appendWhere(Subjects._ID + " = " + uri.getLastPathSegment());
|
||||||
|
break;
|
||||||
|
case GROUPS_LIST:
|
||||||
|
builder.setTables(Groups.TABLE_NAME);
|
||||||
|
break;
|
||||||
|
case GROUPS_ID:
|
||||||
|
builder.setTables(Groups.TABLE_NAME);
|
||||||
|
builder.appendWhere(Groups._ID + " = " + uri.getLastPathSegment());
|
||||||
|
break;
|
||||||
|
case CRITERIES_LIST:
|
||||||
|
builder.setTables(Criteries.TABLE_NAME);
|
||||||
|
break;
|
||||||
|
case CRITERIES_ID:
|
||||||
|
builder.setTables(Criteries.TABLE_NAME);
|
||||||
|
builder.appendWhere(Criteries._ID + " = " + uri.getLastPathSegment());
|
||||||
|
break;
|
||||||
|
case MARKS_LIST:
|
||||||
|
builder.setTables(Marks.TABLE_NAME);
|
||||||
|
break;
|
||||||
|
case MARKS_ID:
|
||||||
|
builder.setTables(Marks.TABLE_NAME);
|
||||||
|
builder.appendWhere(Marks._ID + " = " + uri.getLastPathSegment());
|
||||||
|
break;
|
||||||
|
case GROUP_BY_STUDENT:
|
||||||
|
builder.setTables(String.format(
|
||||||
|
"%s INNER JOIN %s ON %s.%s = %s.%s",
|
||||||
|
Students.TABLE_NAME, Groups.TABLE_NAME,
|
||||||
|
Students.TABLE_NAME, Students.GROUP_ID,
|
||||||
|
Groups.TABLE_NAME, Groups._ID));
|
||||||
|
projection = new String[] {
|
||||||
|
Groups.NAME, Students.GROUP_ID
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("URI " + uri + " is not supported.");
|
||||||
|
}
|
||||||
|
return builder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
final int match = URI_MATCHER.match(uri);
|
||||||
|
switch(match){
|
||||||
|
case STUDENTS_LIST:
|
||||||
|
long id = db.insert(Students.TABLE_NAME, null, values);
|
||||||
|
return getInsertedUri(id, uri);
|
||||||
|
case SUBJECTS_LIST:
|
||||||
|
id = db.insert(Subjects.TABLE_NAME, null, values);
|
||||||
|
return getInsertedUri(id, uri);
|
||||||
|
case GROUPS_LIST:
|
||||||
|
id = db.insert(Groups.TABLE_NAME, null, values);
|
||||||
|
return getInsertedUri(id, uri);
|
||||||
|
case CRITERIES_LIST:
|
||||||
|
id = db.insert(Criteries.TABLE_NAME, null, values);
|
||||||
|
return getInsertedUri(id, uri);
|
||||||
|
case MARKS_LIST:
|
||||||
|
id = db.insert(Marks.TABLE_NAME, null, values);
|
||||||
|
return getInsertedUri(id, uri);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("URI " + uri + " is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Uri getInsertedUri(long id, Uri uri) {
|
||||||
|
if (id <= 0) throw new SQLException("Problem while inserting into uri: " + uri);
|
||||||
|
Uri itemUri = ContentUris.withAppendedId(uri, id);
|
||||||
|
getContext().getContentResolver().notifyChange(itemUri, null);
|
||||||
|
return itemUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
int updateCount = 0;
|
||||||
|
final int match = URI_MATCHER.match(uri);
|
||||||
|
switch (match) {
|
||||||
|
case STUDENTS_LIST:
|
||||||
|
updateCount = db.update(Students.TABLE_NAME, values, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case STUDENTS_ID:
|
||||||
|
String where = Students._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
updateCount = db.update(Students.TABLE_NAME, values, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBJECTS_LIST:
|
||||||
|
updateCount = db.update(Subjects.TABLE_NAME, values, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case SUBJECTS_ID:
|
||||||
|
where = Subjects._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
updateCount = db.update(Subjects.TABLE_NAME, values, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GROUPS_LIST:
|
||||||
|
updateCount = db.update(Groups.TABLE_NAME, values, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case GROUPS_ID:
|
||||||
|
where = Groups._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
updateCount = db.update(Groups.TABLE_NAME, values, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRITERIES_LIST:
|
||||||
|
updateCount = db.update(Criteries.TABLE_NAME, values, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case CRITERIES_ID:
|
||||||
|
where = Criteries._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
updateCount = db.update(Criteries.TABLE_NAME, values, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MARKS_LIST:
|
||||||
|
updateCount = db.update(Marks.TABLE_NAME, values, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case MARKS_ID:
|
||||||
|
where = Marks._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
updateCount = db.update(Marks.TABLE_NAME, values, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("URI " + uri + " is not supported.");
|
||||||
|
}
|
||||||
|
if (updateCount > 0) {
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
}
|
||||||
|
return updateCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
int deleteCount = 0;
|
||||||
|
final int match = URI_MATCHER.match(uri);
|
||||||
|
switch (match) {
|
||||||
|
case STUDENTS_LIST:
|
||||||
|
deleteCount = db.delete(Students.TABLE_NAME, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case STUDENTS_ID:
|
||||||
|
String where = Students._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
deleteCount = db.delete(Students.TABLE_NAME, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBJECTS_LIST:
|
||||||
|
deleteCount = db.delete(Subjects.TABLE_NAME, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case SUBJECTS_ID:
|
||||||
|
where = Subjects._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
deleteCount = db.delete(Subjects.TABLE_NAME, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GROUPS_LIST:
|
||||||
|
deleteCount = db.delete(Groups.TABLE_NAME, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case GROUPS_ID:
|
||||||
|
where = Groups._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
deleteCount = db.delete(Groups.TABLE_NAME, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CRITERIES_LIST:
|
||||||
|
deleteCount = db.delete(Criteries.TABLE_NAME, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case CRITERIES_ID:
|
||||||
|
where = Criteries._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
deleteCount = db.delete(Criteries.TABLE_NAME, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MARKS_LIST:
|
||||||
|
deleteCount = db.delete(Marks.TABLE_NAME, selection, selectionArgs);
|
||||||
|
break;
|
||||||
|
case MARKS_ID:
|
||||||
|
where = Marks._ID + " = " + uri.getLastPathSegment();
|
||||||
|
if (!TextUtils.isEmpty(selection)) {
|
||||||
|
where += " AND " + selection;
|
||||||
|
}
|
||||||
|
deleteCount = db.delete(Marks.TABLE_NAME, where, selectionArgs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("URI " + uri + " is not supported.");
|
||||||
|
}
|
||||||
|
if (deleteCount > 0) {
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
}
|
||||||
|
return deleteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
103
src/com/university/journal/db/DbContract.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package com.university.journal.db;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
|
public final class DbContract {
|
||||||
|
|
||||||
|
public static final String AUTHORITY = "com.university.journal.dbprovider";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||||
|
|
||||||
|
public static final class Students implements BaseColumns {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "students";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.withAppendedPath(DbContract.CONTENT_URI, TABLE_NAME);
|
||||||
|
|
||||||
|
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String LAST_NAME = "lastname";
|
||||||
|
|
||||||
|
public static final String FIRST_NAME = "firstname";
|
||||||
|
|
||||||
|
public static final String MIDDLE_NAME = "midname";
|
||||||
|
|
||||||
|
public static final String GROUP_ID = "group_id";
|
||||||
|
|
||||||
|
public static final String[] PROJECTION_ALL = {_ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, GROUP_ID};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Subjects implements BaseColumns {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "subjects";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.withAppendedPath(DbContract.CONTENT_URI, TABLE_NAME);
|
||||||
|
|
||||||
|
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String NAME = "_name";
|
||||||
|
|
||||||
|
public static final String SHORT_NAME = "shortname";
|
||||||
|
|
||||||
|
public static final String[] PROJECTION_ALL = {_ID, NAME, SHORT_NAME};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Groups implements BaseColumns {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "_groups";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.withAppendedPath(DbContract.CONTENT_URI, TABLE_NAME);
|
||||||
|
|
||||||
|
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String NAME = "_name";
|
||||||
|
|
||||||
|
public static final String[] PROJECTION_ALL = {_ID, NAME};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Criteries implements BaseColumns {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "criteries";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.withAppendedPath(DbContract.CONTENT_URI, TABLE_NAME);
|
||||||
|
|
||||||
|
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String SUBJECT_ID = "subject_id";
|
||||||
|
|
||||||
|
public static final String NAME = "_name";
|
||||||
|
|
||||||
|
public static final String DATE = "_date";
|
||||||
|
|
||||||
|
public static final String[] PROJECTION_ALL = {_ID, SUBJECT_ID, NAME, DATE};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Marks implements BaseColumns {
|
||||||
|
|
||||||
|
public static final String TABLE_NAME = "marks";
|
||||||
|
|
||||||
|
public static final Uri CONTENT_URI = Uri.withAppendedPath(DbContract.CONTENT_URI, TABLE_NAME);
|
||||||
|
|
||||||
|
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/vnd.com.university.journal." + TABLE_NAME;
|
||||||
|
|
||||||
|
public static final String STUDENT_ID = "student_id";
|
||||||
|
|
||||||
|
public static final String CRITERIA_ID = "criteria_id";
|
||||||
|
|
||||||
|
public static final String MARK = "mark";
|
||||||
|
|
||||||
|
public static final String[] PROJECTION_ALL = {_ID, STUDENT_ID, CRITERIA_ID, MARK};
|
||||||
|
}
|
||||||
|
}
|
42
src/com/university/journal/db/DbOpenHelper.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.university.journal.db;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
public final class DbOpenHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
private static final String NAME = DbSchema.DB_NAME;
|
||||||
|
private static final int VERSION = 1;
|
||||||
|
|
||||||
|
public DbOpenHelper(Context context) {
|
||||||
|
super(context, NAME, null, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(DbSchema.DDL_CREATE_TBL_STUDENTS);
|
||||||
|
db.execSQL(DbSchema.DDL_CREATE_TBL_SUBJECTS);
|
||||||
|
db.execSQL(DbSchema.DDL_CREATE_TBL_GROUPS);
|
||||||
|
db.execSQL(DbSchema.DDL_CREATE_TBL_CRITERIES);
|
||||||
|
db.execSQL(DbSchema.DDL_CREATE_TBL_MARKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
db.execSQL(DbSchema.DDL_DROP_TBL_STUDENTS);
|
||||||
|
db.execSQL(DbSchema.DDL_DROP_TBL_SUBJECTS);
|
||||||
|
db.execSQL(DbSchema.DDL_DROP_TBL_GROUPS);
|
||||||
|
db.execSQL(DbSchema.DDL_DROP_TBL_CRITERIES);
|
||||||
|
db.execSQL(DbSchema.DDL_DROP_TBL_MARKS);
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(SQLiteDatabase db) {
|
||||||
|
super.onOpen(db);
|
||||||
|
if (!db.isReadOnly()) {
|
||||||
|
db.execSQL("PRAGMA foreign_keys=ON;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
src/com/university/journal/db/DbSchema.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package com.university.journal.db;
|
||||||
|
|
||||||
|
import static com.university.journal.db.DbContract.*;
|
||||||
|
|
||||||
|
public interface DbSchema {
|
||||||
|
|
||||||
|
String DB_NAME = "journal.db";
|
||||||
|
|
||||||
|
String DDL_CREATE_TBL_STUDENTS =
|
||||||
|
"CREATE TABLE " + Students.TABLE_NAME + " (" +
|
||||||
|
Students._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
|
||||||
|
Students.LAST_NAME + " TEXT NOT NULL, \n" +
|
||||||
|
Students.FIRST_NAME + " TEXT NOT NULL, \n" +
|
||||||
|
Students.MIDDLE_NAME + " TEXT NOT NULL, \n" +
|
||||||
|
Students.GROUP_ID + " INTEGER NOT NULL, \n" +
|
||||||
|
"FOREIGN KEY("+ Students.GROUP_ID + ") REFERENCES " + Groups.TABLE_NAME + "(" + Groups._ID + ") ON DELETE CASCADE \n" +
|
||||||
|
")";
|
||||||
|
|
||||||
|
String DDL_CREATE_TBL_SUBJECTS =
|
||||||
|
"CREATE TABLE " + Subjects.TABLE_NAME + " (" +
|
||||||
|
Subjects._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
|
||||||
|
Subjects.NAME + " TEXT NOT NULL, \n" +
|
||||||
|
Subjects.SHORT_NAME + " TEXT NOT NULL \n" +
|
||||||
|
")";
|
||||||
|
|
||||||
|
String DDL_CREATE_TBL_GROUPS =
|
||||||
|
"CREATE TABLE " + Groups.TABLE_NAME + " (" +
|
||||||
|
Groups._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
|
||||||
|
Groups.NAME + " TEXT NOT NULL \n" +
|
||||||
|
")";
|
||||||
|
|
||||||
|
String DDL_CREATE_TBL_CRITERIES =
|
||||||
|
"CREATE TABLE " + Criteries.TABLE_NAME + " (" +
|
||||||
|
Criteries._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
|
||||||
|
Criteries.SUBJECT_ID + " INTEGER NOT NULL, \n" +
|
||||||
|
Criteries.NAME + " TEXT NOT NULL, \n" +
|
||||||
|
Criteries.DATE + " TEXT NOT NULL, \n" +
|
||||||
|
"FOREIGN KEY("+ Criteries.SUBJECT_ID + ") REFERENCES " + Subjects.TABLE_NAME + "(" + Subjects._ID + ") ON DELETE CASCADE \n" +
|
||||||
|
")";
|
||||||
|
|
||||||
|
String DDL_CREATE_TBL_MARKS =
|
||||||
|
"CREATE TABLE " + Marks.TABLE_NAME + " (" +
|
||||||
|
Marks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, \n" +
|
||||||
|
Marks.STUDENT_ID + " INTEGER NOT NULL, \n" +
|
||||||
|
Marks.CRITERIA_ID + " INTEGER NOT NULL, \n" +
|
||||||
|
Marks.MARK + " TEXT NOT NULL, \n" +
|
||||||
|
"FOREIGN KEY("+ Marks.STUDENT_ID + ") REFERENCES " + Students.TABLE_NAME + "(" + Students._ID + ") ON DELETE CASCADE, \n" +
|
||||||
|
"FOREIGN KEY("+ Marks.CRITERIA_ID + ") REFERENCES " + Criteries.TABLE_NAME + "(" + Criteries._ID + ") ON DELETE CASCADE \n" +
|
||||||
|
")";
|
||||||
|
|
||||||
|
String DDL_DROP_TBL_STUDENTS = "DROP TABLE IF EXISTS " + Students.TABLE_NAME;
|
||||||
|
String DDL_DROP_TBL_SUBJECTS = "DROP TABLE IF EXISTS " + Subjects.TABLE_NAME;
|
||||||
|
String DDL_DROP_TBL_GROUPS = "DROP TABLE IF EXISTS " + Groups.TABLE_NAME;
|
||||||
|
String DDL_DROP_TBL_CRITERIES = "DROP TABLE IF EXISTS " + Criteries.TABLE_NAME;
|
||||||
|
String DDL_DROP_TBL_MARKS = "DROP TABLE IF EXISTS " + Marks.TABLE_NAME;
|
||||||
|
}
|
77
src/com/university/journal/entity/Criteria.java
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import com.university.journal.db.DbContract.Criteries;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
|
public final class Criteria implements DatabaseSerializer {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private int subjectId;
|
||||||
|
private String name;
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
public Criteria() { }
|
||||||
|
|
||||||
|
public Criteria(String name, String date, int subjectId) {
|
||||||
|
this.name = name;
|
||||||
|
this.date = date;
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSubjectId() {
|
||||||
|
return subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubjectId(int subjectId) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(String date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromCursor(Cursor cursor) {
|
||||||
|
id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||||
|
subjectId = cursor.getInt(cursor.getColumnIndex(Criteries.SUBJECT_ID));
|
||||||
|
name = cursor.getString(cursor.getColumnIndex(Criteries.NAME));
|
||||||
|
date = cursor.getString(cursor.getColumnIndex(Criteries.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getContentValues() {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(Criteries.NAME, name);
|
||||||
|
cv.put(Criteries.DATE, date);
|
||||||
|
cv.put(Criteries.SUBJECT_ID, subjectId);
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readableString() {
|
||||||
|
return name + "\n" + date;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
11
src/com/university/journal/entity/DatabaseSerializer.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
public interface DatabaseSerializer {
|
||||||
|
|
||||||
|
void fromCursor(Cursor cursor);
|
||||||
|
|
||||||
|
ContentValues getContentValues();
|
||||||
|
}
|
47
src/com/university/journal/entity/Group.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import com.university.journal.db.DbContract.Groups;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
|
public final class Group implements DatabaseSerializer {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Group() { }
|
||||||
|
|
||||||
|
public Group(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromCursor(Cursor cursor) {
|
||||||
|
id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||||
|
name = cursor.getString(cursor.getColumnIndex(Groups.NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getContentValues() {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(Groups.NAME, name);
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
}
|
70
src/com/university/journal/entity/Mark.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import com.university.journal.db.DbContract.Marks;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
|
public final class Mark implements DatabaseSerializer {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private int studentId, criteriaId;
|
||||||
|
private String mark;
|
||||||
|
|
||||||
|
public Mark() { }
|
||||||
|
|
||||||
|
public Mark(int studentId, int criteriaId, String mark) {
|
||||||
|
this.studentId = studentId;
|
||||||
|
this.criteriaId = criteriaId;
|
||||||
|
this.mark = mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStudentId() {
|
||||||
|
return studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudentId(int studentId) {
|
||||||
|
this.studentId = studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCriteriaId() {
|
||||||
|
return criteriaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCriteriaId(int criteriaId) {
|
||||||
|
this.criteriaId = criteriaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMark() {
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMark(String mark) {
|
||||||
|
this.mark = mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromCursor(Cursor cursor) {
|
||||||
|
id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||||
|
studentId = cursor.getInt(cursor.getColumnIndex(Marks.STUDENT_ID));
|
||||||
|
criteriaId = cursor.getInt(cursor.getColumnIndex(Marks.CRITERIA_ID));
|
||||||
|
mark = cursor.getString(cursor.getColumnIndex(Marks.MARK));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getContentValues() {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(Marks.STUDENT_ID, studentId);
|
||||||
|
cv.put(Marks.CRITERIA_ID, criteriaId);
|
||||||
|
cv.put(Marks.MARK, mark);
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
}
|
24
src/com/university/journal/entity/MarksTableItem.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
public final class MarksTableItem {
|
||||||
|
|
||||||
|
private Student student;
|
||||||
|
private Mark[] marks;
|
||||||
|
|
||||||
|
public MarksTableItem(Student student, Mark[] marks) {
|
||||||
|
this.student = student;
|
||||||
|
this.marks = marks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Student getStudent() {
|
||||||
|
return student;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mark getMark(int index) {
|
||||||
|
return marks[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMark(int index, Mark mark) {
|
||||||
|
marks[index] = mark;
|
||||||
|
}
|
||||||
|
}
|
83
src/com/university/journal/entity/Student.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import com.university.journal.db.DbContract.Students;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
public final class Student implements DatabaseSerializer {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private String firstName, lastName, middleName;
|
||||||
|
private int groupId;
|
||||||
|
|
||||||
|
public Student() { }
|
||||||
|
|
||||||
|
public Student(String firstName, String lastName, String middleName, int groupId) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.middleName = middleName;
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMiddleName() {
|
||||||
|
return middleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMiddleName(String middleName) {
|
||||||
|
this.middleName = middleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(int groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromCursor(Cursor cursor) {
|
||||||
|
firstName = cursor.getString(cursor.getColumnIndex(Students.FIRST_NAME));
|
||||||
|
lastName = cursor.getString(cursor.getColumnIndex(Students.LAST_NAME));
|
||||||
|
middleName = cursor.getString(cursor.getColumnIndex(Students.MIDDLE_NAME));
|
||||||
|
groupId = cursor.getInt(cursor.getColumnIndex(Students.GROUP_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getContentValues() {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(Students.FIRST_NAME, firstName);
|
||||||
|
cv.put(Students.LAST_NAME, lastName);
|
||||||
|
cv.put(Students.MIDDLE_NAME, middleName);
|
||||||
|
cv.put(Students.GROUP_ID, groupId);
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readableString() {
|
||||||
|
return String.format("%s %c.%c.", lastName, firstName.charAt(0), middleName.charAt(0));
|
||||||
|
}
|
||||||
|
}
|
58
src/com/university/journal/entity/Subject.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package com.university.journal.entity;
|
||||||
|
|
||||||
|
import static com.university.journal.db.DbContract.Subjects;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
|
||||||
|
public final class Subject implements DatabaseSerializer {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private String name, shortName;
|
||||||
|
|
||||||
|
public Subject() {}
|
||||||
|
|
||||||
|
public Subject(String name, String shortName) {
|
||||||
|
this.name = name;
|
||||||
|
this.shortName = shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortName() {
|
||||||
|
return shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortName(String shortName) {
|
||||||
|
this.shortName = shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromCursor(Cursor cursor) {
|
||||||
|
id = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
|
||||||
|
name = cursor.getString(cursor.getColumnIndex(Subjects.NAME));
|
||||||
|
shortName = cursor.getString(cursor.getColumnIndex(Subjects.SHORT_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getContentValues() {
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(Subjects.NAME, name);
|
||||||
|
cv.put(Subjects.SHORT_NAME, shortName);
|
||||||
|
return cv;
|
||||||
|
}
|
||||||
|
}
|
62
src/com/university/journal/fragments/CriteriaFragment.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.content.CursorLoader;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import com.university.journal.db.DbContract.Criteries;
|
||||||
|
import com.university.journal.entity.Criteria;
|
||||||
|
|
||||||
|
public final class CriteriaFragment extends DbTableFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int loaderNumber() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getUIBindFrom() {
|
||||||
|
return new String[] { Criteries.NAME, Criteries.DATE };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int[] getUIBindTo() {
|
||||||
|
return new int[] { android.R.id.text1, android.R.id.text2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getUIBindLayoutResource() {
|
||||||
|
return android.R.layout.simple_list_item_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogFragment getAddDataDialogFragment() {
|
||||||
|
return NewCriteriaDialogFragment.newInstance(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onItemDelete(long id) {
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.delete(ContentUris.withAppendedId(Criteries.CONTENT_URI, id), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
|
||||||
|
return new CursorLoader(getActivity(),
|
||||||
|
Criteries.CONTENT_URI, Criteries.PROJECTION_ALL,
|
||||||
|
null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NewCriteriaDialogFragment.AddListener mListener = new NewCriteriaDialogFragment.AddListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirm(String name, String date, long subjectId) {
|
||||||
|
Criteria obj = new Criteria(name, date, (int) subjectId);
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.insert(Criteries.CONTENT_URI, obj.getContentValues());
|
||||||
|
getActivity().getSupportLoaderManager().getLoader(loaderNumber()).forceLoad();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
146
src/com/university/journal/fragments/DbTableFragment.java
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.app.ListFragment;
|
||||||
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter;
|
||||||
|
import android.support.v7.app.ActionBarActivity;
|
||||||
|
import android.support.v7.view.ActionMode;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import com.university.journal.R;
|
||||||
|
|
||||||
|
public abstract class DbTableFragment extends ListFragment implements LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
|
private long mSelectedId;
|
||||||
|
private SimpleCursorAdapter mAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
|
final String[] from = getUIBindFrom();
|
||||||
|
final int[] to = getUIBindTo();
|
||||||
|
|
||||||
|
mAdapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
getUIBindLayoutResource(), null,
|
||||||
|
from, to,
|
||||||
|
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
|
||||||
|
postInitAdapter(mAdapter);
|
||||||
|
setListAdapter(mAdapter);
|
||||||
|
setEmptyText(getString(R.string.no_data));
|
||||||
|
|
||||||
|
getListView().setOnItemLongClickListener(mItemLongClickListener);
|
||||||
|
getActivity().getSupportLoaderManager().initLoader(loaderNumber(), null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String[] getUIBindFrom();
|
||||||
|
|
||||||
|
protected int[] getUIBindTo() {
|
||||||
|
return new int[] { android.R.id.text1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getUIBindLayoutResource() {
|
||||||
|
return android.R.layout.simple_list_item_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void postInitAdapter(SimpleCursorAdapter adapter) { }
|
||||||
|
|
||||||
|
protected abstract int loaderNumber();
|
||||||
|
|
||||||
|
protected abstract DialogFragment getAddDataDialogFragment();
|
||||||
|
|
||||||
|
protected abstract void onItemDelete(long id);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.add_item, menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_add:
|
||||||
|
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
|
||||||
|
getAddDataDialogFragment().show(ft, "dialog");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.swapCursor(cursor);
|
||||||
|
}
|
||||||
|
if (isResumed()) {
|
||||||
|
setListShown(true);
|
||||||
|
} else {
|
||||||
|
setListShownNoAnimation(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(Loader<Cursor> loader) {
|
||||||
|
if (mAdapter != null) {
|
||||||
|
mAdapter.swapCursor(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AdapterView.OnItemLongClickListener mItemLongClickListener =
|
||||||
|
new AdapterView.OnItemLongClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
mSelectedId = id;
|
||||||
|
((ActionBarActivity) getActivity()).startSupportActionMode(mActionCallback);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private final ActionMode.Callback mActionCallback = new ActionMode.Callback() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
|
||||||
|
// Similar to menu handling in Activity.onOptionsItemSelected()
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case R.id.action_delete:
|
||||||
|
// Some remove functionality
|
||||||
|
onItemDelete(mSelectedId);
|
||||||
|
getActivity().getSupportLoaderManager().getLoader(loaderNumber()).forceLoad();
|
||||||
|
actionMode.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||||
|
// Inflate our menu from a resource file
|
||||||
|
actionMode.getMenuInflater().inflate(R.menu.item_context, menu);
|
||||||
|
|
||||||
|
// Return true so that the action mode is shown
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyActionMode(ActionMode actionMode) {
|
||||||
|
// Allows you to be notified when the action mode is dismissed
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
51
src/com/university/journal/fragments/GroupFragment.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.content.CursorLoader;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import com.university.journal.db.DbContract.Groups;
|
||||||
|
import com.university.journal.entity.Group;
|
||||||
|
|
||||||
|
public final class GroupFragment extends DbTableFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int loaderNumber() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getUIBindFrom() {
|
||||||
|
return new String[] { Groups.NAME };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogFragment getAddDataDialogFragment() {
|
||||||
|
return NewGroupDialogFragment.newInstance(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onItemDelete(long id) {
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.delete(ContentUris.withAppendedId(Groups.CONTENT_URI, id), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
|
||||||
|
return new CursorLoader(getActivity(),
|
||||||
|
Groups.CONTENT_URI, Groups.PROJECTION_ALL,
|
||||||
|
null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NewGroupDialogFragment.AddListener mListener = new NewGroupDialogFragment.AddListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirm(String name) {
|
||||||
|
Group obj = new Group(name);
|
||||||
|
getActivity().getContentResolver().insert(Groups.CONTENT_URI, obj.getContentValues());
|
||||||
|
getActivity().getSupportLoaderManager().getLoader(loaderNumber()).forceLoad();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
244
src/com/university/journal/fragments/MainFragment.java
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import com.inqbarna.tablefixheaders.TableFixHeaders;
|
||||||
|
import com.inqbarna.tablefixheaders.adapters.TableAdapter;
|
||||||
|
import com.university.journal.EmptyTableAdapter;
|
||||||
|
import com.university.journal.MarksTableAdapter;
|
||||||
|
import com.university.journal.R;
|
||||||
|
import com.university.journal.db.ContentManager;
|
||||||
|
import com.university.journal.db.DbContract.Groups;
|
||||||
|
import com.university.journal.db.DbContract.Subjects;
|
||||||
|
import com.university.journal.entity.Criteria;
|
||||||
|
import com.university.journal.entity.Mark;
|
||||||
|
import com.university.journal.entity.MarksTableItem;
|
||||||
|
import com.university.journal.entity.Student;
|
||||||
|
|
||||||
|
public final class MainFragment extends Fragment {
|
||||||
|
|
||||||
|
private static TableAdapter sEmptyAdapter;
|
||||||
|
|
||||||
|
private Spinner mSubjectSpinner, mGroupSpinner;
|
||||||
|
private TableFixHeaders mTable;
|
||||||
|
private MarksTableAdapter mAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_main, container, false);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
|
mSubjectSpinner = (Spinner) view.findViewById(R.id.subjectSpinner);
|
||||||
|
mGroupSpinner = (Spinner) view.findViewById(R.id.groupSpinner);
|
||||||
|
mTable = (TableFixHeaders) view.findViewById(R.id.table);
|
||||||
|
|
||||||
|
Cursor cur = getActivity().getContentResolver()
|
||||||
|
.query(Subjects.CONTENT_URI, Subjects.PROJECTION_ALL, null, null, null);
|
||||||
|
String[] from = new String[] { Subjects.NAME };
|
||||||
|
int[] to = new int[] { android.R.id.text1 };
|
||||||
|
SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
android.R.layout.simple_spinner_item, cur,
|
||||||
|
from, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
mSubjectSpinner.setAdapter(adapter);
|
||||||
|
mSubjectSpinner.setOnItemSelectedListener(mSpinnerListener);
|
||||||
|
|
||||||
|
cur = getActivity().getContentResolver()
|
||||||
|
.query(Groups.CONTENT_URI, Groups.PROJECTION_ALL, null, null, null);
|
||||||
|
from = new String[] { Groups.NAME };
|
||||||
|
to = new int[] { android.R.id.text1 };
|
||||||
|
adapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
android.R.layout.simple_spinner_item, cur,
|
||||||
|
from, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
mGroupSpinner.setAdapter(adapter);
|
||||||
|
mGroupSpinner.setOnItemSelectedListener(mSpinnerListener);
|
||||||
|
|
||||||
|
sEmptyAdapter = new EmptyTableAdapter(getActivity());
|
||||||
|
mTable.setAdapter(sEmptyAdapter);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.main, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_export:
|
||||||
|
export();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void export() {
|
||||||
|
if (mAdapter == null) return;
|
||||||
|
|
||||||
|
final String SEP = ",", NEWLINE = "\r\n";
|
||||||
|
StringBuilder csv = new StringBuilder();
|
||||||
|
// For correctly open in Excel
|
||||||
|
csv.append("sep=").append(SEP).append(NEWLINE);
|
||||||
|
// Headers
|
||||||
|
csv.append("Ñòóäåíò").append(SEP);
|
||||||
|
for (int i = 0; i < mAdapter.getColumnCount(); i++) {
|
||||||
|
Criteria cr = mAdapter.getHeader(i);
|
||||||
|
String header = cr.getName() + " / " + cr.getDate();// cr.readableString();
|
||||||
|
csv.append(header).append(SEP);
|
||||||
|
}
|
||||||
|
csv.append(NEWLINE);
|
||||||
|
// Data
|
||||||
|
for (int i = 0; i < mAdapter.getRowCount(); i++) {
|
||||||
|
MarksTableItem item = mAdapter.getItem(i);
|
||||||
|
csv.append(item.getStudent().readableString()).append(SEP);
|
||||||
|
for (int j = 0; j < mAdapter.getColumnCount(); j++) {
|
||||||
|
csv.append(item.getMark(j).getMark()).append(SEP);
|
||||||
|
}
|
||||||
|
csv.append(NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to sdcard
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss");
|
||||||
|
String fullPath = Environment.getExternalStorageDirectory() +
|
||||||
|
File.separator + sdf.format(new Date()) + ".csv";
|
||||||
|
try {
|
||||||
|
Charset charset = Charset.isSupported("CP1251")
|
||||||
|
? Charset.forName("CP1251") : Charset.defaultCharset();
|
||||||
|
FileOutputStream out = new FileOutputStream(new File(fullPath));
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(out, charset);
|
||||||
|
writer.write(csv.toString());
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
Toast.makeText(getActivity(),
|
||||||
|
getString(R.string.saved) + " " + fullPath,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTable() {
|
||||||
|
long subjectId = mSubjectSpinner.getSelectedItemId();
|
||||||
|
if (subjectId == AdapterView.INVALID_ROW_ID) return;
|
||||||
|
|
||||||
|
long groupId = mGroupSpinner.getSelectedItemId();
|
||||||
|
if (groupId == AdapterView.INVALID_ROW_ID) return;
|
||||||
|
|
||||||
|
// Get criteries
|
||||||
|
List<Criteria> criteries = ContentManager
|
||||||
|
.with(getActivity().getContentResolver())
|
||||||
|
.getCriteries(subjectId);
|
||||||
|
if (criteries.isEmpty()) return;
|
||||||
|
final Criteria[] headers = criteries.toArray(new Criteria[0]);
|
||||||
|
|
||||||
|
// Get students
|
||||||
|
List<Student> students = ContentManager
|
||||||
|
.with(getActivity().getContentResolver())
|
||||||
|
.getStudents(groupId);
|
||||||
|
|
||||||
|
// Get marks
|
||||||
|
MarksTableItem[] items = new MarksTableItem[students.size()];
|
||||||
|
for (int i = 0; i < items.length; i++) {
|
||||||
|
final Student student = students.get(i);
|
||||||
|
final int studentId = student.getId();
|
||||||
|
Mark[] marks = new Mark[headers.length];
|
||||||
|
for (int j = 0; j < headers.length; j++) {
|
||||||
|
marks[j] = new Mark(studentId, headers[j].getId(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor cursor = ContentManager
|
||||||
|
.with(getActivity().getContentResolver())
|
||||||
|
.getMarksCursor(studentId);
|
||||||
|
if (cursor != null) {
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
Mark obj = new Mark();
|
||||||
|
obj.fromCursor(cursor);
|
||||||
|
for (int j = 0; j < headers.length; j++) {
|
||||||
|
if (headers[j].getId() == obj.getId()) {
|
||||||
|
marks[j] = obj;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items[i] = new MarksTableItem(student, marks);
|
||||||
|
}
|
||||||
|
mAdapter = new MarksTableAdapter(getActivity(), headers, items);
|
||||||
|
mAdapter.setMarkClickListener(mMarksButtonListener);
|
||||||
|
mTable.setAdapter(mAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final View.OnClickListener mMarksButtonListener =
|
||||||
|
new View.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final int column = (int) v.getTag(R.id.tag_column);
|
||||||
|
final int row = (int) v.getTag(R.id.tag_row);
|
||||||
|
|
||||||
|
final Mark mark = mAdapter.getItem(row).getMark(column);
|
||||||
|
DialogFragment frag = NewMarkDialogFragment.newInstance(mAddListener,
|
||||||
|
mark.getCriteriaId(), mark.getStudentId(), mark.getMark(),
|
||||||
|
row, column);
|
||||||
|
|
||||||
|
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
|
||||||
|
frag.show(ft, "dialog");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private NewMarkDialogFragment.AddListener mAddListener = new NewMarkDialogFragment.AddListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirm(int row, int column, Mark mark) {
|
||||||
|
ContentManager.with(getActivity().getContentResolver())
|
||||||
|
.insertOrUpdate(mark);
|
||||||
|
mAdapter.getItem(row).setMark(column, mark);
|
||||||
|
mAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final AdapterView.OnItemSelectedListener mSpinnerListener =
|
||||||
|
new AdapterView.OnItemSelectedListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
showTable();
|
||||||
|
boolean empty = (mTable.getAdapter() == null) ||
|
||||||
|
(mTable.getAdapter().getColumnCount() == 0);
|
||||||
|
if (empty) {
|
||||||
|
mTable.setAdapter(sEmptyAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
mTable.setAdapter(sEmptyAdapter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import com.university.journal.R;
|
||||||
|
import com.university.journal.db.DbContract.Subjects;
|
||||||
|
|
||||||
|
public final class NewCriteriaDialogFragment extends NewItemDialogFragment {
|
||||||
|
|
||||||
|
public interface AddListener {
|
||||||
|
void onConfirm(String name, String date, long subjectId);
|
||||||
|
};
|
||||||
|
|
||||||
|
private AddListener mListener;
|
||||||
|
private EditText mNameEditText, mDateEditText;
|
||||||
|
private Spinner subjectSpinner;
|
||||||
|
private SimpleCursorAdapter mSpinnerAdapter;
|
||||||
|
|
||||||
|
public static NewCriteriaDialogFragment newInstance(AddListener listener) {
|
||||||
|
NewCriteriaDialogFragment frag = new NewCriteriaDialogFragment();
|
||||||
|
frag.mListener = listener;
|
||||||
|
frag.setCancelable(false);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_add_criteria, null, false);
|
||||||
|
mNameEditText = (EditText) view.findViewById(R.id.name);
|
||||||
|
mDateEditText = (EditText) view.findViewById(R.id.date);
|
||||||
|
subjectSpinner = (Spinner) view.findViewById(R.id.subjectSpinner);
|
||||||
|
|
||||||
|
final Cursor cur = getActivity().getContentResolver()
|
||||||
|
.query(Subjects.CONTENT_URI, Subjects.PROJECTION_ALL, null, null, null);
|
||||||
|
final String[] from = new String[] { Subjects.NAME };
|
||||||
|
final int[] to = new int[] { android.R.id.text1 };
|
||||||
|
mSpinnerAdapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
android.R.layout.simple_spinner_item, cur,
|
||||||
|
from, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
|
||||||
|
mSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
subjectSpinner.setAdapter(mSpinnerAdapter);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean validate() {
|
||||||
|
if (mNameEditText == null) return false;
|
||||||
|
final String name = mNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(name)) return false;
|
||||||
|
|
||||||
|
if (mDateEditText == null) return false;
|
||||||
|
final String date = mDateEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(date)) return false;
|
||||||
|
try {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||||
|
sdf.setLenient(false);
|
||||||
|
sdf.parse(date);
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subjectSpinner.getSelectedItem() == null) return false;
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onConfirm(name, date, subjectSpinner.getSelectedItemId());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import com.university.journal.R;
|
||||||
|
|
||||||
|
public final class NewGroupDialogFragment extends NewItemDialogFragment {
|
||||||
|
|
||||||
|
public interface AddListener {
|
||||||
|
void onConfirm(String name);
|
||||||
|
};
|
||||||
|
|
||||||
|
private AddListener mListener;
|
||||||
|
private EditText mNameEditText;
|
||||||
|
|
||||||
|
public static NewGroupDialogFragment newInstance(AddListener listener) {
|
||||||
|
NewGroupDialogFragment frag = new NewGroupDialogFragment();
|
||||||
|
frag.mListener = listener;
|
||||||
|
frag.setCancelable(false);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_add_group, null, false);
|
||||||
|
mNameEditText = (EditText) view.findViewById(R.id.name);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean validate() {
|
||||||
|
if (mNameEditText == null) return false;
|
||||||
|
final String name = mNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(name)) return false;
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onConfirm(name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import com.university.journal.R;
|
||||||
|
|
||||||
|
public abstract class NewItemDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
|
protected abstract View inflate(LayoutInflater inflater);
|
||||||
|
|
||||||
|
protected abstract boolean validate();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
final AlertDialog dialog = (AlertDialog) getDialog();
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.getButton(Dialog.BUTTON_POSITIVE)
|
||||||
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (validate()) {
|
||||||
|
dismiss();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getActivity(),
|
||||||
|
getString(R.string.validate_error),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
View view = inflate(LayoutInflater.from(getActivity()));
|
||||||
|
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
builder.setView(view);
|
||||||
|
builder.setTitle(R.string.add);
|
||||||
|
builder.setPositiveButton(android.R.string.ok, null);
|
||||||
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import com.university.journal.R;
|
||||||
|
import com.university.journal.entity.Mark;
|
||||||
|
|
||||||
|
public final class NewMarkDialogFragment extends NewItemDialogFragment {
|
||||||
|
|
||||||
|
private static final String ARG_MARK_VALUE = "mark",
|
||||||
|
ARG_CRITERIA_ID = "criteria_id",
|
||||||
|
ARG_STUDENT_ID = "student_id",
|
||||||
|
ARG_TABLE_ROW = "table_row",
|
||||||
|
ARG_TABLE_COL = "table_col";
|
||||||
|
|
||||||
|
public interface AddListener {
|
||||||
|
void onConfirm(int row, int col, Mark mark);
|
||||||
|
};
|
||||||
|
|
||||||
|
private AddListener mListener;
|
||||||
|
private EditText mMarkEditText;
|
||||||
|
private Mark mMark;
|
||||||
|
private int mRow, mCol;
|
||||||
|
|
||||||
|
public static NewMarkDialogFragment newInstance(AddListener listener,
|
||||||
|
int criteriaId, int studentId, String markValue,
|
||||||
|
int row, int col) {
|
||||||
|
NewMarkDialogFragment frag = new NewMarkDialogFragment();
|
||||||
|
frag.mListener = listener;
|
||||||
|
frag.setCancelable(false);
|
||||||
|
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_MARK_VALUE, markValue);
|
||||||
|
args.putInt(ARG_CRITERIA_ID, criteriaId);
|
||||||
|
args.putInt(ARG_STUDENT_ID, studentId);
|
||||||
|
args.putInt(ARG_TABLE_ROW, row);
|
||||||
|
args.putInt(ARG_TABLE_COL, col);
|
||||||
|
frag.setArguments(args);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_add_mark, null, false);
|
||||||
|
mMarkEditText = (EditText) view.findViewById(R.id.mark);
|
||||||
|
|
||||||
|
mMark = new Mark();
|
||||||
|
final Bundle args = getArguments();
|
||||||
|
if (args != null) {
|
||||||
|
final String markValue = args.getString(ARG_MARK_VALUE);
|
||||||
|
mMark.setMark(markValue);
|
||||||
|
mMark.setCriteriaId(args.getInt(ARG_CRITERIA_ID));
|
||||||
|
mMark.setStudentId(args.getInt(ARG_STUDENT_ID));
|
||||||
|
mRow = args.getInt(ARG_TABLE_ROW);
|
||||||
|
mCol = args.getInt(ARG_TABLE_COL);
|
||||||
|
mMarkEditText.setText(markValue);
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean validate() {
|
||||||
|
if (mMarkEditText == null) return false;
|
||||||
|
final String markValue = mMarkEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(markValue)) return false;
|
||||||
|
|
||||||
|
// No edit mark - not update.
|
||||||
|
if (mMark.getMark().equals(markValue)) return true;
|
||||||
|
mMark.setMark(markValue);
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onConfirm(mRow, mCol, mMark);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import com.university.journal.R;
|
||||||
|
import com.university.journal.db.DbContract.Groups;
|
||||||
|
|
||||||
|
public final class NewStudentDialogFragment extends NewItemDialogFragment {
|
||||||
|
|
||||||
|
public interface AddListener {
|
||||||
|
void onConfirm(String firstName, String lastName, String middleName, long groupId);
|
||||||
|
};
|
||||||
|
|
||||||
|
private AddListener mListener;
|
||||||
|
private EditText mFirtsNameEditText, mLastNameEditText, mMiddleNameEditText;
|
||||||
|
private Spinner mGroupSpinner;
|
||||||
|
private SimpleCursorAdapter mSpinnerAdapter;
|
||||||
|
|
||||||
|
public static NewStudentDialogFragment newInstance(AddListener listener) {
|
||||||
|
NewStudentDialogFragment frag = new NewStudentDialogFragment();
|
||||||
|
frag.mListener = listener;
|
||||||
|
frag.setCancelable(false);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_add_student, null, false);
|
||||||
|
mFirtsNameEditText = (EditText) view.findViewById(R.id.firstname);
|
||||||
|
mLastNameEditText = (EditText) view.findViewById(R.id.lastname);
|
||||||
|
mMiddleNameEditText = (EditText) view.findViewById(R.id.middlename);
|
||||||
|
mGroupSpinner = (Spinner) view.findViewById(R.id.groupSpinner);
|
||||||
|
|
||||||
|
final Cursor cur = getActivity().getContentResolver()
|
||||||
|
.query(Groups.CONTENT_URI, Groups.PROJECTION_ALL, null, null, null);
|
||||||
|
final String[] from = new String[] { Groups.NAME };
|
||||||
|
final int[] to = new int[] { android.R.id.text1 };
|
||||||
|
mSpinnerAdapter = new SimpleCursorAdapter(getActivity(),
|
||||||
|
android.R.layout.simple_spinner_item, cur,
|
||||||
|
from, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
|
||||||
|
mSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
mGroupSpinner.setAdapter(mSpinnerAdapter);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean validate() {
|
||||||
|
if (mFirtsNameEditText == null) return false;
|
||||||
|
final String firstName = mFirtsNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(firstName)) return false;
|
||||||
|
|
||||||
|
if (mLastNameEditText == null) return false;
|
||||||
|
final String lastName = mLastNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(lastName)) return false;
|
||||||
|
|
||||||
|
if (mMiddleNameEditText == null) return false;
|
||||||
|
final String middleName = mMiddleNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(middleName)) return false;
|
||||||
|
|
||||||
|
if (mGroupSpinner.getSelectedItem() == null) return false;
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onConfirm(firstName, lastName, middleName, mGroupSpinner.getSelectedItemId());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import com.university.journal.R;
|
||||||
|
|
||||||
|
public final class NewSubjectDialogFragment extends NewItemDialogFragment {
|
||||||
|
|
||||||
|
public interface AddListener {
|
||||||
|
void onConfirm(String name, String shortName);
|
||||||
|
};
|
||||||
|
|
||||||
|
private AddListener mListener;
|
||||||
|
private EditText mNameEditText, mShortNameEditText;
|
||||||
|
|
||||||
|
public static NewSubjectDialogFragment newInstance(AddListener listener) {
|
||||||
|
NewSubjectDialogFragment frag = new NewSubjectDialogFragment();
|
||||||
|
frag.mListener = listener;
|
||||||
|
frag.setCancelable(false);
|
||||||
|
return frag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.dialog_add_subject, null, false);
|
||||||
|
mNameEditText = (EditText) view.findViewById(R.id.name);
|
||||||
|
mShortNameEditText = (EditText) view.findViewById(R.id.shortName);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean validate() {
|
||||||
|
if (mNameEditText == null) return false;
|
||||||
|
final String name = mNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(name)) return false;
|
||||||
|
|
||||||
|
if (mShortNameEditText == null) return false;
|
||||||
|
final String shortName = mShortNameEditText.getText().toString();
|
||||||
|
if (TextUtils.isEmpty(shortName)) return false;
|
||||||
|
|
||||||
|
if (mListener != null) {
|
||||||
|
mListener.onConfirm(name, shortName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
105
src/com/university/journal/fragments/StudentFragment.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.content.CursorLoader;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import android.support.v4.widget.SimpleCursorAdapter;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import com.university.journal.db.DbContract;
|
||||||
|
import com.university.journal.db.DbContract.Groups;
|
||||||
|
import com.university.journal.db.DbContract.Students;
|
||||||
|
import com.university.journal.entity.Student;
|
||||||
|
|
||||||
|
public final class StudentFragment extends DbTableFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int loaderNumber() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getUIBindFrom() {
|
||||||
|
return new String[] { Students.LAST_NAME, Students.FIRST_NAME, Students.MIDDLE_NAME };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int[] getUIBindTo() {
|
||||||
|
return new int[] { android.R.id.text1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getUIBindLayoutResource() {
|
||||||
|
return android.R.layout.simple_list_item_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void postInitAdapter(SimpleCursorAdapter adapter) {
|
||||||
|
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
|
||||||
|
final String lastName = cursor.getString(1);
|
||||||
|
final String firstName = cursor.getString(2);
|
||||||
|
final String middleName = cursor.getString(3);
|
||||||
|
TextView textView = (TextView) view;
|
||||||
|
textView.setText(String.format("%s %s %s",
|
||||||
|
lastName, firstName, middleName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getListView().setOnItemClickListener(mItemClickListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogFragment getAddDataDialogFragment() {
|
||||||
|
return NewStudentDialogFragment.newInstance(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onItemDelete(long id) {
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.delete(ContentUris.withAppendedId(Students.CONTENT_URI, id), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
|
||||||
|
return new CursorLoader(getActivity(),
|
||||||
|
Students.CONTENT_URI, Students.PROJECTION_ALL,
|
||||||
|
null, null, Students.LAST_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AdapterView.OnItemClickListener mItemClickListener =
|
||||||
|
new AdapterView.OnItemClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
String selection = String.format("%s.%s = ?", Students.TABLE_NAME, Students._ID);
|
||||||
|
String[] args = { String.valueOf(id) };
|
||||||
|
Cursor cursor = getActivity().getContentResolver()
|
||||||
|
.query(Uri.withAppendedPath(DbContract.CONTENT_URI, "group_by_student"),
|
||||||
|
null, selection, args, null);
|
||||||
|
if ( (cursor != null) && (cursor.moveToFirst()) ) {
|
||||||
|
String group = cursor.getString(cursor.getColumnIndex(Groups.NAME));
|
||||||
|
Toast.makeText(getActivity(), group, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private NewStudentDialogFragment.AddListener mListener = new NewStudentDialogFragment.AddListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirm(String firstName, String lastName, String middleName, long groupId) {
|
||||||
|
Student obj = new Student(firstName, lastName, middleName, (int) groupId);
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.insert(Students.CONTENT_URI, obj.getContentValues());
|
||||||
|
getActivity().getSupportLoaderManager().getLoader(loaderNumber()).forceLoad();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
51
src/com/university/journal/fragments/SubjectFragment.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.university.journal.fragments;
|
||||||
|
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v4.content.CursorLoader;
|
||||||
|
import android.support.v4.content.Loader;
|
||||||
|
import com.university.journal.db.DbContract.Subjects;
|
||||||
|
import com.university.journal.entity.Subject;
|
||||||
|
|
||||||
|
public final class SubjectFragment extends DbTableFragment {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int loaderNumber() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getUIBindFrom() {
|
||||||
|
return new String[] { Subjects.NAME };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogFragment getAddDataDialogFragment() {
|
||||||
|
return NewSubjectDialogFragment.newInstance(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onItemDelete(long id) {
|
||||||
|
getActivity().getContentResolver()
|
||||||
|
.delete(ContentUris.withAppendedId(Subjects.CONTENT_URI, id), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
|
||||||
|
return new CursorLoader(getActivity(),
|
||||||
|
Subjects.CONTENT_URI, Subjects.PROJECTION_ALL,
|
||||||
|
null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NewSubjectDialogFragment.AddListener mListener = new NewSubjectDialogFragment.AddListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirm(String name, String shortName) {
|
||||||
|
Subject obj = new Subject(name, shortName);
|
||||||
|
getActivity().getContentResolver().insert(Subjects.CONTENT_URI, obj.getContentValues());
|
||||||
|
getActivity().getSupportLoaderManager().getLoader(loaderNumber()).forceLoad();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|