Initial commit

This commit is contained in:
aNNiMON 2024-02-14 00:01:58 +02:00
commit 5c65209f2b
80 changed files with 3240 additions and 0 deletions

9
.classpath Normal file
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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" />

View 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>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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>

View 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
View 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" />

View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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);
}
}

View 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();
}
}

View 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;
}
}

View 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());
}
}
}

View 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;
}
}

View 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};
}
}

View 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;");
}
}
}

View 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;
}

View 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;
}
}

View 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();
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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));
}
}

View 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;
}
}

View 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();
}
};
}

View 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;
}
};
}

View 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();
}
};
}

View 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);
}
};
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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();
}
};
}

View 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();
}
};
}