diff --git a/app/build.gradle b/app/build.gradle index a67cb09..cd4f5ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "jp.ddo.hotmist.unicodepad" minSdkVersion 21 targetSdkVersion 34 - versionCode 68 - versionName "2.15.1" + versionCode 69 + versionName "2.16.0" } compileOptions { diff --git a/app/src/main/assets/namedb.zip b/app/src/main/assets/namedb.zip index fdb6417..c5222f3 100644 Binary files a/app/src/main/assets/namedb.zip and b/app/src/main/assets/namedb.zip differ diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterAdapter.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterAdapter.kt index 1f9c67d..29bda83 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterAdapter.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterAdapter.kt @@ -21,7 +21,6 @@ import android.view.* import android.view.View.MeasureSpec import android.widget.CheckBox import android.widget.LinearLayout -import android.widget.ScrollView import android.widget.TextView import androidx.core.content.res.ResourcesCompat import androidx.core.widget.NestedScrollView @@ -31,7 +30,7 @@ import java.util.* import kotlin.math.max import kotlin.math.min -internal class CharacterAdapter(private val activity: UnicodeActivity, private val adapter: UnicodeAdapter, private val tf: Typeface?, private val locale: Locale, private val db: NameDatabase, private val afav: FavoriteAdapter) : PagerAdapter() { +internal class CharacterAdapter(private val activity: UnicodeActivity, private val adapter: UnicodeAdapter, private var typeface: Typeface?, private var locale: Locale, private val db: NameDatabase, private val afav: FavoriteAdapter) : PagerAdapter() { var index = 0 private set private val reslist = TypedValue().also { @@ -49,7 +48,7 @@ internal class CharacterAdapter(private val activity: UnicodeActivity, private v val text = CharacterView(activity) text.text = adapter.getItem(position) text.setTextSize(fontsize) - text.setTypeface(tf, locale) + text.setTypeface(typeface, locale) text.drawSlash(false) text.setLayerType(View.LAYER_TYPE_SOFTWARE, null) text.setTextColor(Color.BLACK) @@ -68,8 +67,7 @@ internal class CharacterAdapter(private val activity: UnicodeActivity, private v val str = StringBuilder() if (!emoji) str.append(adapter.getItem(position)) val textPadding = (6 * activity.resources.displayMetrics.scaledDensity).toInt() - for (i in 0 until if (!emoji) 10 else 7) { - if (emoji && i == 5) continue + for (i in 0 until if (!emoji) 4 else 5) { if (i == 2) { val v = if (!emoji) db.getInt(itemid, cols[i]) else db.getInt(adapter.getItemString(position), emjs[i]) val desc = TextView(activity) @@ -96,7 +94,7 @@ internal class CharacterAdapter(private val activity: UnicodeActivity, private v break } if (r == null) continue - val l = r.split(if (emoji && i == 6) " " else "\n").toTypedArray() + val l = r.split("\n").toTypedArray() for (s in l) { if (i == 0) { layout.addView(LinearLayout(activity).apply { @@ -132,85 +130,92 @@ internal class CharacterAdapter(private val activity: UnicodeActivity, private v hl.orientation = LinearLayout.HORIZONTAL val it = TextView(activity) it.gravity = Gravity.CENTER_VERTICAL - it.text = (if (!emoji) mods else mode)[i] - hl.addView(it, LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)) - if (i < 6) { - val desc = TextView(activity) - desc.text = s - desc.setTextIsSelectable(true) - hl.addView(desc, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) - } else { - var cs = "" - var ps = "" - var ns: String? = null - Scanner(s).use { sc -> - var j = 0 - while (sc.hasNext()) { - if (i == 9 && j == 0 && s[0] == '<') { - ns = sc.next() - ++j - continue + if (!emoji && i == 3) { + val charMap = mapOf( + "*" to "\u2022 ", + "=" to "= ", + "%" to "\u203B ", + "x" to "\u2192 ", + "~" to "~ ", + ":" to "\u2261 ", + "#" to "\u2248 ", + "@" to "\u2022 ", + ) + it.text = charMap[s.substring(0, 1)] ?: s.substring(0, 1) + hl.addView(it, LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)) + if (s.startsWith("*") || s.startsWith("=") || s.startsWith("%") || s.startsWith("@")) { + it.gravity = Gravity.TOP + val desc = TextView(activity) + desc.text = s.substring(2) + desc.setTextIsSelectable(true) + hl.addView(desc, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) + } else { + var cs = "" + var ps = "" + val ns = mutableListOf() + Scanner(s.substring(2)).use { sc -> + while (sc.hasNext()) { + val ss = sc.next() + if (Regex("[0-9A-Fa-f]{4,6}").matches(ss)) { + val tgt = Integer.parseInt(ss, 16) + cs += String(Character.toChars(tgt)) + ps += String.format("U+%04X ", tgt) + } else { + ns.add(ss) + } } - val tgt = sc.nextInt(16) - cs += String(Character.toChars(tgt)) - ps += String.format("U+%04X ", tgt) - if (i == 6) { - val n = db[tgt, "name"] - ns = n ?: "" - break - } - if (i == 7 && j == 1) { - sc.useDelimiter("\n") - sc.skip(" ") - ns = if (sc.hasNext()) sc.next() else "" - break + } + if (ps.isEmpty()) continue + ps = ps.substring(0, ps.length - 1) + val ct = CharacterView(activity, null, android.R.attr.textAppearanceLarge) + ct.setPadding(0, 0, 0, 0) + ct.setPadding(UnicodeAdapter.padding, UnicodeAdapter.padding, UnicodeAdapter.padding, UnicodeAdapter.padding) + ct.drawSlash(false) + ct.setTextSize(UnicodeAdapter.fontsize) + ct.text = cs + ct.setTypeface(typeface, locale) + hl.addView(ct, LinearLayout.LayoutParams((activity.resources.displayMetrics.scaledDensity * UnicodeAdapter.fontsize * 2 + UnicodeAdapter.padding * 2).toInt(), ViewGroup.LayoutParams.MATCH_PARENT)) + val pt = TextView(activity, null, android.R.attr.textAppearanceSmall) + pt.setPadding(0, 0, 0, 0) + pt.gravity = Gravity.CENTER_VERTICAL + pt.text = ps + if (ns.isNotEmpty()) { + val nt = TextView(activity, null, android.R.attr.textAppearanceSmall) + nt.setPadding(0, 0, 0, 0) + nt.gravity = Gravity.CENTER_VERTICAL + nt.text = ns.joinToString(" ") + val vl = LinearLayout(activity) + vl.orientation = LinearLayout.VERTICAL + vl.addView(pt, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) + vl.addView(nt, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) + hl.addView(vl, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) + } else hl.addView(pt, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) + hl.id = 0x3F000000 + str.codePointCount(0, str.length) + str.append(cs) + hl.isEnabled = true + hl.isClickable = true + hl.isFocusable = true + hl.setOnClickListener { view -> + var j = 0 + while (j < cs.length) { + val code = cs.codePointAt(j) + activity.adpPage.onItemClick(null, view, -1, code.toLong()) + j += Character.charCount(code) } - ++j } - } - if (ps.isEmpty()) continue - ps = ps.substring(0, ps.length - 1) - val ct = CharacterView(activity, null, android.R.attr.textAppearanceLarge) - ct.setPadding(0, 0, 0, 0) - ct.setPadding(UnicodeAdapter.padding, UnicodeAdapter.padding, UnicodeAdapter.padding, UnicodeAdapter.padding) - ct.drawSlash(false) - ct.setTextSize(UnicodeAdapter.fontsize) - ct.text = cs - ct.setTypeface(tf, locale) - hl.addView(ct, LinearLayout.LayoutParams((activity.resources.displayMetrics.scaledDensity * UnicodeAdapter.fontsize * 2 + UnicodeAdapter.padding * 2).toInt(), ViewGroup.LayoutParams.MATCH_PARENT)) - val pt = TextView(activity, null, android.R.attr.textAppearanceSmall) - pt.setPadding(0, 0, 0, 0) - pt.gravity = Gravity.CENTER_VERTICAL - pt.text = ps - if (ns != null) { - val nt = TextView(activity, null, android.R.attr.textAppearanceSmall) - nt.setPadding(0, 0, 0, 0) - nt.gravity = Gravity.CENTER_VERTICAL - nt.text = ns - val vl = LinearLayout(activity) - vl.orientation = LinearLayout.VERTICAL - vl.addView(pt, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) - vl.addView(nt, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) - hl.addView(vl, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) - } else hl.addView(pt, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) - hl.id = 0x3F000000 + str.codePointCount(0, str.length) - str.append(cs) - hl.isEnabled = true - hl.isClickable = true - hl.isFocusable = true - hl.setOnClickListener { view -> - var j = 0 - while (j < cs.length) { - val code = cs.codePointAt(j) - activity.adpPage.onItemClick(null, view, -1, code.toLong()) - j += Character.charCount(code) + hl.setOnLongClickListener { view -> + activity.adpPage.showDesc(null, view.id - 0x3F000000, StringAdapter(str.toString(), activity, db)) + true } + hl.setBackgroundResource(reslist) } - hl.setOnLongClickListener { view -> - activity.adpPage.showDesc(null, view.id - 0x3F000000, StringAdapter(str.toString(), activity, db)) - true - } - hl.setBackgroundResource(reslist) + } else { + it.text = (if (!emoji) mods else mode)[i] + hl.addView(it, LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)) + val desc = TextView(activity) + desc.text = s + desc.setTextIsSelectable(true) + hl.addView(desc, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f)) } hl.setPadding(textPadding, 0, textPadding, 0) layout.addView(hl, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) @@ -239,14 +244,23 @@ internal class CharacterAdapter(private val activity: UnicodeActivity, private v val id: Long get() = adapter.getItemCodePoint(index) + fun getItemId(position: Int): Long { + return adapter.getItemCodePoint(position) + } + + fun setTypeface(typeface: Typeface?, locale: Locale) { + this.typeface = typeface + this.locale = locale + } + companion object { var fontsize = 160f var checker = 10f var lines = true var shrink = true - private val cols = arrayOf("name", "utf8", "version", "comment", "alias", "formal", "xref", "vari", "decomp", "compat") - private val mods = arrayOf(null, "UTF-8: ", "from Unicode ", "\u2022 ", "= ", "\u203B ", "\u2192 ", "~ ", "\u2261 ", "\u2248 ") - private val emjs = arrayOf("name", "utf8", "version", "grp", "subgrp", "", "id") - private val mode = arrayOf(null, "UTF-8: ", "from Unicode Emoji ", "Group: ", "Subgroup: ", null, "") + private val cols = arrayOf("name", "utf8", "version", "lines") + private val mods = arrayOf(null, "UTF-8: ", "from Unicode ", "") + private val emjs = arrayOf("name", "utf8", "version", "grp", "subgrp") + private val mode = arrayOf(null, "UTF-8: ", "from Unicode Emoji ", "Group: ", "Subgroup: ") } } \ No newline at end of file diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterView.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterView.kt index c0a517c..c445b75 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterView.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/CharacterView.kt @@ -72,7 +72,10 @@ class CharacterView @JvmOverloads constructor(context: Context, attrs: Attribute } fun setTypeface(tf: Typeface?, locale: Locale) { - if (paint.typeface != tf) invalid = true + if (paint.typeface != tf || paint.textLocale != locale) { + invalid = true + invalidate() + } paint.typeface = tf paint.textLocale = locale requestLayout() diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/FilterableSpinner.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/FilterableSpinner.kt index 36b05d1..2ab3d82 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/FilterableSpinner.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/FilterableSpinner.kt @@ -10,7 +10,6 @@ import android.util.AttributeSet import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter -import android.widget.ListPopupWindow.INPUT_METHOD_FROM_FOCUSABLE import android.widget.SpinnerAdapter import android.widget.ThemedSpinnerAdapter import androidx.appcompat.widget.AppCompatEditText @@ -32,7 +31,8 @@ class FilterableSpinner(context: Context, attrs: AttributeSet?, defStyle: Int) : popupField.isAccessible = true val popup = popupField.get(this as AppCompatSpinner) if (popup is ListPopupWindow) { - popup.inputMethodMode = INPUT_METHOD_FROM_FOCUSABLE + popup.inputMethodMode = ListPopupWindow.INPUT_METHOD_FROM_FOCUSABLE + popup.show() } } catch (e: NoSuchFieldException) { e.printStackTrace() diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/FindAdapter.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/FindAdapter.kt index 3bef27b..ed980be 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/FindAdapter.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/FindAdapter.kt @@ -39,7 +39,7 @@ internal class FindAdapter(activity: Activity, private val pref: SharedPreferenc override fun instantiate(view: View): View { super.instantiate(view) - val view = view as RecyclerView + check(view is RecyclerView) val layout = LinearLayout(activity) layout.orientation = LinearLayout.VERTICAL val find = ImageButton(activity) @@ -104,10 +104,6 @@ internal class FindAdapter(activity: Activity, private val pref: SharedPreferenc override fun destroy() { adapter = null - curList?.close() - curList = null - curEmoji?.close() - curEmoji = null super.destroy() } diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/ListAdapter.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/ListAdapter.kt index b277e0d..b99d1a6 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/ListAdapter.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/ListAdapter.kt @@ -670,17 +670,6 @@ internal class ListAdapter(activity: Activity, pref: SharedPreferences, db: Name } layout.addView(this.view, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) (this.view as RecyclerView?)?.also { view -> - view.setOnTouchListener { _, _ -> - runOnUiThread { - highTarget?.setBackgroundColor(resnormal) - highTarget = null - if (highlight != -1) { - notifyItemChanged(highlight) - highlight = -1 - } - } - false - } val e = fromCodePoint.floorEntry(scroll) ?: fromCodePoint.firstEntry() if (e.value.end < scroll) scroll = e.value.end scrollToItem(scroll - e.key + e.value.index) @@ -827,6 +816,17 @@ internal class ListAdapter(activity: Activity, pref: SharedPreferences, db: Name return (i - e.key + e.value.codePoint).toLong() } + override fun onTouch() { + runOnUiThread { + highTarget?.setBackgroundColor(resnormal) + highTarget = null + if (highlight != -1) { + notifyItemChanged(highlight) + highlight = -1 + } + } + } + init { val str = pref.getString("mark", null) ?: "" for (s in str.split("\n").toTypedArray()) { diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/NameDatabase.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/NameDatabase.kt index 3e41277..5b9249d 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/NameDatabase.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/NameDatabase.kt @@ -134,7 +134,7 @@ class NameDatabase(context: Context) { try { db.rawQuery("SELECT * FROM version_code;", null).use { cur -> cur.moveToFirst() - if (cur.getInt(0) != 59) throw SQLiteException() + if (cur.getInt(0) != 60) throw SQLiteException() } } catch (e: SQLiteException) { db.close() diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/PageAdapter.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/PageAdapter.kt index f9c4498..d05a1bc 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/PageAdapter.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/PageAdapter.kt @@ -20,6 +20,7 @@ import android.app.AlertDialog import android.content.SharedPreferences import android.content.res.Resources import android.graphics.Typeface +import android.os.Build import android.view.* import android.widget.* import android.widget.AdapterView.OnItemClickListener @@ -54,6 +55,7 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share private val adapterFavorite: FavoriteAdapter internal val adapterEdit: EditAdapter private val adapterEmoji: EmojiAdapter + private var adapterCharacter: CharacterAdapter? = null private var blist = false private var bfind = false private var brec = false @@ -109,31 +111,56 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share return adapters[position].let { adapter -> adapter.setListener(this) if (adapter is DragListUnicodeAdapter<*> && adapter.single) { - DynamicDragListView(activity, null).let { view -> + DynamicDragListView(activity, null).also { view -> view.setLayoutManager(LinearLayoutManager(activity)) view.setDragListListener(adapter) view.setAdapter(adapter, false) view.setCanDragHorizontally(false) view.setCanDragVertically(true) - view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - views[position] = view - adapter.instantiate(view).also { layout -> - collection.addView(layout, 0) - layouts[position] = layout - } } } else { check(adapter is RecyclerView.Adapter<*>) - RecyclerView(activity).let { view -> + RecyclerView(activity).also { view -> view.adapter = adapter view.layoutManager = adapter.getLayoutManager(activity, column) view.adapter = adapter - view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - views[position] = view - adapter.instantiate(view).also { layout -> - collection.addView(layout, 0) - layouts[position] = layout + } + }.let { view -> + view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + views[position] = view + adapter.instantiate(view).also { layout -> + val scaleDetector = ScaleGestureDetector(activity, object : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScale(detector: ScaleGestureDetector): Boolean { + return (if (detector.scaleFactor > 1f) { + true + } else if (detector.scaleFactor < 1f) { + false + } else { + null + })?.let { + if (adapter.single != it) { + pref.edit().putString( + if (adapter === adapterRecent) "single_rec" else + if (adapter === adapterList) "single_list" else + if (adapter === adapterFind) "single_find" else + if (adapter === adapterFavorite) "single_fav" else + if (adapter === adapterEdit) "single_edt" else + if (adapter === adapterEmoji) "single_emoji" else null, + it.toString() + ).apply() + notifyDataSetChanged() + } + true + } ?: false + } + }) + (if (view is DragListView) view.recyclerView else view).setOnTouchListener { _, event -> + adapter.onTouch() + scaleDetector.onTouchEvent(event) + scaleDetector.isInProgress } + collection.addView(layout, 0) + layouts[position] = layout } } } @@ -162,9 +189,6 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share val end = edit.selectionEnd if (start == -1) return edit.editableText.replace(min(start, end), max(start, end), if (adapter == null || id >= 0) String(Character.toChars(id.toInt())) else adapter.getItem(position)) - dlg?.let { - if (it.isShowing) it.dismiss() - } } override fun onItemLongClick(parent: AdapterView<*>, view: View, position: Int, id: Long): Boolean { @@ -176,8 +200,10 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share showDesc(adapter, position, adapter) } - private var dlg: AlertDialog? = null fun showDesc(parentAdapter: UnicodeAdapter?, index: Int, ua: UnicodeAdapter) { + activity.getSystemService(android.content.Context.INPUT_METHOD_SERVICE)?.let { + (it as android.view.inputmethod.InputMethodManager).hideSoftInputFromWindow(edit.windowToken, 0) + } val pager = ViewPager(activity) pager.addView(PagerTabStrip(activity).apply { id = R.id.TAB_ID @@ -188,6 +214,7 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share isDecor = true }) val adapter = CharacterAdapter(activity, ua.freeze(), tf, locale, db, adapterFavorite) + adapterCharacter = adapter pager.adapter = adapter pager.setCurrentItem(index, false) pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { @@ -209,7 +236,7 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share adapterRecent.rem(adapter.id.toInt()) adapterRecent.notifyItemRemoved(adapter.index) } - }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 3, ViewGroup.LayoutParams.WRAP_CONTENT)) + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) if (view is AbsListView && parentAdapter === adapterEdit) addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { text = activity.getString(R.string.delete) setOnClickListener { @@ -217,7 +244,7 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share val s = edit.editableText.toString() edit.editableText.delete(s.offsetByCodePoints(0, i), s.offsetByCodePoints(0, i + 1)) } - }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 3, ViewGroup.LayoutParams.WRAP_CONTENT)) + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) if (view is RecyclerView && parentAdapter === adapterList) addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { text = activity.getString(R.string.mark) setOnClickListener { @@ -228,25 +255,45 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share .setPositiveButton(R.string.mark) { _, _ -> adapterList.mark(adapter.id.toInt(), edit.text.toString()) } .create().show() } - }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 3, ViewGroup.LayoutParams.WRAP_CONTENT)) + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) addView(View(activity), LinearLayout.LayoutParams(0, 1, 1f)) - if (parentAdapter !== adapterEmoji) addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { - text = activity.getString(R.string.inlist) - setOnClickListener { find(adapter.id.toInt()) } - }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 3, ViewGroup.LayoutParams.WRAP_CONTENT)) + addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { + text = activity.getString(R.string.find) + isEnabled = adapter.getItemId(index) >= 0 + setOnClickListener { if (adapter.id >= 0) find(adapter.id.toInt()) } + pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} + override fun onPageSelected(position: Int) { + isEnabled = adapter.getItemId(position) >= 0 + } + override fun onPageScrollStateChanged(state: Int) {} + }) + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) addView(View(activity), LinearLayout.LayoutParams(0, 1, 1f)) - if (view != null) addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { - text = activity.getString(R.string.input) - setOnClickListener { - if (adapter.id >= 0) { - adapterRecent.add(adapter.id.toInt()) + if (view != null) { + addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { + text = activity.getString(android.R.string.copy) + setOnClickListener { + val cm = activity.getSystemService(android.content.Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager + cm.setPrimaryClip(android.content.ClipData.newPlainText(null, ua.getItem(adapter.index))) + if (Build.VERSION.SDK_INT <= 32) { + Toast.makeText(activity, R.string.copied, Toast.LENGTH_SHORT).show() + } } - val start = edit.selectionStart - val end = edit.selectionEnd - if (start == -1) return@setOnClickListener - edit.editableText.replace(min(start, end), max(start, end), ua.getItem(adapter.index)) - } - }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 3, ViewGroup.LayoutParams.WRAP_CONTENT)) + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) + addView(Button(activity, null, android.R.attr.buttonBarButtonStyle).apply { + text = activity.getString(R.string.input) + setOnClickListener { + if (adapter.id >= 0) { + adapterRecent.add(adapter.id.toInt()) + } + val start = edit.selectionStart + val end = edit.selectionEnd + if (start == -1) return@setOnClickListener + edit.editableText.replace(min(start, end), max(start, end), ua.getItem(adapter.index)) + } + }, LinearLayout.LayoutParams(Resources.getSystem().displayMetrics.widthPixels / 4, ViewGroup.LayoutParams.WRAP_CONTENT)) + } }, LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) activity.setBottomSheetContent(layout, if (parentAdapter === adapterList) null else ua) } @@ -286,6 +333,7 @@ class PageAdapter(private val activity: UnicodeActivity, private val pref: Share adapterFavorite.setTypeface(tf, locale) adapterEdit.setTypeface(tf, locale) adapterEmoji.setTypeface(tf, locale) + adapterCharacter?.setTypeface(tf, locale) } fun onSizeChanged(top: Int) { diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/TabsActivity.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/TabsActivity.kt index 9f2a090..410fb7a 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/TabsActivity.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/TabsActivity.kt @@ -17,6 +17,9 @@ package jp.ddo.hotmist.unicodepad import android.annotation.SuppressLint import android.os.Bundle +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.view.setPadding import androidx.recyclerview.widget.LinearLayoutManager import com.woxthebox.draglistview.DragListView @@ -34,14 +37,21 @@ class TabsActivity : BaseActivity() { @SuppressLint("ClickableViewAccessibility") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val view = DynamicDragListView(this, null) - val adapter = TabsAdapter(this) - view.setLayoutManager(LinearLayoutManager(this)) - view.setDragListListener(adapter) - view.setAdapter(adapter, true) - view.setCanDragHorizontally(false) - view.setCanDragVertically(true) - setContentView(view) + setContentView(LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + addView(TextView(this@TabsActivity).apply { + setText(R.string.tabs_hint) + setPadding((8 * this@TabsActivity.resources.displayMetrics.density).toInt()) + }) + val view = DynamicDragListView(this@TabsActivity, null) + val adapter = TabsAdapter(this@TabsActivity) + view.setLayoutManager(LinearLayoutManager(this@TabsActivity)) + view.setDragListListener(adapter) + view.setAdapter(adapter, true) + view.setCanDragHorizontally(false) + view.setCanDragVertically(true) + addView(view) + }) } override fun onSupportNavigateUp(): Boolean { diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeActivity.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeActivity.kt index 2f8a9e9..24b91b7 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeActivity.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeActivity.kt @@ -56,7 +56,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.coordinatorlayout.widget.CoordinatorLayout @@ -338,7 +337,7 @@ class UnicodeActivity : BaseActivity() { ) AndroidView( factory = { context -> Button(context, null, android.R.attr.buttonBarButtonStyle).apply { - text = resources.getText(R.string.find) + text = resources.getText(R.string.desc) } }, update = { it.setOnClickListener { @@ -348,17 +347,13 @@ class UnicodeActivity : BaseActivity() { if (start == -1) return@setOnClickListener val end = editText.selectionEnd adpPage.adapterEdit.updateString() - adpPage.showDesc( - null, - str.codePointCount( - 0, - if (start == end) if (start == 0) 0 else start - 1 else min( - start, - end - ) - ), - adpPage.adapterEdit - ) + var pos = if (start == end) if (start == 0) 0 else start - 1 else min(start, end) + var i = 0 + while (pos > 0) { + pos -= adpPage.adapterEdit.getItem(i++).length + } + if (pos < 0) i-- + adpPage.showDesc(null, i, adpPage.adapterEdit) } }, modifier = Modifier.weight(1f), @@ -370,11 +365,13 @@ class UnicodeActivity : BaseActivity() { update = { it.setOnClickListener { cm.text = editText.text.toString() - Toast.makeText( - this@UnicodeActivity, - R.string.copied, - Toast.LENGTH_SHORT - ).show() + if (Build.VERSION.SDK_INT <= 32) { + Toast.makeText( + this@UnicodeActivity, + R.string.copied, + Toast.LENGTH_SHORT + ).show() + } } }, modifier = Modifier.weight(1f), @@ -481,22 +478,31 @@ class UnicodeActivity : BaseActivity() { } AndroidView( factory = { context -> CoordinatorLayout(context).apply { - addView(if (scrollUi) { - LockableScrollView(context).also { - scroll = it - it.addView(ComposeView(it.context).apply { - setContent { - MainView() - } - }) - it.clipToOutline = true - } - } else { - scroll = null - ComposeView(context).apply { - setContent { - MainView() + addView(LinearLayout(context).apply { + orientation = LinearLayout.VERTICAL + addView(if (scrollUi) { + LockableScrollView(context).also { + scroll = it + it.addView(ComposeView(it.context).apply { + setContent { + MainView() + } + }) + it.clipToOutline = true + } + } else { + scroll = null + ComposeView(context).apply { + setContent { + MainView() + } } + }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)) + if (adCompat.showAdSettings) { + addView(LinearLayout(context).apply { + id = R.id.adContainer + orientation = LinearLayout.VERTICAL + }, LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)) } }) addView(LinearLayout(context).apply { @@ -548,20 +554,13 @@ class UnicodeActivity : BaseActivity() { } }) }}, + update = { + if (adCompat.showAdSettings) { + adCompat.renderAdToContainer(this@UnicodeActivity, pref) + } + }, modifier = Modifier.fillMaxWidth().weight(1f), ) - if (adCompat.showAdSettings) { - AndroidView( - factory = { context -> LinearLayout(context).apply { - id = R.id.adContainer - orientation = LinearLayout.VERTICAL - } }, - update = { - adCompat.renderAdToContainer(this@UnicodeActivity, pref) - }, - modifier = Modifier.fillMaxWidth(), - ) - } } LaunchedEffect(Unit) { @@ -834,7 +833,13 @@ class UnicodeActivity : BaseActivity() { if (start == -1) return@run val end = editText.selectionEnd adpPage.adapterEdit.updateString() - adpPage.showDesc(null, str.codePointCount(0, if (start == end) if (start == 0) 0 else start - 1 else min(start, end)), adpPage.adapterEdit) + var pos = if (start == end) if (start == 0) 0 else start - 1 else min(start, end) + var i = 0 + while (pos > 0) { + pos -= adpPage.adapterEdit.getItem(i++).length + } + if (pos < 0) i-- + adpPage.showDesc(null, i, adpPage.adapterEdit) } MENU_ID_COPY -> { cm.text = editText.text.toString() @@ -875,12 +880,12 @@ class UnicodeActivity : BaseActivity() { super.onPause() } - override fun dispatchKeyEvent(e: KeyEvent): Boolean { - if (e.keyCode == KeyEvent.KEYCODE_MENU && e.action == KeyEvent.ACTION_UP) { + override fun dispatchKeyEvent(event: KeyEvent): Boolean { + if (event.keyCode == KeyEvent.KEYCODE_MENU && event.action == KeyEvent.ACTION_UP) { startActivityForResult(Intent(this, SettingActivity::class.java), 0) return true } - return super.dispatchKeyEvent(e) + return super.dispatchKeyEvent(event) } @Deprecated("Deprecated in Java") @@ -976,6 +981,16 @@ class UnicodeActivity : BaseActivity() { editText.typeface = tf editText.textLocale = locale adpPage.setTypeface(tf, locale) + fun visit(view: View) { + if (view is ViewGroup) { + for (i in 0 until view.childCount) { + visit(view.getChildAt(i)) + } + } else if (view is CharacterView) { + view.setTypeface(tf, locale) + } + } + visit(bottomSheetView) } companion object { diff --git a/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeAdapter.kt b/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeAdapter.kt index d4d9999..bfcf855 100644 --- a/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeAdapter.kt +++ b/app/src/main/java/jp/ddo/hotmist/unicodepad/UnicodeAdapter.kt @@ -24,6 +24,7 @@ import android.util.TypedValue import android.view.* import android.widget.* import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.woxthebox.draglistview.DragItemAdapter import com.woxthebox.draglistview.DragListView @@ -36,6 +37,8 @@ class GridLayoutManagerWrapper(context: Context, spanCount: Int) : GridLayoutMan super.onLayoutChildren(recycler, state) } catch (e: IndexOutOfBoundsException) { Log.e("GridLayoutManager", "onLayoutChildren: $e") + } catch (e: IllegalArgumentException) { + Log.e("GridLayoutManager", "onLayoutChildren: $e") } } } @@ -117,7 +120,6 @@ interface UnicodeAdapter { fun setTypeface(typeface: Typeface?, locale: Locale) { this.typeface = typeface this.locale = locale - invalidateViews() } companion object { @@ -128,7 +130,11 @@ interface UnicodeAdapter { abstract class ViewHolder(val view: View) : DragItemAdapter.ViewHolder(view, R.id.HANDLE_ID, false) - abstract class CharacterViewHolder(view: View, val characterView: CharacterView) : ViewHolder(view) + abstract class CharacterViewHolder(view: View, val characterView: CharacterView) : ViewHolder(view) { + fun setTypeface(typeface: Typeface?, locale: Locale) { + characterView.setTypeface(typeface, locale) + } + } class CellViewHolder(view: LinearLayout, characterView: CharacterView) : CharacterViewHolder(view, characterView) @@ -206,6 +212,8 @@ interface UnicodeAdapter { activity.runOnUiThread(action) } + fun onTouch() {} + var layoutManager: GridLayoutManager? fun getLayoutManager(context: Context, spanCount: Int): GridLayoutManager { @@ -313,6 +321,17 @@ abstract class RecyclerUnicodeAdapter(override val activity: Activity, private v return if (getTitleCount() > 0 && i == getTitlePosition(titleIndex) + titleIndex) 1 else 0 } + override fun setTypeface(typeface: Typeface?, locale: Locale) { + super.setTypeface(typeface, locale) + layoutManager?.let { layoutManager -> + for (i in layoutManager.findFirstVisibleItemPosition()..layoutManager.findLastVisibleItemPosition()) { + val holder = (view as RecyclerView?)?.findViewHolderForAdapterPosition(i) + if (holder is UnicodeAdapter.CharacterViewHolder) { + holder.setTypeface(typeface, locale) + } + } + } + } class GroupViewHolder(view: TextView) : RecyclerView.ViewHolder(view) { val textView: TextView = view @@ -433,6 +452,20 @@ abstract class DragListUnicodeAdapter(override val activity: Activity, privat return itemCount } + override fun setTypeface(typeface: Typeface?, locale: Locale) { + super.setTypeface(typeface, locale) + ((view as? DragListView)?.recyclerView ?: view as? RecyclerView)?.let { recyclerView -> + (recyclerView.layoutManager as? LinearLayoutManager)?.let { layoutManager -> + for (i in layoutManager.findFirstVisibleItemPosition()..layoutManager.findLastVisibleItemPosition()) { + val holder = recyclerView.findViewHolderForAdapterPosition(i) + if (holder is UnicodeAdapter.CharacterViewHolder) { + holder.setTypeface(typeface, locale) + } + } + } + } + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UnicodeAdapter.ViewHolder { return super.onCreateViewHolder(parent, viewType) as UnicodeAdapter.ViewHolder } diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index b96c6d1..22fbf3a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -403,6 +403,7 @@ 広告を非表示 チュートリアルをスキップ タブ設定… + ヒント: リスト上でピンチイン・アウトすると1列と複数列を素早く切り替えられます 表示タブ 非表示タブ diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 60400b9..3ca3e93 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -43,8 +43,8 @@ Pontos de código Ponto de código inválido Não foi possível abrir a fonte - Impossível acessar; o aplicativo pode não ter permissão de leitura - Você negou o acesso. Para navegar pelo cartão SD, por favor garanta permissão ao armazenamento pela Configuração do app. + Não é possível acessar; o aplicativo pode não ter permissão de leitura + Você negou o acesso. Para navegar pelo cartão SD, por favor, garanta permissão ao armazenamento pelas Configurações do app. 0 Latim Básico 80 Latim Suplementar 1 @@ -116,7 +116,7 @@ 1D00 Expansões Fonéticas 1D80 Expansões Fonéticas Suplementares 1DC0 Marcas Diacríticas Combinantes Suplementares - 1E00 Latim Expandido Adicional + 1E00 Expansão Adicional do Latim 1F00 Expansões do Grego 2000 Pontuação Geral 2070 Superscripts e Subscripts @@ -153,7 +153,7 @@ 2E80 Suplemento de Radicais do CJK 2F00 Radicais Kangxi 2FF0 Caracteres de Descrição Ideográfica - 3000 Símbolos e Pontuação do CJK + 3000 Símbolos e Pontuações do CJK 3040 Hiragana 30A0 Katakana 3100 Bopomofo @@ -201,7 +201,7 @@ FB50 Formas A de Apresentação em Arábe FE00 Seletores de Variação FE10 Formas Verticais - FE20 Marcas Combinando Pela Metade + FE20 Marcas Combinantes do Meio FE30 Formas de Compatibilidade do CJK FE50 Variantes de Formas Pequenas FE70 Formas B de Apresentação em Arábe diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 17a2865..6fd8396 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -458,6 +458,7 @@ Opt-out ads Skip tutorials Tabs settings… + Hint: You can quickly switch between single / multiple columns by pinching in and out on lists Shown tabs Hidden tabs @@ -502,7 +503,7 @@ Copyright © 1991-2023 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. - UnicodePad 2.15.1 + UnicodePad 2.16.0 UnicodePad is licensed under the Apache License, Version2.0 https://github.com/Ryosuke839/UnicodePad \ No newline at end of file diff --git a/scripts/build_namedb.py b/scripts/build_namedb.py index d96649d..7e38468 100755 --- a/scripts/build_namedb.py +++ b/scripts/build_namedb.py @@ -31,40 +31,34 @@ def main(): print(ftp.login()) with sqlite3.connect('namedb') as con: cur = con.cursor() - cur.execute('CREATE TABLE name_table (id integer NOT NULL PRIMARY KEY, words text NOT NULL, name text NOT NULL, version integer NOT NULL, comment text, alias text, formal text, xref text, vari text, decomp text, compat text);') + cur.execute('CREATE TABLE name_table (id integer NOT NULL PRIMARY KEY, words text NOT NULL, name text NOT NULL, version integer NOT NULL, lines text);') characters = {} class OneCharacter: id = None name = None version = 0 - comment = [] - alias = [] - formal = [] - xref = [] - vari = [] - decomp = [] - compat = [] + words = [] + lines = [] def __init__(self, code, name, version): self.id = int(code, 16) self.name = name self.version = version - self.comment = [] - self.alias = [] - self.formal = [] - self.xref = [] - self.vari = [] - self.decomp = [] - self.compat = [] + self.words = [name] + self.lines = [] def update(self): nonlocal characters if self.id in characters: self.version = characters[self.id].version characters[self.id] = self + def append_line(self, line_type, line, is_word=False): + if is_word: + self.words.append(line.replace('\'', '\'\'')) + self.lines.append(line_type + ' ' + line.replace('\'', '\'\'')) def insert(self): nonlocal cur def list_to_str(l): return '\'' + '\n'.join(l) + '\'' if len(l) > 0 else 'NULL' - exp = f'INSERT INTO name_table (id, words, name, version, comment, alias, formal, xref, vari, decomp, compat) values ({self.id}, \'{" ".join([self.name] + self.alias + self.formal)}\', \'{self.name}\', {self.version}, {list_to_str(self.comment)}, {list_to_str(self.alias)}, {list_to_str(self.formal)}, {list_to_str(self.xref)}, {list_to_str(self.vari)}, {list_to_str(self.decomp)}, {list_to_str(self.compat)});' + exp = f'INSERT INTO name_table (id, words, name, version, lines) values ({self.id}, \'{" ".join(self.words)}\', \'{self.name}\', {self.version}, {list_to_str(self.lines)});' try: cur.execute(exp) except: @@ -78,9 +72,9 @@ def oneline(line): nonlocal current if len(line) == 0: return - elif line[0] in ['@', ';']: + elif line[0] in ['@', ';'] and not line.startswith('@+'): return - elif line[0] == '\t': + elif line[0] == '\t' or line.startswith('@+'): if current is None: return if len(line) < 3: @@ -89,19 +83,21 @@ def oneline(line): if line[1] == '\t': return if line[1] == '*': - current.comment.append(line[3:].replace('\'', '\'\'')) + current.append_line('*', line[3:]) + if line.startswith('@+'): + current.append_line('@', line[3:].lstrip('\t').lstrip('* ')) if line[1] == '=': - current.alias.append(line[3:].replace('\'', '\'\'')) + current.append_line('=', line[3:], True) if line[1] == '%': - current.formal.append(line[3:].replace('\'', '\'\'')) + current.append_line('%', line[3:], True) if line[1] == 'x': - current.xref.append((line.split(' ')[-1][:-1] if line[3] == '(' else line[3:]).lstrip('0').replace('\'', '\'\'')) + current.append_line('x', (line.split(' - ')[0][4:] + ' ' + line.split(' ')[-1][:-1] if line[3] == '(' else line[3:]).lstrip('0')) if line[1] == '~': - current.vari.append(' '.join(s.lstrip('0') for s in line[3:].split(' ')).replace('\'', '\'\'')) + current.append_line('~', line[3:]) if line[1] == ':': - current.decomp.append(' '.join(s.lstrip('0') for s in line[3:].split(' ') if re.match('^[0-9A-F]+$', s)).replace('\'', '\'\'')) + current.append_line(':', line[3:]) if line[1] == '#': - current.compat.append(' '.join(s.lstrip('0') for s in line[3:].split(' ') if re.match('^([0-9A-F]+|<.*>)$', s)).replace('\'', '\'\'')) + current.append_line('#', line[3:]) else: if current is not None: current.update() @@ -167,7 +163,7 @@ def emoji_line(line): cur.execute('CREATE TABLE emoji_table1510 (id text NOT NULL PRIMARY KEY, name text NOT NULL, version integer NOT NULL, grp text NOT NULL, subgrp text NOT NULL, tone integer NOT NULL, direction integer NOT NULL);') print(ftp.retrlines(f'RETR emoji-test.txt', emoji_line)) con.commit() - cur.execute('CREATE TABLE version_code as SELECT 59 as version;') + cur.execute('CREATE TABLE version_code as SELECT 60 as version;') con.commit() print('SELECT * FROM \'version_code\';') cur.execute('SELECT * FROM \'version_code\';')